




免费预览已结束,剩余13页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
24l01的多机通信采用频分多子的方法,只需要在接受端对不同的通道配置地址即可。发送端使用相应的地址作为本机地址。接受数据时通过读取STATUS中相关位即可得知接收的是哪个通道的数据。以下仅给出多对一的通信代码。至于一对多,以及多对多等情况读者可以自行研究了。只给出相关部分,其他部分请参考前两篇文章-接受端-uint const ADDRESS0ADR_WIDTH= 0x34,0x43,0x10,0x10,0x01; /频道0接收地址uint const ADDRESS1ADR_WIDTH= 0xc4,0xc3,0xc2,0xc1,0xc0; /频道1接收地址uchar who=0xff;/*/*NRF24L01初始化/*/void init_NRF24L01(void) us(100); CE=0; / chip enable CSN=1; / Spi disable SCK=0; / Spi clock line init high/SPI_Write_Buf(WRITE_REG + TX_ADDR,ADDRESS0, ADR_WIDTH); / 写本地地址SPI_Write_Buf(WRITE_REG + RX_ADDR_P0,ADDRESS0,ADR_WIDTH); / 频道0地址SPI_Write_Buf(WRITE_REG + RX_ADDR_P1,ADDRESS1,ADR_WIDTH); / 频道1地址SPI_RW_Reg(WRITE_REG + EN_AA, 0x03); /频道0、1自动应答 SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x03); /允许频道0、1 SPI_RW_Reg(WRITE_REG + RF_CH, 0); / 设置信道工作为2.4GHZ,收发必须一致SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); /0接收数据长度SPI_RW_Reg(WRITE_REG + RX_PW_P1, RX_PLOAD_WIDTH); /1接收数据长度SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); /设置发射速率为1MHZ,发射功率为最大值0dB/*/*函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)/*功能:数据读取后放如rx_buf接收缓冲区中/*/unsigned char nRF24L01_RxPacket(unsigned char* rx_buf) unsigned char revale=0;sta=SPI_Read(STATUS); / 读取状态寄存其来判断数据接收状况if(RX_DR) / 判断是否接收到数据 CE = 0; SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH); revale =1; who=sta&0x0e; who|=0xf0; /通道0:who=0xf0;通道1:who=0xf2SPI_RW_Reg(WRITE_REG+STATUS,0xff); /接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志CSN=0;SPI_RW(FLUSH_RX);CSN=1;return revale;void main(void)uchar i;uchar RxBufTX_PLOAD_WIDTH; init_NRF24L01() ;StartUART();ms(6000);while(1) /如果接收到数据,发往PC SetRX_Mode(); if(nRF24L01_RxPacket(RxBuf) R_S_Byte(who); ms(10000); for(i=0;iTX_PLOAD_WIDTH;i+) R_S_Byte(RxBufi); ms(10000); -发送1-uint const ADDRESS0ADR_WIDTH= 0x34,0x43,0x10,0x10,0x01;其余与双工通信相同-发送2-uint const ADDRESS1ADR_WIDTH= 0xc4,0xc3,0xc2,0xc1,0xc0; /频道1接收地址其余与双工通信相同以上就是简要的代码。也是重要的地方。如果发送端要发送数据的话,可能在配置自动应答的接受地址时会遇到一些问题。(因为是以通道0作为应答通道,而发送模式又必须使得接收发送地址一致,这样给两台发送机发数据就要对0实时配置地址)笔者尝试过配置,没有成功,只好不配置了,都是这样接收端无法接收到自动应答的信号24l01双向通讯2010-11-19 21:28 一周的时间过去了,终于搞出来了双向通讯,中间出了点莫名奇妙的情况,导致我迷惘了很久。 上次发的头文件和.c文件有个模式设置的选项。在做双向通信的时候发现这个有点多余。所以就删掉了,内容也做了些小改动。所以就只发修改的部分-24l01.h-这个文件和之前的一样。只去掉/模式选择/#define RMODE#define TMODE这几行-24l01.c-修改了三个地方。分别是1、/*/*NRF24L01初始化/*这里不用设置什么模式,等需要接受或发送数据时指定模式/*/void init_NRF24L01(void) us(100); CE=0; / chip enable CSN=1; / Spi disable SCK=0; / Spi clock line init highSPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); / 写本地地址 SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); / 写接收端地址SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); / 频道0自动 ACK应答允许 SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); / 允许接收地址只有频道0,如果需要多频道可以参考Page21 SPI_RW_Reg(WRITE_REG + RF_CH, 0); / 设置信道工作为2.4GHZ,收发必须一致SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); /设置接收数据长度,本次设置为32字节SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); /设置发射速率为1MHZ,发射功率为最大值0dB2、/*/*函数:void SetRX_Mode(void)/*功能:数据接收配置 /*/void SetRX_Mode(void)CE=0;SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); / IRQ收发完成中断响应,16位CRC ,主接收CE = 1; us(130);3、/*/*函数:void nRF24L01_TxPacket(unsigned char * tx_buf)/*功能:发送 tx_buf中数据/*/void nRF24L01_TxPacket(unsigned char * tx_buf)CE=0; /StandBy I模式 SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); / 装载接收端地址SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); / 装载数据 SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); / IRQ收发完成中断响应,16位CRC,主发送CE=1; /置高CE,激发数据发送us(10);-以上就是全部的修改。这两个文件同样适用于单工通信。以下给出这次测试用的两个主函数。为了方便与上次的文章对应。这里还是以接收,发送区分。-接收-#include nrf24l01.h#include delay.huchar TxBufTX_PLOAD_WIDTH=0x55,0xaa;/*串口初始化*void StartUART( void ) /波特率2400 SCON = 0x50; TMOD = 0x20; TH1 = 0xF3; TL1 = 0xF3; PCON = 0x00; TR1 = 1;/*通过串口将接收到数据发送给PC端*void R_S_Byte(uchar R_Byte) SBUF = R_Byte; while( TI = 0 ); /查询法TI = 0; /*主函数*void main(void)uchar i;uchar RxBufTX_PLOAD_WIDTH; init_NRF24L01() ;StartUART();ms(6000);while(1) /如果接收到数据,发往PC SetRX_Mode(); if(nRF24L01_RxPacket(RxBuf) for(i=0;iTX_PLOAD_WIDTH;i+) R_S_Byte(RxBufi); /发送0x55,0xaa要求发送端发数据 nRF24L01_TxPacket(TxBuf); /SPI_RW_Reg(WRITE_REG+STATUS,0XFF); 加上这句后,会出现接收到几组数据后停止了接收的现象,原因未知 ms(130);/这个延时很重要,延时过短,数据包丢失。 /延时过长,减慢速度,甚至无法接收(实验时出现的问题,原因未知) RxBuf0=0; RxBuf1=0; -发送-include nrf24l01.h#include delay.huchar TxBufTX_PLOAD_WIDTH=0x01,0x02;void main() char RxBufTX_PLOAD_WIDTH=0;init_NRF24L01() ;nRF24L01_TxPacket(TxBuf);ms(6000);while(1) SetRX_Mode(); if(nRF24L01_RxPacket(RxBuf) /将收到的数据发回接收端检验是否正确 /如果设置的数据较长,应使用for循环 TxBuf0=RxBuf0; TxBuf1=RxBuf1; nRF24L01_TxPacket(TxBuf); SPI_RW_Reg(WRITE_REG+STATUS,0XFF); ms(90);/这个延时一样很重要 RxBuf0=0; RxBuf1=0; -以上就是这周忙活的东西了,高手不要见笑。PS:原先想要使用自动重发功能的,结果发现自动重发的话,传输速率很慢,没有延时的快。也可能是我自动重发的延时没设置好。另外最开始几天一直在做中断通信,如果使用IRQ上中断来接受数据,可以明显减轻MCU的负担。可是我测试了几天下来发现一个无语的结果。在中断里读出来的STATUS 的值是0x00,顿时心灰意冷。网上有其他人貌似做出来了,可惜我写的跟他们一样也不行啊,不知道问题在哪。但有一点是肯定的:接收到数据时必然引起中断。过几天继续贴出多机通信的代码。nrf24l01的51驱动程序2010-11-13 18:58 随着物联网时代的到来,无线通信技术日趋重要。 nrf24l01是适合初学入门的无线模块。于是乎我就一头埋进去,苦干一周有余。发现网上的程序都是抄来抄去的,不甚寒心。抄也就算了,光抄错的!后来自己动手研究,完成了SPI接口的操作,继续攻克无线模块,最终无果,只好再找代码。终于找到了一个可以的。 本来想直接贴出来的,但为了许多和我曾经一样迷茫的同胞可以顺利进入无线领域。我特意修改代码,整理出nrf24l01.h与nrf24l01.c,一则便于模块化管理,二则,便于使用,便于二次开发。同时,增加了许多注释。 代码中应该还有许多不足的,甚至多余的东西,后续将会继续发表一篇关于无线模块开发的注意事项。/-nrf24l01.h-#ifndef NRF24L01_H#define NRF24L01_H#include /模式选择/#define RMODE#define TMODEtypedef unsigned char uchar;typedef unsigned char uint;/*SPI-IO端口*sbit CE = P10;/3sbit SCK = P11;/5sbit MISO = P12;/7sbit CSN = P15;/4sbit MOSI = P16;/6sbit IRQ = P17;/8/*地址、数据长度*#define TX_ADR_WIDTH 5 / 5 uints TX address width#define RX_ADR_WIDTH 5 / 5 uints RX address width#define TX_PLOAD_WIDTH 32 / 20 uints TX payload#define RX_PLOAD_WIDTH 32 / 20 uints TX payload/*NRF24L01寄存器指令*#define READ_REG 0x00 / 读寄存器指令#define WRITE_REG 0x20 / 写寄存器指令#define RD_RX_PLOAD 0x61 / 读取接收数据指令#define WR_TX_PLOAD 0xA0 / 写待发数据指令#define FLUSH_TX 0xE1 / 冲洗发送 FIFO指令#define FLUSH_RX 0xE2 / 冲洗接收 FIFO指令#define REUSE_TX_PL 0xE3 / 定义重复装载数据指令#define NOP 0xFF / 保留/*SPI(nRF24L01)寄存器地址*#define CONFIG 0x00 / 配置收发状态,CRC校验模式以及收发状态响应方式#define EN_AA 0x01 / 自动应答功能设置#define EN_RXADDR 0x02 / 可用信道设置#define SETUP_AW 0x03 / 收发地址宽度设置#define SETUP_RETR 0x04 / 自动重发功能设置#define RF_CH 0x05 / 工作频率设置#define RF_SETUP 0x06 / 发射速率、功耗功能设置#define STATUS 0x07 / 状态寄存器#define OBSERVE_TX 0x08 / 发送监测功能#define CD 0x09 / 地址检测 #define RX_ADDR_P0 0x0A / 频道0接收数据地址#define RX_ADDR_P1 0x0B / 频道1接收数据地址#define RX_ADDR_P2 0x0C / 频道2接收数据地址#define RX_ADDR_P3 0x0D / 频道3接收数据地址#define RX_ADDR_P4 0x0E / 频道4接收数据地址#define RX_ADDR_P5 0x0F / 频道5接收数据地址#define TX_ADDR 0x10 / 发送地址寄存器#define RX_PW_P0 0x11 / 接收频道0接收数据长度#define RX_PW_P1 0x12 / 接收频道0接收数据长度#define RX_PW_P2 0x13 / 接收频道0接收数据长度#define RX_PW_P3 0x14 / 接收频道0接收数据长度#define RX_PW_P4 0x15 / 接收频道0接收数据长度#define RX_PW_P5 0x16 / 接收频道0接收数据长度#define FIFO_STATUS 0x17 / FIFO栈入栈出状态寄存器设置/*void init_NRF24L01(void);uint SPI_RW(uint uchar);uchar SPI_Read(uchar reg);void SetRX_Mode(void);uint SPI_RW_Reg(uchar reg, uchar value);uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars);uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars);unsigned char nRF24L01_RxPacket(unsigned char* rx_buf);void nRF24L01_TxPacket(unsigned char * tx_buf);/*#endif/-nrf24l01.h结束-/-nrf24l01.c-#include nrf24l01.h#include delay.huint bdata sta; /状态标志sbit RX_DR =sta6;sbit TX_DS =sta5;sbit MAX_RT =sta4;uint const TX_ADDRESSTX_ADR_WIDTH= 0x34,0x43,0x10,0x10,0x01; /本地地址uint const RX_ADDRESSRX_ADR_WIDTH= 0x34,0x43,0x10,0x10,0x01; /接收地址/*/*NRF24L01初始化/*/void init_NRF24L01(void) us(100); CE=0; / chip enable CSN=1; / Spi disable SCK=0; / Spi clock line init highSPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); / 写本地地址 SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); / 写接收端地址SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); / 频道0自动 ACK应答允许 SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); / 允许接收地址只有频道0,如果需要多频道可以参考Page21 SPI_RW_Reg(WRITE_REG + RF_CH, 0); / 设置信道工作为2.4GHZ,收发必须一致SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); /设置接收数据长度,本次设置为32字节SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); /设置发射速率为1MHZ,发射功率为最大值0dB#ifdef RMODESPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); / IRQ收发完成中断响应,16位CRC ,主接收#endif#ifdef TMODESPI_RW_Reg(WRITE_REG + CONFIG, 0x0E); / IRQ收发完成中断响应,16位CRC ,主接收#endif/*/*函数:uint SPI_RW(uint uchar)/*功能:NRF24L01的SPI写时序/*/uint SPI_RW(uint uchar)uint bit_ctr; for(bit_ctr=0;bit_ctr8;bit_ctr+) / output 8-bit MOSI = (uchar & 0x80); / output uchar, MSB to MOSI uchar = (uchar 1); / shift next bit into MSB. SCK = 1; / Set SCK high. uchar |= MISO; / capture current MISO bit SCK = 0; / .then set SCK low again return(uchar); / return read uchar/*/*函数:uchar SPI_Read(uchar reg)/*功能:NRF24L01的SPI时序/*/uchar SPI_Read(uchar reg)uchar reg_val;CSN = 0; / CSN low, initialize SPI communication.SPI_RW(reg); / Select register to read from.reg_val = SPI_RW(0); / .then read registervalueCSN = 1; / CSN high, terminate SPI communicationreturn(reg_val); / return register value/*/*功能:NRF24L01读写寄存器函数/*/uint SPI_RW_Reg(uchar reg, uchar value)uint status;CSN = 0; / CSN low, init SPI transactionstatus = SPI_RW(reg); / select registerSPI_RW(value); / .and write value to it.CSN = 1; / CSN high againreturn(status); / return nRF24L01 status uchar/*/*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数/*/uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)uint status,uchar_ctr;CSN = 0; / Set CSN low, init SPI tranactionstatus = SPI_RW(reg); / Select register to write to and read status ucharfor(uchar_ctr=0;uchar_ctruchars;uchar_ctr+) pBufuchar_ctr = SPI_RW(0); / CSN = 1; return(status); / return nRF24L01 status uchar/*/*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数/*/uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)uint status,uchar_ctr;CSN = 0; /SPI使能 status = SPI_RW(reg); for(uchar_ctr=0; uchar_ctruchars; uchar_ctr+) / SPI_RW(*pBuf+);CSN = 1; /关闭SPIreturn(status); / /*/*函数:void SetRX_Mode(void)/*功能:数据接收配置 /*/void SetRX_Mode(void)CE=0;#ifdef TMODESPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); / IRQ收发完成中断响应,16位CRC ,主接收#endifCE = 1; us(130);/*/*函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)/*功能:数据读取后放如rx_buf接收缓冲区中/*/unsigned char nRF24L01_RxPacket(unsigned char* rx_buf) unsigned char revale=0;sta=SPI_Read(STATUS); / 读取状态寄存其来判断数据接收状况if(RX_DR) / 判断是否接收到数据 CE = 0; /SPI使能 SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);/ read receive payload from RX_FIFO buffer revale =1; /读取数据完成标志SPI_RW_Reg(WRITE_REG+STATUS,sta); /接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志return revale;/*/*函数:void nRF24L01_TxPacket(unsigned char * tx_buf)/*功能:发送 tx_buf中数据/*/void nRF24L01_TxPacket(unsigned char * tx_buf)CE=0; /StandBy I模式 SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); / 装载接收端地址SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); / 装载数据#ifdef RMODE SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); / IRQ收发完成中断响应,16位CRC,主发送#endifCE=1; /置高CE,激发数据发送us(10);/-nrf24l01.c结束-文中用到的“delay.h”中一个us延时,一个ms延时,读者可以自己写。(由于晶振不同,延时函数不同,这里就不列出了)这两个文件同时包含了收发模式。通过/模式选择#define RMODE/#define TM
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025版个人知识产权纠纷仲裁协议合同范本
- 二零二五版本二手房买卖合同含购房人征信查询及审核
- 二零二五年度房屋装修设计与改造施工合同
- 2025版智能拆除技术应用于工业厂房合同范本
- 2025版掘进机租赁合同暨施工材料供应与验收服务协议
- 鹦鹉知识课件教学
- 二手房卖房协议附带房屋租赁权及租赁期满续约协议
- 吊装运输设备检验与认证合同
- 二零二五年度水利工程改造承包劳务合同范本
- 二零二五年度特色老房改造买卖合同示范
- 2025年新疆维吾尔自治区事业单位教师招聘美术学科专业知识试卷
- 小说中苦难叙事的艺术表现及其情感影响研究
- 北森心理测评试题及答案
- 政府补助专项管理制度
- 大学生心理健康教育试题库及参考答案
- DB32/T 3669-2019人民调解委员会建设规范
- 护理康复操作规范
- 软组织损伤课件
- 工资欠薪协商协议书
- 直播切片授权协议书
- 影视剧组演员保密协议
评论
0/150
提交评论