×
单片机 > 单片机程序设计 > 详情

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

发布时间:2020-06-06 发布时间:
|

main.c

 1 #include

 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 }

2401.h

  1 #ifndef __NRF24L01_H__

  2 #define __NRF24L01_H__

  3 #include

  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

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

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__ */




『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
可升级和可配置的PSoC62系列MCU平台架构