SPI nRF24L01无线 [可以放在2个单片机里实现通信]
2017-01-15 来源:eefocus
main.c
1 #include
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 }
2401.h
1 #ifndef __NRF24L01_H__
2 #define __NRF24L01_H__
3 #include
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 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 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__ */
上一篇:单片机简单的串口通信