找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2099|回复: 0
收起左侧

基于51单片机&NRF2401L的多通道遥控车程序

[复制链接]
ID:751452 发表于 2020-5-26 09:05 | 显示全部楼层 |阅读模式
5黑币
       最近研究NRF2401L无线模块,想用其做一个遥控车,但是调通了第0通道,其他几个通道不知道怎么弄了,希望大神指导。
       目前能够实现的功能只有:遥控按前进,车子前进,按左转前轮向左偏转,但是二者不可同时操作,也就是每次只能按下一个按键,不然就会紊乱。
下面是遥控器端NRF2401L的驱动程序:
  1. #ifndef NRF24L01_H
  2. #define NRF24L01_H
  3. #include "delay.h"

  4. sbit         MISO        =P2^0;
  5. sbit        SCK          =P2^1;
  6. sbit        CE          =P2^2;

  7. sbit        IRQ                =P2^7;
  8. sbit         MOSI        =P2^6;
  9. sbit        CSN                =P2^5;

  10. /*********NRF24L01*****************/
  11. #define TX_ADR_WIDTH    5          
  12. #define RX_ADR_WIDTH    5          
  13. #define TX_PLOAD_WIDTH  12         
  14. #define RX_PLOAD_WIDTH  12         
  15. uchar const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01};        //本地地址
  16. uchar const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01};        //接收地址
  17. /*********NRF24L01寄存器指令*****************/
  18. #define READ_REG        0x00          // 读寄存器指令
  19. #define WRITE_REG       0x20         // 写寄存器指令
  20. #define RD_RX_PLOAD     0x61          // 读取接收数据指令
  21. #define WR_TX_PLOAD     0xA0          // 写待发数据指令
  22. #define FLUSH_TX        0xE1         // 冲洗发送 FIFO指令
  23. #define FLUSH_RX        0xE2          // 冲洗接收 FIFO指令
  24. #define REUSE_TX_PL     0xE3          // 定义重复装载数据指令
  25. #define NOP             0xFF          // 保留
  26. /*********nRF24L01寄存器地址*****************/
  27. #define CONFIG          0x00  // 配置收发状态,CRC校验模式以及收发状态响应方式
  28. #define EN_AA           0x01  // 自动应答功能设置
  29. #define EN_RXADDR       0x02  // 可用信道设置
  30. #define SETUP_AW        0x03  // 收发地址宽度设置
  31. #define SETUP_RETR      0x04  // 自动重发功能设置
  32. #define RF_CH           0x05  // 工作频率设置
  33. #define RF_SETUP        0x06  // 发射速率、功耗功能设置
  34. #define STATUS          0x07  // 状态寄存器
  35. #define OBSERVE_TX      0x08  // 发送监测功能
  36. #define CD              0x09  // 地址检测           
  37. #define RX_ADDR_P0      0x0A  // 频道0接收数据地址
  38. #define RX_ADDR_P1      0x0B  // 频道1接收数据地址
  39. #define RX_ADDR_P2      0x0C  // 频道2接收数据地址
  40. #define RX_ADDR_P3      0x0D  // 频道3接收数据地址
  41. #define RX_ADDR_P4      0x0E  // 频道4接收数据地址
  42. #define RX_ADDR_P5      0x0F  // 频道5接收数据地址
  43. #define TX_ADDR         0x10  // 发送地址寄存器
  44. #define RX_PW_P0        0x11  // 接收频道0接收数据长度
  45. #define RX_PW_P1        0x12  // 接收频道0接收数据长度
  46. #define RX_PW_P2        0x13  // 接收频道0接收数据长度
  47. #define RX_PW_P3        0x14  // 接收频道0接收数据长度
  48. #define RX_PW_P4        0x15  // 接收频道0接收数据长度
  49. #define RX_PW_P5        0x16  // 接收频道0接收数据长度
  50. #define FIFO_STATUS     0x17  // FIFO栈入栈出状态寄存器设置

  51. /*NRF24L01的SPI写时序*/
  52. uchar SPI_RW(uchar datal)
  53. {
  54.         uchar i;
  55.            for(i=0;i<8;i++)
  56.            {
  57.                 MOSI = (datal & 0x80);         
  58.                 datal = (datal << 1);           
  59.                 SCK = 1;                     
  60.                 datal |= MISO;                        
  61.                 SCK = 0;                              
  62.            }
  63.     return(datal);                             
  64. }



  65. /* 读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数*/
  66. uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)
  67. {
  68.         uchar status,i;
  69.         CSN=0;                  
  70.         status = SPI_RW(reg);              
  71.         for(i=0;i<uchars;i++)
  72.                 pBuf[i] = SPI_RW(0);  
  73.         CSN=1;                           
  74.         return status;               
  75. }


  76. uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)
  77. {
  78.         uchar status,i;
  79.         CSN=0;            
  80.         status = SPI_RW(reg);   
  81.         for(i=0; i<uchars; i++)
  82.         SPI_RW(*pBuf++);
  83.         CSN=1;         
  84.         return status;
  85. }
  86. uint SPI_RW_Reg(uchar reg, uchar value)
  87. {
  88.         uint status;
  89.        
  90.         CSN = 0;                  
  91.         status = SPI_RW(reg);      
  92.         SPI_RW(value);            
  93.         CSN = 1;                  
  94.        
  95.         return(status);         
  96. }

  97. void init_NRF24L01(void)
  98. {
  99.         CE=0;   
  100.         CSN=1;   
  101.         SCK=0;   
  102.         SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);    // 写本地地址       
  103.         SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址
  104.         SPI_RW_Reg(WRITE_REG + EN_AA, 0x3f);      //  频道0自动        ACK应答允许       
  105.         SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x3f);  //  允许接收地址只有频道0,如果需要多频道可以参考Page21  
  106.         SPI_RW_Reg(WRITE_REG + RF_CH, 0);        //   设置信道工作为2.4GHZ,收发必须一致
  107.         SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为20字节
  108.         SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);                   //设置发射速率为1MHZ,发射功率为最大值0dB       
  109.         SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);                    // IRQ收发完成中断响应,16位CRC,主发送
  110. }
  111. void nRF24L01_TxPacket(uchar * tx_buf)
  112. {
  113.         CE=0;                        //StandBy I模式       
  114.         SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载接收端地址
  115.         SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH);                          // 装载数据       
  116.         CE=1;                 //置高CE,激发数据发送
  117.         Delay(10);
  118.         SPI_RW_Reg(WRITE_REG+STATUS,0XFF);
  119.        
  120.        
  121. }
  122. /***********************************
  123. //检测24L01是否存在
  124. //返回值:0:成功    1:失败       
  125. ***********************************/
  126. uchar NRF24L01_Check(void)
  127. {       
  128.         uchar i;
  129.         uchar buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
  130.         SPI_Write_Buf(WRITE_REG+TX_ADDR,buf,5);//写入5个字节的地址.       
  131.         SPI_Read_Buf(TX_ADDR,buf,5); //读出写入的地址  
  132.         for(i=0;i<5;i++){if(buf[i]!=0XA5)break;}                                                                   
  133.         if(i!=5)return 1;//检测24L01错误       
  134.         return 0;                 //检测到24L01
  135. }
  136. #endif
复制代码
下面是遥控主程序:

  1. #include "nrf24l01.h"//无线模块头文件

  2. sbit LED  = P1^7;           //LED指示

  3. sbit key1 = P1^0;         //1号
  4. sbit key2 = P1^2;         //2号
  5. sbit key3 = P1^4;         //3号
  6. sbit key4 = P1^6;         //4号

  7. sbit key5 = P1^1;         //5号

  8. void main(void)
  9. {         
  10.         uint count=0;       //计数变量
  11.         uchar TxBuf[12];    //发射缓存数组
  12.           
  13.         //无线模块检测函数
  14.         MOSI=0;
  15.         while(NRF24L01_Check())
  16.         {
  17.                 LED=1;
  18.                 Delay(200);
  19.                 LED=0;
  20.                 Delay(200);
  21.     }
  22.         init_NRF24L01();   //无线模块初始化
  23.         TxBuf[0]=0xFF;
  24.         TxBuf[1]=0x00;
  25.        
  26.                 //TxBuf[2]=0x02;//按键值
  27.         TxBuf[3]=0x55;
  28.         TxBuf[4]=0x55;
  29.         TxBuf[5]=0x55;
  30.         TxBuf[6]=0x55;
  31.         TxBuf[7]=0x55;
  32.         TxBuf[8]=0x55;
  33.         TxBuf[9]=0x55;
  34.         TxBuf[10]=0x00;
  35.         TxBuf[11]=0xFF;
  36.         while(1)
  37.         {
  38.                 if(!key1)//
  39.                 {
  40.                         Delay(5);
  41.                         if(!key1)
  42.                         {
  43.                                    LED=0;
  44.                                 TxBuf[2]=0x01;
  45.                         }
  46.                 }
  47.                
  48.                
  49.                 if(!key2)//
  50.                 {
  51.                            Delay(5);
  52.                         if(!key2)
  53.                         {
  54.                                    LED=0;
  55.                                 TxBuf[2]=0x02;
  56.                         }
  57.                 }
  58.                
  59.                
  60.                 if(!key3)//
  61.                 {
  62.                            Delay(5);
  63.                         if(!key3)
  64.                         {
  65.                                    LED=0;
  66.                                 TxBuf[2]=0x03;
  67.                         }
  68.                 }
  69.                
  70.                
  71.                 if(!key4)//
  72.                 {
  73.                            Delay(5);
  74.                         if(!key4)
  75.                         {
  76.                                    LED=0;
  77.                                 TxBuf[2]=0x04;
  78.                         }
  79.                 }
  80.                
  81.                
  82.                 if(!key5)
  83.                 {
  84.                            Delay(5);
  85.                         if(!key5)
  86.                         {
  87.                                    LED=0;
  88.                                 TxBuf[2]=0x05;
  89.                         }
  90.                 }
  91.                
  92.                 if(key1 && key2 && key3 && key4 && key5)//没有,执行下面指示
  93.                 {
  94.                         count++;if(count>330)count=34;
  95.                         if(count%33==0)
  96.                         {
  97.                                 LED=~LED;      //led取反
  98.                         }
  99.                         TxBuf[2]=0x00;
  100.       TxBuf[0]=0x00;                       
  101.                 }
  102.                 nRF24L01_TxPacket(TxBuf);///无线发射函数
  103.                 Delay(5);
  104.         }
  105. }
复制代码


                                                                                ------------到接收机了-------------
下面是接收机NRF2401L的驱动程序:
  1. #ifndef NRF24L01_H
  2. #define NRF24L01_H
  3. #include "delay.h"

  4. sbit        IRQ                =P1^0;
  5. sbit         MOSI        =P1^1;
  6. sbit        CSN                =P1^2;

  7. sbit         MISO        =P1^3;
  8. sbit        SCK          =P1^4;
  9. sbit        CE          =P1^5;

  10. /*********NRF24L01*****************/
  11. #define TX_ADR_WIDTH    5          
  12. #define RX_ADR_WIDTH    5          
  13. #define TX_PLOAD_WIDTH  12         
  14. #define RX_PLOAD_WIDTH  12         
  15. uchar const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01};        //本地地址
  16. uchar const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01};        //接收地址

  17. /*********NRF24L01寄存器指令*****************/
  18. #define READ_REG        0x00          // 读寄存器指令
  19. #define WRITE_REG       0x20         // 写寄存器指令
  20. #define RD_RX_PLOAD     0x61          // 读取接收数据指令
  21. #define WR_TX_PLOAD     0xA0          // 写待发数据指令
  22. #define FLUSH_TX        0xE1         // 冲洗发送 FIFO指令
  23. #define FLUSH_RX        0xE2          // 冲洗接收 FIFO指令
  24. #define REUSE_TX_PL     0xE3          // 定义重复装载数据指令
  25. #define NOP             0xFF          // 保留

  26. /*********nRF24L01寄存器地址*****************/
  27. #define CONFIG          0x00  // 配置收发状态,CRC校验模式以及收发状态响应方式
  28. #define EN_AA           0x01  // 自动应答功能设置
  29. #define EN_RXADDR       0x02  // 可用信道设置
  30. #define SETUP_AW        0x03  // 收发地址宽度设置
  31. #define SETUP_RETR      0x04  // 自动重发功能设置
  32. #define RF_CH           0x05  // 工作频率设置
  33. #define RF_SETUP        0x06  // 发射速率、功耗功能设置
  34. #define STATUS          0x07  // 状态寄存器
  35. #define OBSERVE_TX      0x08  // 发送监测功能
  36. #define CD              0x09  // 地址检测           
  37. #define RX_ADDR_P0      0x0A  // 频道0接收数据地址
  38. #define RX_ADDR_P1      0x0B  // 频道1接收数据地址
  39. #define RX_ADDR_P2      0x0C  // 频道2接收数据地址
  40. #define RX_ADDR_P3      0x0D  // 频道3接收数据地址
  41. #define RX_ADDR_P4      0x0E  // 频道4接收数据地址
  42. #define RX_ADDR_P5      0x0F  // 频道5接收数据地址
  43. #define TX_ADDR         0x10  // 发送地址寄存器
  44. #define RX_PW_P0        0x11  // 接收频道0接收数据长度
  45. #define RX_PW_P1        0x12  // 接收频道0接收数据长度
  46. #define RX_PW_P2        0x13  // 接收频道0接收数据长度
  47. #define RX_PW_P3        0x14  // 接收频道0接收数据长度
  48. #define RX_PW_P4        0x15  // 接收频道0接收数据长度
  49. #define RX_PW_P5        0x16  // 接收频道0接收数据长度
  50. #define FIFO_STATUS     0x17  // FIFO栈入栈出状态寄存器设置


  51. uchar SPI_RW(uchar datal)
  52. {
  53.         uchar i;
  54.            for(i=0;i<8;i++)
  55.            {
  56.                 MOSI = (datal & 0x80);         
  57.                 datal = (datal << 1);           
  58.                 SCK = 1;                     
  59.                 datal |= MISO;                        
  60.                 SCK = 0;                              
  61.            }
  62.     return(datal);                             
  63. }


  64. uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)
  65. {
  66.         uchar status,i;
  67.         CSN=0;                  
  68.         status = SPI_RW(reg);              
  69.         for(i=0;i<uchars;i++)
  70.                 pBuf[i] = SPI_RW(0);  
  71.         CSN=1;                           
  72.         return status;               
  73. }


  74. uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)
  75. {
  76.         uchar status,i;
  77.         CSN=0;            
  78.         status = SPI_RW(reg);   
  79.         for(i=0; i<uchars; i++)
  80.         SPI_RW(*pBuf++);
  81.         CSN=1;         
  82.         return status;
  83. }
  84. uint SPI_RW_Reg(uchar reg, uchar value)
  85. {
  86.         uint status;
  87.        
  88.         CSN = 0;                  
  89.         status = SPI_RW(reg);      
  90.         SPI_RW(value);            
  91.         CSN = 1;                  
  92.        
  93.         return(status);            
  94. }
  95. /* NRF24L01的SPI读时序   */
  96. uchar SPI_Read(uchar reg)
  97. {
  98.         uchar reg_val;
  99.         CSN=0;                  // CSN low, initialize SPI communication...
  100.         SPI_RW(reg);            // Select register to read from..
  101.         reg_val = SPI_RW(0);    // ..then read registervalue
  102.         CSN=1;                  // CSN high, terminate SPI communication
  103.         return(reg_val);        // return register value
  104. }


  105. void SetRX_Mode(void)
  106. {
  107.         CE=0;
  108.         SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);                   // IRQ收发完成中断响应,16位CRC        ,主接收
  109.         CE=1;
  110.         Delay(1);                                  //注意不能太小
  111. }
  112. /*:数据读取后放如rx_buf接收缓冲区中    */
  113. uchar nRF24L01_RxPacket(uchar* rx_buf)
  114. {
  115.         uchar  sta;
  116.         sta=SPI_Read(STATUS);             // 读取状态寄存器来判断数据接收状况               
  117.         SPI_RW_Reg(WRITE_REG+STATUS,sta);   //清除TX_DS或MAX_RT中断标志
  118.         if(sta&0x40)                 //接收到数据
  119.         {
  120.             //Low_24L01_CE;                         //SPI使能
  121.                 SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);//读取数据
  122.                 //SPI_RW_Reg(WRITE_REG+STATUS,0xff);//清除RX FIFO寄存器
  123.                 return 1;                       
  124.         }
  125.         return 0;
  126. }

  127. //接收模式设置,F接收频率设置,应与发射频率对应
  128. void init_NRF24L01(void)
  129. {                                                                                                                 
  130.         CE=0;    // chip enable
  131.         CSN=1;   // Spi disable
  132.         SCK=0;   // Spi clock line init high                    
  133.           SPI_Write_Buf(WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址
  134.           SPI_Write_Buf(WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK          
  135.           SPI_RW_Reg(WRITE_REG+EN_AA,0x3f);     //使能通道0的自动应答   
  136.           SPI_RW_Reg(WRITE_REG+EN_RXADDR,0x3f); //使能通道0的接收地址  
  137.           SPI_RW_Reg(WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次
  138.           SPI_RW_Reg(WRITE_REG+RF_CH,0);        //设置RF通道为40
  139.         SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);//设置TX发射参数,0db增益,2Mbps,低噪声增益开启
  140.           SPI_RW_Reg(WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);
  141.         SPI_RW_Reg(WRITE_REG+CONFIG,0x7e);    //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
  142.         CE=1;    // chip enable
  143.     Delay(50);
  144. }

  145. //检测24L01是否存在
  146. //返回值:0:成功    1:失败       
  147. uchar NRF24L01_Check(void)
  148. {       
  149.         uchar i;
  150.         uchar buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
  151.         SPI_Write_Buf(WRITE_REG+TX_ADDR,buf,5);//写入5个字节的地址.       
  152.         SPI_Read_Buf(TX_ADDR,buf,5); //读出写入的地址  
  153.         for(i=0;i<5;i++){if(buf[i]!=0XA5)break;}                                                                   
  154.         if(i!=5)return 1;//检测24L01错误       
  155.         return 0;                 //检测到24L01
  156. }
  157. #endif
复制代码
下面是接收机主函数:
  1. #include "nrf24l01.h"  //NRF24L01头文件

  2. sbit QJ  = P2^4;
  3. sbit HT  = P2^7;
  4. sbit Z  = P2^2;
  5. sbit Y  = P2^3;

  6. sbit LED01 = P0^1;

  7. sbit LED  = P2^0;
  8. sbit KEY   = P3^7;           //确认按键


  9. void main(void)
  10. {
  11.        
  12.         uchar flagNo1=0;
  13.         uchar RxBuf[12];    //接收缓存数组
  14.         //无线模块检测
  15.         while(NRF24L01_Check())
  16.         {
  17.                 LED=0;
  18.                 Delay(500);
  19.                 LED=1;
  20.                 Delay(500);
  21.     }
  22.         init_NRF24L01();//无线模块初始化
  23.                
  24.                
  25.         while(1)
  26.         {
  27.                 nRF24L01_RxPacket(RxBuf);//接收从机数据
  28.                 SetRX_Mode();//配置为接收模块
  29.                 //判断
  30.                
  31.                         if(RxBuf[2]==0x01)
  32.                         {  QJ=0;}               
  33.                            else {QJ=1;}
  34.                                  
  35.                         if(RxBuf[2]==0x02)
  36.                         {  HT=0; }               
  37.                            else {HT=1;}
  38.                
  39.                         /*   此处省略一部分     */
  40.        
  41.                                  //确认处理
  42.                 if(!KEY)
  43.                 {
  44.                         LED=1;//关闭蜂鸣器
  45.                 }
  46.         }
  47. }
复制代码






回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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