小R科技-WIFI机器人网·机器人创意工作室

 找回密码
 立即注册
查看: 8031|回复: 1

51单片机驱动NRF24L01无线模块双向通信亲测调试通过

[复制链接]
发表于 2016-5-2 20:25:23 | 显示全部楼层 |阅读模式
折腾好几个星期啦,今天终于调试通过,甲乙单片机双向通信。3.3v给模块供电,电源输入和输出加10uf电容,模块vcc和gnd加104瓷片。模块的引脚和单片机的引脚直接相连,不用担心不会烧坏模块。我当时看到网上说要加限流电阻或模块和单片机连接的引脚要下拉,结果很多网上的程序都调不通,去掉限流电阻一切正常。希望能帮到像我一样的菜菜鸟!!!!!!1
  1. /************************************************
  2.         功能   :双单片机通过NRF24L01进行无线通信
  3.                         甲单片机按下按键控制乙单片机的数码管显示
  4.                         乙单片机按下按键控制甲单片机的LED显示
  5.                                         调试通过。
  6.         甲单片机:STC12C5608AD
  7.         乙单片机:STC12C5A60S2
  8.         晶    振:11.0592M
  9.         作    者:苏义江改编自网络
  10.         时    间:2016.4.30
  11.         注   释 :甲单片机发个乙单片机,乙单片机接收到数据
  12.                         再发给甲单片机。同理乙发给甲单片机数据,
  13.                         甲单片机接收到数据再发给乙单片机。
  14.                                         双方相互通信

  15. ***********************************************/

  16. #include <reg52.h>
  17. #include <intrins.h>   
  18. typedef unsigned char uchar;
  19. typedef unsigned char uint;
  20. #define uz unsigned  uint
  21. //甲单片机STC12C5608AD端口定义
  22. /*sbit MISO =P1^7; //数字输出(从 SPI 数据输出脚)
  23. sbit MOSI =P1^4; //数字输入(从 SPI 数据输入脚)
  24. sbit SCK  =P1^5; //数字输入(SPI 时钟)  
  25. sbit CE   =P1^3; //数字输入(RX 或 TX 模式选择)
  26. sbit CSN  =P1^2; //数字输入(SPI片选信号)
  27. sbit IRQ  =P1^6; //数字输入(可屏蔽中断)
  28. sbit KEY1 =P2^4;//按键S1
  29. sbit KEY2 =P2^5;//按键S2
  30. sbit led1 =P2^0; //LED0
  31. sbit led2 =P2^1; //LED1  
  32. sbit led3 =P2^2; //LED2  
  33. sbit led4 =P2^3; //LED3 */


  34. //乙单片机STC12C5A60S2端口定义
  35. sbit MISO =P2^1; //数字输出(从 SPI 数据输出脚)
  36. sbit MOSI =P2^2; //数字输入(从 SPI 数据输入脚)
  37. sbit SCK  =P2^3; //数字输入(SPI 时钟)  
  38. sbit CE   =P1^6; //数字输入(RX 或 TX 模式选择)
  39. sbit CSN  =P2^4; //数字输入(SPI片选信号)
  40. sbit IRQ  =P2^0; //数字输入(可屏蔽中断)
  41. sbit KEY1 =P3^7;//按键S1
  42. sbit KEY2 =P3^6;//按键S2
  43. sbit led1 =P0^0; //LED0
  44. sbit led2 =P0^1; //LED1  
  45. sbit led3 =P0^2; //LED2  
  46. sbit led4 =P0^3; //LED3
  47. sbit fmq  =P1^7;
  48. sbit wei=P2^7;
  49. sbit duan=P2^6;
  50. uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,
  51.                                 0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,
  52.                                 0xa1,0x86,0x8e,0x89};
  53. uchar code tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
  54. uchar code tab1[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};

  55. #define TX_ADR_WIDTH    5   // 5 uints TX address width
  56. #define RX_ADR_WIDTH    5   // 5 uints RX address width
  57. #define TX_PLOAD_WIDTH  20   // 20 uints TX payload
  58. #define RX_PLOAD_WIDTH  20   // 20 uints TX payload  
  59. uint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址  
  60. uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址
  61. #define READ_REG        0x00   // 读寄存器指令
  62. #define WRITE_REG       0x20 // 写寄存器指令
  63. #define RD_RX_PLOAD     0x61   // 读取接收数据指令
  64. #define WR_TX_PLOAD     0xA0   // 写待发数据指令
  65. #define FLUSH_TX        0xE1 // 冲洗发送 FIFO指令
  66. #define FLUSH_RX        0xE2   // 冲洗接收 FIFO指令
  67. #define REUSE_TX_PL     0xE3   // 定义重复装载数据指令
  68. #define NOP             0xFF   // 保留  

  69. #define CONFIG          0x00  // 配置收发状态,CRC校验模式以及收发状态响应方式  
  70. #define EN_AA           0x01  // 自动应答功能设置
  71. #define EN_RXADDR       0x02  // 可用信道设置
  72. #define SETUP_AW        0x03  // 收发地址宽度设置
  73. #define SETUP_RETR      0x04  // 自动重发功能设置
  74. #define RF_CH           0x05  // 工作频率设置  
  75. #define RF_SETUP        0x06  // 发射速率、功耗功能设置
  76. #define STATUS          0x07  // 状态寄存器
  77. #define OBSERVE_TX      0x08  // 发送监测功能
  78. #define CD              0x09  // 地址检测            
  79. #define RX_ADDR_P0      0x0A  // 频道0接收数据地址
  80. #define RX_ADDR_P1      0x0B  // 频道1接收数据地址
  81. #define RX_ADDR_P2      0x0C  // 频道2接收数据地址
  82. #define RX_ADDR_P3      0x0D  // 频道3接收数据地址
  83. #define RX_ADDR_P4      0x0E  // 频道4接收数据地址
  84. #define RX_ADDR_P5      0x0F  // 频道5接收数据地址
  85. #define TX_ADDR         0x10  // 发送地址寄存器
  86. #define RX_PW_P0        0x11  // 接收频道0接收数据长度
  87. #define RX_PW_P1        0x12  // 接收频道0接收数据长度
  88. #define RX_PW_P2        0x13  // 接收频道0接收数据长度
  89. #define RX_PW_P3        0x14  // 接收频道0接收数据长度
  90. #define RX_PW_P4        0x15  // 接收频道0接收数据长度
  91. #define RX_PW_P5        0x16  // 接收频道0接收数据长度
  92. #define FIFO_STATUS     0x17  // FIFO栈入栈出状态寄存器设置

  93. void Delay(unsigned int s);     //大延时
  94. void inerDelay_us(unsigned char n); //小延时
  95. void init_NRF24L01(void);  //NRF24L01 初始化  
  96. uint SPI_RW(uint dat);  //根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01读出一字节  
  97. uchar SPI_Read(uchar reg);  //从reg寄存器读一字节
  98. void SetRX_Mode(void);  
  99. //数据接收配置  
  100. uint SPI_RW_Reg(uchar reg, uchar value);  
  101. //写数据value到reg寄存器  
  102. uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars);  
  103. //从reg寄存器读出bytes个字节,通常用来
  104. uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars);
  105. //把pBuf缓存中的数据写入到nRF24L01,通常用来写入发  
  106. //射通道数据或接收/发送地址  
  107. unsigned char nRF24L01_RxPacket(unsigned char* rx_buf);  
  108. //数据读取后放入rx_buf接收缓冲区中  
  109. void nRF24L01_TxPacket(unsigned char * tx_buf);  
  110. //发送 tx_buf中数据

  111. void Delay(unsigned int s)
  112. {  
  113.         unsigned int i;
  114.         for(i=0; i<s; i++);
  115.         for(i=0; i<s; i++);
  116. }  
  117. uint bdata sta;   //状态标志  
  118. sbit RX_DR =sta^6; //RX_DR 为 sta 的第六位
  119. sbit TX_DS =sta^5; //TX_DS 为 sta 的第五位
  120. sbit MAX_RT =sta^4; //MAX_RT 为 sta 的第四位
  121. void inerDelay_us(unsigned char n) //延时,us 级
  122. {  
  123.         for(;n>0;n--)
  124.          _nop_();
  125. }

  126. void init_NRF24L01(void)
  127. {      
  128.         inerDelay_us(100);   
  129.         CE=0;    // 芯片使能   
  130.         CSN=1;   // 禁止 SPI
  131.         SCK=0;   // SPI时钟置低  
  132.         SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);   
  133. // 写本地地址  
  134.         SPI_Write_Buf(WRITE_REG  +  RX_ADDR_P0,  RX_ADDRESS,  RX_ADR_WIDTH);
  135. // 写接收端地址  
  136.         SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);      
  137. //  频道0自动 ACK应答允许  
  138.         SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);  
  139. //  允许接收地址只有频道0,如果需要多频道可以参考Page21   
  140.         SPI_RW_Reg(WRITE_REG + RF_CH, 0);        
  141. //   设置信道工作为2.4GHZ,收发必须一致  
  142.         SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH);
  143. //设置接收数据长度,本次设置为32字节  
  144.         SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);   
  145. //设置发射速率为1MHZ,发射功率为最大值0dB
  146. }

  147. uint SPI_RW(uint dat)
  148. {
  149.         uint i;     
  150.         for(i=0;i<8;i++) // 循环8次   
  151.         {  
  152.                 MOSI = (dat & 0x80);  
  153.                 // dat的最高位输出到MOSI   
  154.                 dat = (dat << 1);     
  155.                 // 从右向左进一位         
  156.                 SCK = 1;              
  157.                 // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据  Set SCK high..  
  158.                 dat |= MISO;          //读MISO到 dat 最低位
  159.                 SCK = 0;              // SCK置低                     
  160.         }      
  161.         return(dat);            
  162.         //返回读出的一字节           
  163. }  
  164. uchar SPI_Read(uchar reg)
  165. {  
  166.         uchar reg_val;  
  167.         CSN = 0;            
  168.         //CSN置低,开始传输数据   
  169.         SPI_RW(reg);         //选择寄存器              
  170.         reg_val = SPI_RW(0); //然后从该寄存器读数据   
  171.         CSN = 1;             //CSN拉高,结束数据传输   
  172.         return(reg_val);     //返回寄存器数据         
  173. }

  174. uint SPI_RW_Reg(uchar reg, uchar value)
  175. {  
  176.         uchar status;
  177.          CSN = 0;               
  178.         // CSN置低,开始传输数据      
  179.         status = SPI_RW(reg);  
  180.         // 选择寄存器,同时返回状态字  
  181.         SPI_RW(value);         
  182.         // 然后写数据到该寄存器        
  183.         CSN = 1;               
  184.         // CSN拉高,结束数据传输      
  185.         return(status);        // 返回状态寄存器              
  186. }

  187. uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)
  188. {  
  189.         uint status,i;  
  190.         CSN = 0;                 
  191.         //CSN置低,开始传输数据   
  192.         status = SPI_RW(reg);   
  193.         //选择寄存器,同时返回状态字  
  194.         for(i=0;i<uchars;i++)  
  195.         pBuf[i] = SPI_RW(0);
  196.         //逐个字节从nRF24L01读出
  197.         CSN = 1;                 //CSN拉高,结束数据传输
  198.         return(status);         
  199.         //返回状态寄存器return nRF24L01 status uchar      

  200. }

  201. uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)
  202. {  
  203.         uint status,i;  
  204.         CSN = 0;               
  205.         //CSN置低,开始传输数据        
  206.         status = SPI_RW(reg);  
  207.         //选择寄存器,同时返回状态字
  208.         inerDelay_us(10);   
  209.         for(i=0; i<uchars; i++)   
  210.         SPI_RW(*pBuf++); //逐个字节写入nRF24L01
  211.         CSN = 1;           
  212.         //CSN拉高,结束数据传输
  213.         return(status);    //返回状态寄存器
  214. }

  215. void SetRX_Mode(void)
  216. {  
  217.         CE=0;  
  218.         SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);
  219.         //CRC使能,16位CRC校验,上电,接收模式   
  220.         CE = 1;   
  221.         // 拉高CE启动接收设备  
  222.         inerDelay_us(130);
  223. }

  224. unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)
  225. {      
  226.         unsigned char revale=0;  
  227.         sta=SPI_Read(STATUS);
  228.         // 读取状态寄存其来判断数据接收状况
  229.         if(RX_DR) // 判断是否接收到数据
  230.         {     
  231.                 CE = 0; //SPI使能  
  232.                 SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);
  233.                 revale =1; //读取数据完成标志
  234.         }
  235.         SPI_RW_Reg(WRITE_REG+STATUS,sta);     
  236.         //接收到数据后 RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志
  237.         return revale;
  238. }

  239. void nRF24L01_TxPacket(unsigned char * tx_buf)
  240. {  
  241.         CE=0; //StandBy I模式
  242.         SPI_Write_Buf(WRITE_REG+RX_ADDR_P0,TX_ADDRESS,TX_ADR_WIDTH);
  243.         // 装载接收端地址  
  244.         SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH);
  245.         // 装载数据
  246.         SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);   
  247.         // IRQ收发完成中断响应,16位CRC,主发送  
  248.         CE=1; //置高CE,激发数据发送
  249.         inerDelay_us(10);
  250. }
  251. void delay1(uint z)
  252. {
  253.         uint x,y;
  254.         for(x=z;x>0;x--)
  255.         for(y=650;y>0;y--);
  256. }

  257. void main(void)
  258. {   
  259.         unsigned char tf =0;
  260.         uint i ;
  261.         unsigned char TxBuf[20]={0};
  262.         // 要发送的数组
  263.         unsigned char RxBuf[20]={0};
  264.         // 接收的数据 数组     
  265.         init_NRF24L01();  //模块初始化
  266.         led1=1;led2=1;led3 =1;led4 =1; //led 灯关闭   
  267.         Delay(1000);   
  268.         while(1)
  269.         {
  270.                 if(KEY1 ==0 ) //按键 1 按下   
  271.                 {     
  272.                
  273.                         TxBuf[1] = 1;  //赋值   
  274.                         tf = 1;   
  275.                         led1=0; //本地led 灯闪烁
  276.                         Delay(200);
  277.                         led1=1;
  278.                         Delay(200);   
  279.                  }
  280.                 if(KEY2 ==0 )  //按键 2 按下   
  281.                 {  
  282.                        
  283.                         TxBuf[2] =1;  //赋值
  284.                         tf = 1 ;  
  285.                         led2=0; //本地led 灯闪烁
  286.                         Delay(200);  
  287.                         led2=1;
  288.                         Delay(200);   
  289.                 }   
  290.                 if (tf==1) //有键按下
  291.                 {  
  292.                         nRF24L01_TxPacket(TxBuf);
  293.                         //发送数据Transmit Tx buffer data  
  294.                        
  295.                         TxBuf[1] = 0x00;
  296.                         //清零
  297.                         TxBuf[2] = 0x00;
  298.                         tf=0;  
  299.                         Delay(1000);   
  300.                 }
  301.        
  302.                 SetRX_Mode();  //设置成接受模式
  303.                 RxBuf[1] = 0x00;  
  304.                 //接收的数组相应位清零
  305.                 RxBuf[2] = 0x00;   
  306.                 Delay(1000);  
  307.                 nRF24L01_RxPacket(RxBuf);  //接收数据

  308.                 if(RxBuf[1]|RxBuf[2])
  309.                 {//如果有一组为高就执行下面语句  
  310.                         if( RxBuf[1]==1)
  311.                         {     
  312.                                 wei=1;//乙单片机接收的数据
  313.                                 P0=0xef;
  314.                                 wei=0;
  315.                                 duan=1;
  316.                                 P0= table[2] ;
  317.                                 duan=0;
  318.                                  Delay(30);
  319.                                 for(i=0;i<8;i++)
  320.                                 {
  321.                                         P0=tab[i];
  322.                                         Delay(20000);        
  323.                                 }
  324.                                 for(i=0;i<8;i++)
  325.                                 {
  326.                                 P0=0XAA;
  327.                                 Delay(30000);
  328.                                 P0=0XFF;
  329.                                 Delay(30000);
  330.                                 }
  331.                                 for(i=300;i>0;i--)
  332.                                 {
  333.                                         fmq=0;
  334.                                         delay1(60000);delay1(60000);
  335.                                 //        fmq=1;
  336.                                         delay1(60000);delay1(60000);
  337.                                 }
  338.                         /*        led3=RxBuf[0];//甲单片机接收的数据 */
  339.                         }  
  340.                        
  341.                         if( RxBuf[2]==1)
  342.                         {  
  343.                                 wei=1;//乙单片机接收的数据
  344.                                 P0=0x00;
  345.                                 wei=0;
  346.                                 for(i=0;i<17;i++)
  347.                                 {
  348.                                 duan=1;
  349.                                 P0= table[i] ;
  350.                                 duan=0;
  351.                                  Delay(60000); Delay(60000);
  352.                                 }
  353.                                 for(i=0;i<8;i++)
  354.                                 {
  355.                                         P0=tab1[i];
  356.                                         Delay(20000);        
  357.                                 }
  358.                                 for(i=0;i<8;i++)
  359.                                 {
  360.                                 P0=0X55;
  361.                                 Delay(30000);
  362.                                 P0=0XFF;
  363.                                 Delay(30000);
  364.                                 }
  365.                         /*        led4=RxBuf[4];//甲单片机接收的数据 */
  366.                         }
  367.                        
  368.                                 Delay(3000); //old is '1000'
  369.                 }  
  370.                 RxBuf[1] = 0x00;   
  371.                 //清零
  372.                 RxBuf[2] = 0x00; //清零
  373.                 fmq=1;
  374.                 led3=1;  //关灯
  375.                 led4=1; //关灯
  376.                 duan=1;
  377.                 P0=0xff;//关数码管
  378.                 duan=0;
  379.         }
  380. }
复制代码


评分

参与人数 1威望 +2 金钱 +3 贡献 +1 收起 理由
liuviking + 2 + 3 + 1 很给力!

查看全部评分

回复

使用道具 举报

发表于 2016-5-23 12:57:19 | 显示全部楼层
很强大啊。双核。。
回复 支持 反对

使用道具 举报

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

本版积分规则

关闭

新品特惠推荐上一条 /2 下一条

QQ|QQ技术咨询1|QQ技术咨询2|商务合作微信1:xiaorgeek001|商务合作微信2:XiaoRGEEK|诚聘英才|Archiver|手机版|小R科技-WIFI机器人网·机器人创意工作室 ( 粤ICP备15000788号-6 )

GMT+8, 2024-11-22 23:59 , Processed in 1.152461 second(s), 23 queries .

Powered by XiaoR GEEK X3.4

© 2014-2021 XiaoR GEEK

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