[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

[51单片机] SPI nRF24L01无线 [可以放在2个单片机里实现通信],布布扣,bubuko.com

时间: 2024-12-23 21:30:59

[51单片机] SPI nRF24L01无线 [可以放在2个单片机里实现通信]的相关文章

[51单片机] SPI nRF24L01 无线简单程序 1

main.c 1 #include <reg51.h> 2 #include <api.h> 3 4 #define uchar unsigned char 5 6 /***************************************************/ 7 #define TX_ADR_WIDTH 5 // 5字节宽度的发送/接收地址 8 #define TX_PLOAD_WIDTH 4 // 数据通道有效数据宽度 9 #define LED P2 10 11

[51单片机] nRF24L01 无线模块 测试 按键-灯-远程控制

哈哈,穷吊死一个,自己做的一个超简单的板还没有电源提供,只得借助我的大开发板啦.其实这2个模块是完全可以分开的,无线嘛,你懂得!进入正题,这个实验的功能就是一个发送模块(大的那个板)连接4个按键,通过按动这4个不同的按键来发送4种不同的命令,来控制接收端(小的板)点亮4个不同的灯. >_<!首先是发送模块: 1 void main() 2 { 3 uchar Tx_Buf1[]={1}; //发送的信息1 4 uchar Rx_Buf[32]; //接收到的数据暂存器,最多32字节数据 5 i

[51单片机] nRF24L01 无线模块 串口法命令 通过无线控制另一个的灯

>_<!概述: 这是在上一个的基础上通过按键发送4种不同命令来控制接收端的LED灯亮的改进版(上一个:http://www.cnblogs.com/zjutlitao/p/3840013.html),这里俺把按键发命令给去掉,然后加入一个串口通信的功能,PC通过串口给发送端发送命令,然后发送端通过无线将命令发给接收端来实现控制,这里接收端和上一个例程中的一样,只是在发送端的代码里去除了按键控制,变成了串口控制. >_<!发送端电路: >_<!接收电路图: >_&l

nRF2401A/nRF24L01/nRF24L01+无线模块最常见问题汇集(转)

俗话说:每个人一生下来什么都会的,都是通过自己努力和探索出来的,NRF系列芯片,刚开始都好奇心加兴趣才来捣鼓它的,刚开始做硬件和软件,没有收发数据弄得整个人头都快炸开了,所以在此和大家分享一下前辈的经验,希望大家会少走弯路. Q:最近在选型的时候发现基本常见的无线模块都是3V供电,而我使用的单片机是5V的,它们之间要怎么连接呢?直接连接会不会损坏模块? 回答: 如果你使用的51单片机的P0口是高阻引脚,可以直接将无线模块的IO脚连接到P0端口,并在对应的连线与3V电源间放置1K~10K左右的偏置

CB1 驱动NRF24L01 无线模块 通信成功

系统:lubuntu 官方  (喜欢cb官方原版)硬件: cb   NRF24L01*2   51开发板一块   杜邦线若干 CB1 驱动NRF24L01 无线模块与STC51单片机通信成功!!! 1.废话不多说,上图上代码: 2.自制51单片机开发板:(24L01在右下角,有内置接口)   3.来张清晰的图,上面手抖了,      LCD1602显示温度,并实时通过无线发给cubieboard 1   4. 下图,第一位是正负温度指示,0x00代表正 ,0xff代表零下  . 后两位分别代表温

【Espruino】NO.15 nRF24L01+无线收发器

http://blog.csdn.net/qwert1213131/article/details/35853747 本文属于个人理解,能力有限,纰漏在所难免,还望指正! [小鱼有点电] [Espruino中文社区] nRF24L01+(或nRF24L01P)是一款工作在2.4~2.5GHz 世界通用ISM 频段的单片无线收发器芯片.无线收发器包括:频率发生器.增强型SchockBurst模式控制器.功率放大器.晶体振荡器调制器.解调器.输出功率频道选择和协议的设置可以通过SPI接口进行设置.

STM32+NRF24L01无线(转)

源:STM32+NRF24L01无线 硬件SPI和模拟SPI源码: nrf24发送(模拟SPI)BHS-STM32.rar nrf24接收(模拟SPI)BHS-STM32.rar nrf24发送(硬件SPI)BHS-STM32.rar nrf24接收(硬件SPI)BHS-STM32.rar NRF24L01资料 NRF24.rar 部分代码: #define TX_PLOAD_WIDTH 20 // 20 uints TX payload u8 TxBuf[32]={0}; #define CE

单片机入门指南系列(十五) 单片机程序下载失败总结

前面介绍了点亮第一个LED的全过程,很多人可能很幸运的点亮了LED,然而也很可能不少人非常不幸没有把程序下载进去.初学者常会遇到程序无法下载的情况,很多人在尝试多次未果后比较受打击,因此放弃了学习,实在太可惜了.鉴于此,这里列举了单片机程序下载失败的各种出错原因.判断方法和解决方法,是前人所遇到的种种原因的总结. STC单片机下载程序主要分为三部分:单片机最小系统.下载电路.计算机端.下载失败一般主要就从这三个方面来解决问题. 快速排错方法 如果你有或者能向别人借到一套可以正常下载程序的电脑.单

51单片机SPI协议与应用实例

-------------------------------------------- SPI总线 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 参考链接: http://blog.csdn.net/fly__chen/article/detail