首页 > 代码库 > [51单片机] SPI nRF24L01无线 [可以放在2个单片机里实现通信]

[51单片机] SPI nRF24L01无线 [可以放在2个单片机里实现通信]

 

main.c

 1 #include<reg51.h>
 2 #include"2401.h"
 3 
 4 #define uint unsigned int
 5 #define uchar unsigned char
 6 
 7 sbit KEY8=P3^7;     //发送按键 
 8 sbit beep=P2^3;//喇叭 
 9 sbit LED6=P1^6;     ////接收到数据后的功能实现灯  
10 
11 void delay_ms(uint z)     //延时函数 
12 {
13     uint x,y;
14     for(x=z;x>0;x--)
15         for(y=110;y>0;y--);
16 }
17 void delayms(unsigned int x)
18 {
19     unsigned int i;
20     while(x--)
21         for(i=125;i>0;i--);
22 }
23 void main()
24 {
25      uchar Tx_Buf1[]={1};//发送的信息1 
26      uchar Rx_Buf[32];  //接收到的数据暂存器,最多32字节数据  
27      init_NRF24L01();
28      LED6=1;//初始灯6熄灭   
29 
30 
31     while(NRF24L01_Check())        //检查不到24l01则报警 
32     {
33         beep=0;
34         delayms(200);
35         beep=1;
36         delayms(200);
37     }
38     while(1)
39     {    
40         RX_Mode();//接收模式  
41         while(!nRF24L01_RxPacket(Rx_Buf)) //等待接收数据 ,返回1则接收到数据 ,在等待接收数据期间,可以随时变成发送模式  
42         {
43             if(KEY8==0)     //按了按键8   则变成发送模式,发送对应数据,发送完后变成接收模式 
44             {    
45                 delay_ms(5);//消抖动 
46                 if(KEY8==0)
47                 {
48                      while(!KEY8);
49                     TX_Mode();     //发送模式 
50                     nRF24L01_TxPacket(Tx_Buf1);    // 发送命令数据
51                       LED6=0;
52                     delay_ms(300);
53                     LED6=1;
54                     delay_ms(300);            //发送后LED6闪一下 
55                     break;    //退出最近的循环,从而变回接收模式,这句关键
56                  }
57                 
58              }
59          }
60          if(Rx_Buf[0]==1)       //若接收到对应的数据则实现对应功能 
61          {
62              Rx_Buf[0]=0;//清空数据 
63                LED6=0;
64              delay_ms(300);
65              LED6=1;
66              delay_ms(300);//接收到数据 后闪烁      
67          }         
68     }
69 }
  1 #ifndef __NRF24L01_H__
  2 #define __NRF24L01_H__
  3 #include<reg51.h>
  4 #define uchar unsigned char
  5 #define uint unsigned int
  6 
  7 sbit    CE        =P1^0;
  8 sbit    CSN        =P1^1;
  9 sbit    SCK        =P1^2;
 10 sbit     MOSI    =P1^3;
 11 sbit     MISO    =P1^4;
 12 sbit    IRQ        =P1^5;
 13 
 14 //uchar TxBuf[20]={"1234567890abcdefghij"};
 15 #define TX_ADR_WIDTH    5       // 5 uints TX address width
 16 #define RX_ADR_WIDTH    5       // 5 uints RX address width
 17 #define TX_PLOAD_WIDTH  32      // 32 uints TX payload
 18 #define RX_PLOAD_WIDTH  32      // 32 uints TX payload
 19 uchar  TX_ADDRESS[TX_ADR_WIDTH]= {0xE7,0xE7,0xE7,0xE7,0xE7};    //本地地址
 20 uchar  RX_ADDRESS[RX_ADR_WIDTH]= {0xE7,0xE7,0xE7,0xE7,0xE7};    //接收地址
 21 ///***************************************NRF24L01寄存器指令*******************************************************
 22 #define READ_REG        0x00      // 读寄存器指令
 23 #define WRITE_REG       0x20     // 写寄存器指令
 24 #define RD_RX_PLOAD     0x61      // 读取接收数据指令
 25 #define WR_TX_PLOAD     0xA0      // 写待发数据指令
 26 #define FLUSH_TX        0xE1     // 冲洗发送 FIFO指令
 27 #define FLUSH_RX        0xE2      // 冲洗接收 FIFO指令
 28 #define REUSE_TX_PL     0xE3      // 定义重复装载数据指令
 29 #define NOP             0xFF      // 保留
 30 ///*************************************SPI(nRF24L01)寄存器地址****************************************************
 31 #define CONFIG          0x00  // 配置收发状态,CRC校验模式以及收发状态响应方式
 32 #define EN_AA           0x01  // 自动应答功能设置
 33 #define EN_RXADDR       0x02  // 可用信道设置
 34 #define SETUP_AW        0x03  // 收发地址宽度设置
 35 #define SETUP_RETR      0x04  // 自动重发功能设置
 36 #define RF_CH           0x05  // 工作频率设置
 37 #define RF_SETUP        0x06  // 发射速率、功耗功能设置
 38 #define NRFRegSTATUS    0x07  // 状态寄存器
 39 #define OBSERVE_TX      0x08  // 发送监测功能
 40 #define CD              0x09  // 地址检测           
 41 #define RX_ADDR_P0      0x0A  // 频道0接收数据地址
 42 #define RX_ADDR_P1      0x0B  // 频道1接收数据地址
 43 #define RX_ADDR_P2      0x0C  // 频道2接收数据地址
 44 #define RX_ADDR_P3      0x0D  // 频道3接收数据地址
 45 #define RX_ADDR_P4      0x0E  // 频道4接收数据地址
 46 #define RX_ADDR_P5      0x0F  // 频道5接收数据地址
 47 #define TX_ADDR         0x10  // 发送地址寄存器
 48 #define RX_PW_P0        0x11  // 接收频道0接收数据长度
 49 #define RX_PW_P1        0x12  // 接收频道1接收数据长度
 50 #define RX_PW_P2        0x13  // 接收频道2接收数据长度
 51 #define RX_PW_P3        0x14  // 接收频道3接收数据长度
 52 #define RX_PW_P4        0x15  // 接收频道4接收数据长度
 53 #define RX_PW_P5        0x16  // 接收频道5接收数据长度
 54 #define FIFO_STATUS     0x17  // FIFO栈入栈出状态寄存器设置
 55 ///*****************************子函数集*********************************************************
 56 uchar NRF24SPI_Send_Byte(uchar dat);
 57 uchar SPI_WR_Reg(uchar reg, uchar value);
 58 uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar Len);
 59 uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar Len);
 60 uchar nRF24L01_RxPacket(unsigned char* rx_buf);
 61 void nRF24L01_TxPacket(unsigned char * tx_buf);
 62 uchar SPI_RD_Reg(uchar reg);
 63 void init_NRF24L01(void);
 64 void TX_Mode(void);
 65 void RX_Mode(void);
 66 void NRF_Send(void);
 67 uchar NRF24L01_Check(void);
 68 ///*************************************************************************************
 69 uchar NRF24SPI_Send_Byte(uchar dat)
 70 {
 71   uchar i;
 72    for (i = 0; i < 8; i++) // output 8-bit
 73    {
 74       //发送1位数据
 75       if (dat & 0x80)         // output ‘uchar‘, MSB to MOSI
 76       {
 77          MOSI = 1;
 78       }
 79       else
 80       {
 81          MOSI = 0;
 82       }
 83 
 84       dat <<= 1;           // shift next bit into MSB..
 85       
 86       //读取1位数据
 87       SCK = 1;                      // Set SCK high..
 88 
 89       if (MISO)
 90       {
 91          dat |= 1;
 92       }             // capture current MISO bit
 93       else
 94       {
 95          dat &= 0xFE;
 96       }
 97       SCK = 0;                    // ..then set SCK low again
 98    }
 99    
100    return(dat);                  // return read uchar
101 }
102 
103 void Delay_n10us(uint n)       //延时n个10us
104 {
105    for(;n>0;n--)
106    {
107         unsigned char a,b;
108      for(b=1;b>0;b--)
109          for(a=2;a>0;a--);
110    }
111 }
112 ///****************************************************************************************
113 ///*NRF24L01检测是否存在
114 ///***************************************************************************************/
115 uchar NRF24L01_Check(void)
116 {
117     uchar bu[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
118     uchar bu1[5];
119     uchar i;        
120     SPI_Write_Buf(WRITE_REG+TX_ADDR,bu,5);//写入5个字节的地址.    
121     SPI_Read_Buf(TX_ADDR,bu1,5);              //读出写入的地址      
122     for(i=0;i<5;i++)if(bu1[i]!=0XA5)break;                       
123     if(i!=5)return 1;                               //NRF24L01不在位    
124     return 0;                                        //NRF24L01在位
125 }          
126 ///****************************************************************************************
127 ///*NRF24L01初始化
128 ///***************************************************************************************/
129 void init_NRF24L01(void)
130 {
131    uchar buf[5]={0};
132    Delay_n10us(10);
133    CE = 0;    // chip enable
134    CSN= 0;    // Spi disable 
135   
136   SPI_Read_Buf(TX_ADDR, buf, TX_ADR_WIDTH);//debug 测试原来的本地地址:复位值是:0xE7 0xE7 0xE7 0xE7 0xE7
137   
138 //    SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);    // 写本地地址    
139 //    SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址
140 
141 //    
142 //    SPI_WR_Reg(WRITE_REG + EN_AA, 0x01);      //  频道0自动    ACK应答允许    
143 //    SPI_WR_Reg(WRITE_REG + EN_RXADDR, 0x01);  //  允许接收地址只有频道0,如果需要多频道可以参考Page21  
144 //    SPI_WR_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 设置自动重发时间和次数:500us + 86us, 10 retrans...
145 //    SPI_WR_Reg(WRITE_REG + RF_CH, 22);        //   设置信道工作为2.4GHZ,收发必须一致
146 //    SPI_WR_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节
147 //    SPI_WR_Reg(WRITE_REG + RF_SETUP, 0x07);           //设置发射速率为1MHZ,发射功率为最大值0dB
148 //  
149 //  SPI_RD_Reg(WRITE_REG + EN_AA);
150 //  SPI_RD_Reg(WRITE_REG + EN_RXADDR);
151 //  SPI_RD_Reg(WRITE_REG + RF_CH);
152 //  SPI_RD_Reg(WRITE_REG + RX_PW_P0);
153 //  SPI_RD_Reg(WRITE_REG + RF_SETUP);
154 }
155 ///****************************************************************************************************
156 ///*函数:uchar SPI_Read(uchar reg)
157 ///*功能:NRF24L01的SPI时序
158 ///****************************************************************************************************/
159 uchar SPI_RD_Reg(uchar reg)
160 {
161     uchar reg_val;
162     
163     CSN = 0;                // CSN low, initialize SPI communication...
164     NRF24SPI_Send_Byte(reg);            // Select register to read from..
165     reg_val = NRF24SPI_Send_Byte(0);    // ..then read registervalue
166     CSN = 1;                // CSN high, terminate SPI communication
167     
168     return(reg_val);        // return register value
169 }
170 //****************************************************************************************************/
171 //*功能:NRF24L01读写寄存器函数
172 //****************************************************************************************************/
173 uchar SPI_WR_Reg(uchar reg, uchar value)
174 {
175     uchar status;
176     
177     CSN = 0;                   // CSN low, init SPI transaction
178     status = NRF24SPI_Send_Byte(reg);// select register
179     NRF24SPI_Send_Byte(value);             // ..and write value to it..
180     CSN = 1;                   // CSN high again
181     
182     return(status);            // return nRF24L01 status uchar
183 }
184 ///****************************************************************************************************/
185 //*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar Len)
186 //*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数
187 //****************************************************************************************************/
188 uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar Len)
189 {
190     uint status,i;
191     
192     CSN = 0;                            // Set CSN low, init SPI tranaction
193     status = NRF24SPI_Send_Byte(reg);               // Select register to write to and read status uchar
194     
195   for(i=0;i<Len;i++)
196   {
197      pBuf[i] = NRF24SPI_Send_Byte(0);
198   }
199     
200     CSN = 1;                           
201     
202     return(status);                    // return nRF24L01 status uchar
203 }
204 //*********************************************************************************************************
205 //*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar Len)
206 //*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数
207 //*********************************************************************************************************/
208 uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar Len)
209 {
210     uint status,i;
211     
212     CSN = 0;            //SPI使能       
213     status = NRF24SPI_Send_Byte(reg);   
214     for(i=0; i<Len; i++) //
215     {
216        NRF24SPI_Send_Byte(*pBuf);
217          pBuf ++;
218     }
219     CSN = 1;           //关闭SPI
220     return(status);    // 
221 }
222 
223 //****************************************************************************************************/
224 //*函数:void SetRX_Mode(void)
225 //*功能:数据接收配置 
226 //****************************************************************************************************/
227 void RX_Mode(void)
228 {
229     uchar buf[5]={0};
230     CE = 0;
231     
232     SPI_Read_Buf(TX_ADDR, buf, TX_ADR_WIDTH);//debug 测试原来的本地地址:复位值是:0xE7 0xE7 0xE7 0xE7 0xE7
233     //SPI_WR_Reg(WRITE_REG + CONFIG, 0x03);//SPI_WR_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收发完成中断响应,16位CRC    ,主接收
234     
235     //SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);    // 写本地地址    
236     SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址
237     
238     SPI_WR_Reg(WRITE_REG + EN_AA, 0);//0x01);      //  频道0自动    ACK应答允许    
239     SPI_WR_Reg(WRITE_REG + EN_RXADDR,0x01);  //  允许接收地址只有频道0,如果需要多频道可以参考Page21  
240     SPI_WR_Reg(WRITE_REG + SETUP_RETR,0x1a); // 设置自动重发时间和次数:500us + 86us, 10 retrans...
241     SPI_WR_Reg(WRITE_REG + RF_CH, 40);        //   设置信道工作为2.4GHZ,收发必须一致
242     SPI_WR_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节
243     SPI_WR_Reg(WRITE_REG + RF_SETUP, 0x0F);           //设置发射速率为2MHZ,发射功率为最大值0dB
244     
245     SPI_WR_Reg(WRITE_REG + CONFIG, 0x0F);//0x0F);    
246     CE = 1; 
247     Delay_n10us(20); //200us
248 }
249 //******************************************************************************************************/
250 //*函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)
251 //*功能:数据读取后放如rx_buf接收缓冲区中
252 //******************************************************************************************************/
253 uchar nRF24L01_RxPacket(unsigned char* rx_buf)
254 {
255     uchar flag=0;
256     uchar status;
257      
258     status=SPI_RD_Reg(NRFRegSTATUS);    // 读取状态寄存其来判断数据接收状况
259     
260     if(status & 0x40)                // 判断是否接收到数据
261     {
262        CE = 0;             //SPI使能
263          SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO buffer
264          flag =1;            //读取数据完成标志
265     }
266     SPI_WR_Reg(WRITE_REG+NRFRegSTATUS, status);   //接收到数据后RX_DR,TX_DS,MAX_RT都置高为1,通过写1来清楚中断标志
267     return flag;
268 }
269 void TX_Mode(void)
270 {
271     CE = 0;
272     //SPI_WR_Reg(WRITE_REG + CONFIG, 0x02);   //0x0E         // IRQ收发完成中断响应,16位CRC,主发送
273     
274     SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);    // 写本地地址    
275     SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址
276     
277     SPI_WR_Reg(WRITE_REG + EN_AA, 0);//0x01);      //  频道0自动    ACK应答允许    
278     SPI_WR_Reg(WRITE_REG + EN_RXADDR,0);// 0x01);  //  允许接收地址只有频道0,如果需要多频道可以参考Page21  
279     SPI_WR_Reg(WRITE_REG + SETUP_RETR, 0);//0x1a); // 设置自动重发时间和次数:500us + 86us, 10 retrans...
280     SPI_WR_Reg(WRITE_REG + RF_CH, 40);        //   设置信道工作为2.4GHZ,收发必须一致
281     SPI_WR_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节
282     SPI_WR_Reg(WRITE_REG + RF_SETUP, 0x0F);           //设置发射速率为2MHZ,发射功率为最大值0dB
283 
284     SPI_WR_Reg(WRITE_REG + CONFIG, 0x0E);
285     CE = 1;
286 }
287 //***********************************************************************************************************
288 //*函数:void nRF24L01_TxPacket(unsigned char * tx_buf)
289 //*功能:发送 tx_buf中数据
290 //**********************************************************************************************************/
291 void nRF24L01_TxPacket(unsigned char * tx_buf)
292 {
293     CE = 0;            //StandBy I模式    
294     SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载接收端地址
295     SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH);              // 装载数据    
296 //    SPI_WR_Reg(WRITE_REG + CONFIG, 0x0e);            // IRQ收发完成中断响应,16位CRC,主发送
297     CE = 1;         //置高CE,激发数据发送
298 }
299 
300 
301 ///************************************主函数************************************************************
302 //void NRF_Send(void)
303 //{
304 //  //static uint counter=0;
305 //  static uchar flag=0;  
306 //   
307 //   //TX_Mode();
308 //   
309 //   //IntervalTimems(100);
310 //   if(flag==0)
311 //   {
312 //      flag=1;
313 //      //memcpy(TxBuf, "1234567890abcdefghij", 20);
314 //      nRF24L01_TxPacket(TxBuf);
315 //   }
316 //   else
317 //   {
318 //      flag=0;
319 //      //memcpy(TxBuf, "abcdefghij1234567890", 20);
320 //      nRF24L01_TxPacket(TxBuf);
321 //   }
322 //   
323 //}
324 
325 #endif   /*__NRF24L01_H__ */
2401.h