找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3338|回复: 3
收起左侧

nRF24L01硬件SPI无线双向通讯单片机程序

[复制链接]
ID:386826 发表于 2019-1-10 22:00 | 显示全部楼层 |阅读模式
stc实例无线双向通讯代码
nRF24L01双向通讯实验步骤:
1:将TXRX程序下载到两块EasySTC15开发板(开发板A和开发板B)中。
2:按下开发板A上的按键S3,可以看到开发板B上的RGB指示灯中的红灯状态翻转。
2:按下开发板B上的按键S3,可以看到开发板A上的RGB指示灯中的红灯状态翻转。

单片机源程序如下:
  1. /****************************************Copyright (c)****************************************************
  2. **                                       
  3. **                                 
  4. **
  5. **--------------File Info---------------------------------------------------------------------------------
  6. ** File name:                       
  7. ** Last modified Date:         
  8. ** Last Version:                  
  9. ** Descriptions:                                                       
  10. **--------------------------------------------------------------------------------------------------------
  11. ** Created by:                        FiYu
  12. ** Created date:                2016-3-5
  13. ** Version:                            1.0
  14. ** Descriptions:                nRF24L01无线双向通讯(硬件SPI)                                       
  15. **--------------------------------------------------------------------------------------------------------
  16. ** Modified by:                        FiYu
  17. ** Modified date:               
  18. ** Version:                               
  19. ** Descriptions:               
  20. ** Rechecked by:                       
  21. **********************************************************************************************************/
  22. /****-----参考:宏晶科技的有关资料及程序-------***********/
  23. #include <STC15F2K60S2.h>

  24. #define  uint unsigned int  
  25. #define  uchar unsigned char

  26. //无线收发地址宽度(字节数)
  27. #define TX_ADDR_WIDTH 5
  28. #define RX_ADDR_WIDTH 5

  29. //无线收发数据长度(字节数)
  30. #define TX_PLOAD_WIDTH 1
  31. #define RX_PLOAD_WIDTH 1

  32. #define SPIF 0x80 //SPSTAT.7
  33. #define WCOL 0x40 //SPSTAT.6
  34. #define SSIG 0x80 //SPCTL.7
  35. #define SPEN 0x40 //SPCTL.6
  36. #define DORD 0x20 //SPCTL.5
  37. #define MSTR 0x10 //SPCTL.4
  38. #define CPOL 0x08 //SPCTL.3
  39. #define CPHA 0x04 //SPCTL.2
  40. #define SPDHH 0x00 //CPU_CLK/4
  41. #define SPDH 0x01 //CPU_CLK/8
  42. #define SPDL 0x02 //CPU_CLK/16
  43. #define SPDLL 0x03 //CPU_CLK/32

  44. /****************************************************************************************************/
  45. //NRF24L01寄存器操作命令
  46. #define SPI_READ_REG    0x00  //读配置寄存器,低5位为寄存器地址
  47. #define SPI_WRITE_REG   0x20  //写配置寄存器,低5位为寄存器地址
  48. #define RD_RX_PLOAD     0x61  //读RX有效数据,1~32字节
  49. #define WR_TX_PLOAD     0xA0  //写TX有效数据,1~32字节
  50. #define FLUSH_TX        0xE1  //清除TX FIFO寄存器.发射模式下用
  51. #define FLUSH_RX        0xE2  //清除RX FIFO寄存器.接收模式下用
  52. #define REUSE_TX_PL     0xE3  //重新使用上一包数据,CE为高,数据包被不断发送.
  53. #define NOP             0xFF  //空操作,可以用来读状态寄存器         
  54. //SPI(NRF24L01)寄存器地址
  55. #define CONFIG          0x00  //配置寄存器地址;bit0:1接收模式,0发射模式;bit1:电选择;bit2:CRC模式;bit3:CRC使能;
  56.                               //bit4:中断MAX_RT(达到最大重发次数中断)使能;bit5:中断TX_DS使能;bit6:中断RX_DR使能
  57. #define EN_AA           0x01  //使能自动应答功能  bit0~5,对应通道0~5
  58. #define EN_RXADDR       0x02  //接收地址允许,bit0~5,对应通道0~5
  59. #define SETUP_AW        0x03  //设置地址宽度(所有数据通道):bit1,0:00,3字节;01,4字节;02,5字节;
  60. #define SETUP_RETR      0x04  //建立自动重发;bit3:0,自动重发计数器;bit7:4,自动重发延时 250*x+86us
  61. #define RF_CH           0x05  //RF通道,bit6:0,工作通道频率;
  62. #define RF_SETUP        0x06  //RF寄存器;bit3:传输速率(0:1Mbps,1:2Mbps);bit2:1,发射功率;bit0:低噪声放大器增益
  63. #define STATUS          0x07  //状态寄存器;bit0:TX FIFO满标志;bit3:1,接收数据通道号(最大:6);bit4,达到最多次重发
  64.                               //bit5:数据发送完成中断;bit6:接收数据中断;
  65. #define MAX_TX              0x10    //达到最大发送次数中断
  66. #define TX_OK               0x20    //TX发送完成中断
  67. #define RX_OK               0x40    //接收到数据中断

  68. #define OBSERVE_TX      0x08  //发送检测寄存器,bit7:4,数据包丢失计数器;bit3:0,重发计数器
  69. #define CD              0x09  //载波检测寄存器,bit0,载波检测;
  70. #define RX_ADDR_P0      0x0A  //数据通道0接收地址,最大长度5个字节,低字节在前
  71. #define RX_ADDR_P1      0x0B  //数据通道1接收地址,最大长度5个字节,低字节在前
  72. #define RX_ADDR_P2      0x0C  //数据通道2接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;
  73. #define RX_ADDR_P3      0x0D  //数据通道3接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;
  74. #define RX_ADDR_P4      0x0E  //数据通道4接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;
  75. #define RX_ADDR_P5      0x0F  //数据通道5接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;
  76. #define TX_ADDR         0x10  //发送地址(低字节在前),ShockBurstTM模式下,RX_ADDR_P0与此地址相等
  77. #define RX_PW_P0        0x11  //接收数据通道0有效数据宽度(1~32字节),设置为0则非法
  78. #define RX_PW_P1        0x12  //接收数据通道1有效数据宽度(1~32字节),设置为0则非法
  79. #define RX_PW_P2        0x13  //接收数据通道2有效数据宽度(1~32字节),设置为0则非法
  80. #define RX_PW_P3        0x14  //接收数据通道3有效数据宽度(1~32字节),设置为0则非法
  81. #define RX_PW_P4        0x15  //接收数据通道4有效数据宽度(1~32字节),设置为0则非法
  82. #define RX_PW_P5        0x16  //接收数据通道5有效数据宽度(1~32字节),设置为0则非法
  83. #define FIFO_STATUS     0x17  //FIFO状态寄存器;bit0,RX FIFO寄存器空标志;bit1,RX FIFO满标志;bit2,3,保留
  84.                               //bit4,TX FIFO空标志;bit5,TX FIFO满标志;bit6,1,循环发送上一数据包.0,不循环;
  85.                                                                                                                        
  86. #define CE_LOW        en=0
  87. #define CE_HIGH       en=1
  88. #define CS_LOW        SPI_CS=0
  89. #define CS_HIGH       SPI_CS=1
  90.                                                                                                                        
  91. const uchar TX_ADDRESS[TX_ADDR_WIDTH]={0xE1,0xE2,0xE3,0xE4,0xE5}; //发送地址
  92. const uchar RX_ADDRESS[RX_ADDR_WIDTH]={0xE1,0xE2,0xE3,0xE4,0xE5}; //接收地址       
  93. uchar  RxPayload[32];   //无线接收缓存
  94. uchar  TxPayload[32];   //无线发送缓存

  95. /**********************
  96. 引脚别名定义
  97. ***********************/       
  98. sbit IRQ=P3^3;        //中断
  99. sbit en=P3^2;         //使能控制
  100. sbit SPI_CS=P1^2;     //片选

  101. sbit KEY=P0^4;            //用户按键S3用IO口P04
  102. sbit LED_B=P0^5;   //三色指示灯之蓝色LED用IO口P05
  103. sbit LED_R=P0^6;   //三色指示灯之红色LED用IO口P06
  104. /**************************************
  105. 功能描述:延时函数
  106. 入口参数:uint x ,该值为1时,延时1ms
  107. 返回值:无
  108. ***************************************/
  109. void delay_ms(uint x)
  110. {  
  111.         uint j,i;   
  112.         for(j=0;j<x;j++)   
  113.         {   
  114.                 for(i=0;i<1100;i++);   
  115.         }  
  116. }

  117. /***************************************************************************
  118. * 描  述 : 初始化SPI
  119. * 入  参 : 无
  120. * 返回值 : 无
  121. **************************************************************************/
  122. void InitSPI(void)
  123. {
  124.   SPDAT = 0; //初始化SPI数据
  125.   SPSTAT = SPIF | WCOL; //清除SPI状态位
  126.   SPCTL = SPEN | MSTR | SSIG; //主机模式
  127. }

  128. /***************************************************************************
  129. * 描  述 : 模拟SPI读写数据函数,读写一个字节
  130. * 入  参 : 写入的数据
  131. * 返回值 : 读取的数据
  132. **************************************************************************/
  133. uchar SPI_RW(uchar byte)
  134. {
  135.   SPDAT = byte; //触发SPI发送数据
  136.   while (!(SPSTAT & SPIF)); //等待发送完成
  137.   SPSTAT = SPIF | WCOL; //清除SPI状态位
  138.   return SPDAT; //返回SPI数据
  139. }

  140. /***************************************************************************
  141. * 描  述 : NRF24L01寄存器写函数
  142. * 入  参 : regaddr:要写的寄存器地址;data:写入到寄存器的数据
  143. * 返回值 : 读取的状态值
  144. **************************************************************************/
  145. uchar NRF24L01_Write_Reg(uchar regaddr,uchar dat)
  146. {
  147.         uchar status;       
  148.        
  149.   CS_LOW;  
  150.         status =SPI_RW(regaddr);
  151.   SPI_RW(dat);             //写入寄存器的值
  152.   CS_HIGH;              //禁止SPI传输       
  153.   return(status);                //返回状态值
  154. }

  155. /***************************************************************************
  156. * 描  述 : NRF24L01寄存器读函数
  157. * 入  参 : regaddr:要读取的寄存器地址
  158. * 返回值 : 读取的寄存器的值
  159. **************************************************************************/
  160. uchar NRF24L01_Read_Reg(uchar regaddr)
  161. {
  162.         uchar reg_val;          
  163.   
  164.         CS_LOW;                          //使能SPI传输       
  165.         SPI_RW(regaddr);
  166.         reg_val=SPI_RW(0XFF);
  167.   CS_HIGH;                         //禁止SPI传输               
  168.   return(reg_val);                 //返回读取的值
  169. }       
  170. /***************************************************************************
  171. * 描  述 : 从指定地址读出指定长度的数据
  172. * 入  参 : pBuf:读出数据的存放地址;datlen:读出的数据字节数
  173. * 返回值 : 读取的寄存器的值
  174. **************************************************************************/
  175. uchar NRF24L01_Read_Buf(uchar regaddr,uchar *pBuf,uchar datlen)
  176. {
  177.         uchar status,u8_ctr;               
  178.   CS_LOW;                               //使能SPI传输
  179.         status=SPI_RW(regaddr);
  180.         for(u8_ctr=0;u8_ctr<datlen;u8_ctr++)
  181.         {
  182.                 pBuf[u8_ctr]=SPI_RW(0XFF);//读出数据
  183.         }
  184.   CS_HIGH;                              //关闭SPI传输

  185.   return status;                        //返回读到的状态值
  186. }
  187. /***************************************************************************
  188. * 描  述 : 向指定地址写入指定长度的数据
  189. * 入  参 : pBuf:读出数据的存放地址;datlen:读出的数据字节数
  190. * 返回值 : 读取的状态寄存器值
  191. **************************************************************************/
  192. uchar NRF24L01_Write_Buf(uchar regaddr, uchar *pBuf, uchar datalen)
  193. {
  194.         uchar status,u8_ctr;            
  195.         CS_LOW;                                              //使能SPI传输
  196.         status = SPI_RW(regaddr);  
  197. for(u8_ctr=0; u8_ctr<datalen; u8_ctr++)
  198. {
  199.         SPI_RW(*pBuf++); //写入数据               
  200. }
  201.   CS_HIGH;                                             //关闭SPI传输
  202.   return status;                                       //返回读到的状态值
  203. }       
  204. /***************************************************************************
  205. * 描  述 : NRF24L01初始化函数,初始化连接NRF24L01模块的管脚,调用SPI初始化函数
  206. *          完成和NRF24L01模块通讯的SPI总线的初始化
  207. * 入  参 : 无
  208. * 返回值 : 无
  209. **************************************************************************/
  210. void Init_NRF24L01(void)
  211. {       
  212.         delay_ms(2);
  213.         LED_B=1;
  214.         CE_LOW;                                         //使能NRF24L01
  215.         CS_HIGH;                                  //SPI片选取消
  216.         InitSPI();
  217. }
  218. /***************************************************************************
  219. * 描  述 : 启动NRF24L01发送一次数据
  220. * 入  参 : buf:待发送数据首地址
  221. * 返回值 : 发送完成状况
  222. **************************************************************************/
  223. uchar NRF24L01_TxPacket(uchar *buf)
  224. {
  225.         uchar state,retVal = 0xff;   
  226.        
  227.         CE_LOW;
  228.         //写TX节点地址
  229.         NRF24L01_Write_Reg(SPI_WRITE_REG+CONFIG,0x0e);
  230.   NRF24L01_Write_Buf(SPI_WRITE_REG+TX_ADDR,(uchar*)TX_ADDRESS,TX_ADDR_WIDTH);  
  231.   NRF24L01_Write_Buf(WR_TX_PLOAD,buf,TX_PLOAD_WIDTH);  //写数据到TX BUF
  232.         CE_HIGH;                                             //启动发送          
  233.         while(IRQ!=0);                                       //等待发送完成
  234.         state=NRF24L01_Read_Reg(STATUS);                     //读取状态寄存器的值          
  235.         NRF24L01_Write_Reg(SPI_WRITE_REG+STATUS,state);      //清除TX_DS或MAX_RT中断标志
  236.         if(state&MAX_TX)                                     //达到最大重发次数
  237.         {
  238.                 NRF24L01_Write_Reg(FLUSH_TX,0xff);                 //清除TX FIFO寄存器
  239.                 retVal = MAX_TX;
  240.         }
  241.         if(state&TX_OK)                                      //发送完成
  242.         {
  243.                 retVal = TX_OK;
  244.         }
  245.         CE_LOW;
  246.         NRF24L01_Write_Reg(SPI_WRITE_REG+CONFIG, 0x0f);
  247.         CE_HIGH;
  248.         return retVal;                                         //其他原因发送失败
  249. }
  250. /***************************************************************************
  251. * 描  述 : 启动NRF24L01读取一次数据
  252. * 入  参 : buf:待发送数据首地址
  253. * 返回值 : RX_OK:接收到数据;0:未接收到数据
  254. **************************************************************************/
  255. uchar NRF24L01_RxPacket(uchar *buf)
  256. {
  257.         uchar state;                    
  258.        
  259.         state=NRF24L01_Read_Reg(STATUS);                //读取状态寄存器的值             
  260.         NRF24L01_Write_Reg(SPI_WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中断标志
  261.         if(state&RX_OK)                                    //接收到数据
  262.         {
  263.                 NRF24L01_Read_Buf(RD_RX_PLOAD,buf,RX_PLOAD_WIDTH);//读取数据
  264.                 NRF24L01_Write_Reg(FLUSH_RX,0xff);            //清除RX FIFO寄存器
  265.                 return RX_OK;
  266.         }          
  267.         return 0;                                           //没收到任何数据
  268. }
  269. /***************************************************************************
  270. * 描  述 : 初始化NRF24L01到RX模式,配置相关参数,CE变高后,即进入RX模式
  271. * 入  参 : 无
  272. * 返回值 : 无
  273. **************************************************************************/
  274. void Set_RxMode(void)
  275. {
  276.         CE_LOW;          
  277.         // Delay_1ms(20);
  278.   //写RX节点地址
  279.   NRF24L01_Write_Buf(SPI_WRITE_REG+RX_ADDR_P0,(uchar*)RX_ADDRESS,RX_ADDR_WIDTH);

  280.   //关闭通道0的自动应答   
  281.   NRF24L01_Write_Reg(SPI_WRITE_REG+EN_AA,0x00);   
  282.   //使能通道0的接收地址           
  283.   NRF24L01_Write_Reg(SPI_WRITE_REG+EN_RXADDR,0x01);
  284.   //设置RF通信频率                  
  285.   NRF24L01_Write_Reg(SPI_WRITE_REG+RF_CH,55);             
  286.   //选择通道0的有效数据宽度             
  287.   NRF24L01_Write_Reg(SPI_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);
  288.   //设置TX发射参数,0db增益,2Mbps,低噪声增益开启   
  289.   NRF24L01_Write_Reg(SPI_WRITE_REG+RF_SETUP,0x26);
  290.   //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,PRIM_RX接收模式
  291.   NRF24L01_Write_Reg(SPI_WRITE_REG+CONFIG, 0x0f);
  292.   //CE为高,进入接收模式
  293.   CE_HIGH;              
  294. }       
  295. /***************************************************************************
  296. * 描  述 : 主函数
  297. * 入  参 : 无
  298. * 返回值 : 无
  299. **************************************************************************/
  300. int main()            //主函数
  301. {     
  302. /////////////////////////////////////////////////
  303. //注意: STC15W4K32S4系列的芯片,上电后所有与PWM相关的IO口均为
  304. //      高阻态,需将这些口设置为准双向口或强推挽模式方可正常使用
  305. //相关IO: P0.6/P0.7/P1.6/P1.7/P2.1/P2.2
  306. //        P2.3/P2.7/P3.7/P4.2/P4.4/P4.5
  307. /////////////////////////////////////////////////
  308.         P0M1 = 0;        P0M0 = 0;        //设置P0.0~P0.7为准双向口
  309.         P2M1 = 0;        P2M0 = 0;        //设置P2.0~P2.7为准双向口
  310.         P3M1 = 0;        P3M0 = 0;        //设置P3.0~P3.7为准双向口
  311.         P4M1 = 0;        P4M0 = 0;        //设置P4.0~P4.7为准双向口
  312.         P5M1 = 0;        P5M0 = 0;        //设置P5.0~P5.7为准双向口
  313.        
  314.         Init_NRF24L01();                //初始化
  315.         Set_RxMode();                                                  //配置nRF24L01为发送模式
  316.        
  317.   while(1)
  318.   {
  319.           if(KEY == 0)//按键按下
  320.           {
  321.             delay_ms(10);
  322.             if(KEY== 0)         //延时去抖动   
  323.             {
  324.                     LED_B=0;
  325.                                 while(KEY == 0); //等待按键释放
  326.                                
  327.         TxPayload[0] = 0x5A;
  328.                                 LED_B=1;
  329.                                 if(NRF24L01_TxPacket(TxPayload) == TX_OK)        //如果发送成功
  330.                     {
  331.                         //无线发射成功        
  332.                     }
  333.                     else
  334.                     {
  335.             //添加错误处理代码
  336.         }
  337.             }
  338.           }
  339.                 if(NRF24L01_RxPacket(RxPayload) == RX_OK)        //如果接收成功
  340.                 {
  341.       if(RxPayload[0] == 0x5A)               
  342.       {
  343.                                 LED_R=~LED_R;//NRF24L01模块状态指示灯翻转
  344.                                 RxPayload[0] = 0;
  345.       }                       
  346.                 }
  347.         }
  348. }
复制代码

所有资料51hei提供下载:
nRF24L01_TxRx(硬件SPI).zip (48.89 KB, 下载次数: 109)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:243748 发表于 2019-2-24 12:10 来自手机 | 显示全部楼层
上个电路图呀,不懂接线
回复

使用道具 举报

ID:234782 发表于 2019-7-9 10:05 | 显示全部楼层
注释不怎么好
回复

使用道具 举报

ID:501909 发表于 2019-7-9 10:34 | 显示全部楼层
感谢楼主 分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表