NRF24L01做为一款2.4GHZ的无线收发模块,在很多工程师眼里,还是比较受欢迎的。这里我们简单说下,使用STC89C52单片机,如何连接NRF24L01,如何编写程序。
要注意的地方:51单片机作为一个编程芯片,虽然简单,但仍需一定的基础。所以,如果是没有单片机编程基础的人,看这篇文章,基本是看不懂的。
那,怎么算有基础?
会写点亮LED的程序,会写检测按键的程序,会写驱动数码管的程序,会用单片机IO模拟IIC总线,会用单片机IO模拟SPI总线。
注意,上面说的这些操作,是要求你真的手动从0开始,一行代码一行代码的写过。如果只是跑个例程,就算了。
首先看如何接线,模块外形如下:
可以看到,模块右侧是有一组2X4的双排针的,分别是什么信号?再看下图:
是不是清楚多了?
这个图是哪来的?
你在某宝上,任意一家卖这个模块的店铺里,都能找到卖家提供的资料。资料里会有各种说明。如果卖家不提供,你直接换一家就行了。
这里使用的是STC89C52的P1管脚,具体定义如下:
sbit CE = P1^0;
sbit CSN= P1^1;
sbit SCK= P1^2;
sbit MOSI= P1^3;
sbit MISO= P1^4;
sbit IRQ = P1^5;
主要看前五个,第六个是中断,一般用的很少。
第二,通信协议。NRF24L01模块上面只有一个SPI接口,这是一个串行通信总线,我们可以简单的看下它的工作时序:
SS是片选信号;
SCLK是时钟信号;
MOSI是主(master)出(out)从(slave)入(in)。
MISO是主入从出。
主,指的是主机。一般,如果通信双方一个是单片机,一个是NRF24L01模块,那么单片机做主机。如果双方都是单片机,那么谁都可以做主机。主机主动发起通信,提供时钟,从机被动的提供数据。
第三,如何工作。这部分说简单也简单,说复杂也复杂。说简单是因为,相关的工作配置,都在NRF24L01的数据手册里,看相关的寄存器就可以了,而且网上已经有人写好相关的驱动程序,直接调用就行。
说复杂是因为,数据手册很长,内容很多,理解起来需要花时间。如果是没基础的人,基本就别想看懂了。
这里贴出通信过程中的主要的程序部分,详细的可以下载完整工程看。
发送部分:
void main(void)
{
unsigned char sta;
delay_ms(1000);
init_io();
TX_Mode();
while(1)
{
CE = 0;
SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH);
CE = 1;
while(IRQ);
sta=SPI_Read(STATUS);
SPI_RW_Reg(FLUSH_TX, 0xff);
SPI_RW_Reg(WRITE_REG+STATUS,sta);
delay_ms(1000);
}
}
void TX_Mode(void)
{
CE = 0;
SPI_RW_Reg(FLUSH_TX, 0xff);
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // Writes TX_Address to nRF24L01
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // RX_Addr0 same as TX_Adr for Auto.Ack
SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH);
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // Enable Auto.Ack:Pipe0
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // Enable Pipe0
SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 500us + 86us, 10 retrans...
SPI_RW_Reg(WRITE_REG + RF_CH, 40); // Select RF channel 40
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // TX_PWR:0dBm, Datarate:2Mbps, LNA:HCURR
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // Set PWR_UP bit, enable CRC(2 bytes) & Prim:TX. MAX_RT & TX_DS enabled..
CE=1;
}
接收部分:
void main(void)
{
uchar sta;
init_io();
delay_ms(1000);
RX_Mode();
while(1)
{
sta=SPI_Read(STATUS);
if((sta & 0x40) != 0)
{
SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);
}
if((rx_buf[0]==0x23) && (rx_buf[1]==0x23) && (rx_buf[2]==0x23) && (rx_buf[3]==0x23) && (rx_buf[4]==0x23))
{
LED = ~LED;
}
SPI_RW_Reg(FLUSH_RX,0xff);
SPI_RW_Reg(WRITE_REG+STATUS,sta);
delay_ms(1000);
}
}
void RX_Mode(void)
{
CE = 0;
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // Writes TX_Address to nRF24L01
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // Use the same address on the RX device as the TX device
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // Enable Auto.Ack:Pipe0
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // Enable Pipe0
SPI_RW_Reg(WRITE_REG + RF_CH, 40); // Select RF channel 40
SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // Select same RX payload width as TX Payload width
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // TX_PWR:0dBm, Datarate:2Mbps, LNA:HCURR
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // Set PWR_UP bit, enable CRC(2 bytes) & Prim:RX. RX_DR enabled..
CE = 1; // Set CE pin high to enable RX device
}
调试这两段程序,你需要两片单片机,外加一个LED。保存、编译、下载、上电。可以看到P2.0管脚的LED正在闪烁!
打完手工!
需要完整代码的,可以关注公众号:单片机爱好者,回复关键词:51视频,在升级版课程里。