51单片机连接NRF24L01的发送程序和接收程序

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接口,这是一个串行通信总线,我们可以简单的看下它的工作时序:

http://img00.hc360.com/edu/201102/201102171610495519.jpg

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视频,在升级版课程里。

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据