zoukankan      html  css  js  c++  java
  • [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
  • 相关阅读:
    swift5.x for-in, switch语句
    swift5.x 数组(Array)的基本操作
    OC NSDictionary的属性一般为什么要设置为copy
    iOS APP 从编译到运行
    重装win10系统之后,如何使用之前的虚拟机
    [Delphi]接口认识
    [QPlugins]学习大纲
    [QPlugins]概述
    [转发]Oauth 1.0 1.0a 和 2.0 的之间的区别有哪些?
    [Delphi] Webbroker ISAPI 示例说明
  • 原文地址:https://www.cnblogs.com/zjutlitao/p/3753984.html
Copyright © 2011-2022 走看看