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