已阅读5页,还剩14页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
说实话,对于一个初次调试这个模块的同学,想要找一个直接可用的程序不好找,同时是找到的片 段程序很多又是木有注释的,我们(菜鸟)没有很好的理解芯片资料的能力,看着都是一头雾水。 在这儿,我贴出发送和接收两部分,希望可以让学习者轻松一点理解和掌握其操作流程。同时声明 一下,下面的程序不是我写的,但是99%的注释是我写的,对于掌握的人来说,不需要这样多的注 释,我是面对需要学习的人而写的。这样也算是我对电子技术给我的乐趣的回馈。在没有和程序作 者取得联系的情况下我修改一部分且直接贴上百度,希望见谅,我们都是希望这对大家的学习有所 帮助! 注释的位置需要调整一下哦 以下是发送端程序: #include #include #define MODE 0 /MODE=1时为发送代码MODE=0时为接收代码 typedef unsigned char uchar; /*IO 端口定义* sbit MISO = P23; sbit MOSI = P22; sbit SCK = P21; sbit CE = P25; sbit CSN = P20; sbit IRQ = P32; sbit led = P12; /* uchar bdata sta; /状态标志 sbit RX_DR = sta6; sbit TX_DS = sta5; sbit MAX_RT = sta4; /*NRF24L01* #define TX_ADR_WIDTH5 / 5 uints TX address width #define RX_ADR_WIDTH5 / 5 uints RX address width #define TX_PLOAD_WIDTH32 / 32 uints TX payload #define RX_PLOAD_WIDTH32 / 32 uints TX payload uchar const TX_ADDRESS TX_ADR_WIDTH = 0x34,0x43,0x10,0x10,0x01; /本地地址 uchar const RX_ADDRESS RX_ADR_WIDTH = 0x34,0x43,0x10,0x10,0x01; /接收地址 ucharcodeTx_BufTX_PLOAD_WIDTH= 0xff,0xee,0x11,0x22,0x33,0xaa,0xbb,0x11,0x22,0x33,0xaa,0xbb, 0x11,0x22,0x33,0xaa, 0xbb,0x11,0x22,0x33,0xaa,0xbb,0x11,0x22,0x33,0xaa,0xbb,0x11,0x22,0x33,0xee,0xff;/发 送数据 uchar Rx_BufRX_PLOAD_WIDTH;/接收数据 /*NRF24L01 寄存器指令* #define READ_REG0x00 / 读寄存器指令 #define WRITE_REG0x20 / 写寄存器指令 #define RD_RX_PLOAD0x61 / 读取接收数据指令 #define WR_TX_PLOAD0xA0 / 写待发数据指令 #define FLUSH_TX0xE1 / 冲洗发送FIFO指令 #define FLUSH_RX0xE2 / 冲洗接收FIFO指令 #define REUSE_TX_PL0xE3 / 定义重复装载数据指令 #define NOP0xFF / 保留 /*SPI(nRF24L01) 寄存器地址* #define CONFIG0x00 / 配置收发状态,CRC校验模式以及收发状态响应方式 #define EN_AA0x01 / 自动应答功能设置 #define EN_RXADDR0x02 / 可用信道设置 #define SETUP_AW0x03 / 收发地址宽度设置 #define SETUP_RETR0x04 / 自动重发功能设置 #define RF_CH0x05 / 工作频率设置 #define RF_SETUP0x06 / 发射速率、功耗功能设置 #define STATUS0x07 / 状态寄存器 #define OBSERVE_TX0x08 / 发送监测功能 #define CD0x09 / 地址检测 #define RX_ADDR_P00x0A / 频道0接收数据地址 #define RX_ADDR_P10x0B / 频道1接收数据地址 #define RX_ADDR_P20x0C / 频道2接收数据地址 #define RX_ADDR_P30x0D / 频道3接收数据地址 #define RX_ADDR_P40x0E / 频道4接收数据地址 #define RX_ADDR_P50x0F / 频道5接收数据地址 #define TX_ADDR0x10 / 发送地址寄存器 #define RX_PW_P00x11 / 接收频道0接收数据长度 #define RX_PW_P10x12 / 接收频道0接收数据长度 #define RX_PW_P20x13 / 接收频道0接收数据长度 #define RX_PW_P30x14 / 接收频道0接收数据长度 #define RX_PW_P40x15 / 接收频道0接收数据长度 #define RX_PW_P50x16 / 接收频道0接收数据长度 #define FIFO_STATUS0x17 / FIFO栈入栈出状态寄存器设置 /*延时函数 */ void Delay( unsigned int s )/长延时 unsigned int i,j; for( i = 0;i 1000; i+ )for( j = 0; j s; j+ ); void delay_ms( unsigned int x )/短延时 unsigned int i,j; i = 0; for( i = 0; i x; i+ ) j = 108; while( j- ); /*IO口模拟SPI总线代码 */ uchar SPI_RW( uchar byte )/SPI边发送边接收,这儿写法值得学习,减少形参 uchar bit_ctr; for( bit_ctr = 0; bit_ctr 8; bit_ctr+ ) MOSI = ( byte /取最高位发送 byte = ( byte 1 );/不断地填补到最高位 SCK = 1; byte |= MISO;/把接收到的数据一位一位的补充到byte中去,这样就不 需要多定义变量 /led=MISO;Delay(150); SCK = 0; return( byte );/byte就是从机的答复 /* 通 过 spi 通 讯 的 方 式 对 模 块 进 行 写 操 作 * uchar SPI_RW_Reg ( uchar reg, uchar value ) / 向寄存器REG写一个字节,同时返回状态字节, 这里关系到模块的操作, /你要给模块发送命令, 然后它回复你表示收到了指 令,然后执行你的指令 uchar status; CSN = 0; status = SPI_RW(reg);/ reg就是我们按照资料给模块的指令,SPI_RW(reg)的 return值就是模块的答复,也就是告诉单片机它现在的状态,它要干什么。 SPI_RW( value );/ value就是我们需要传输的内容,这里就是给它发送我们要 它发送东西的指令,接着我们就把要发送的东西给它。 CSN = 1; return( status );/之所以要return一个status, 是因为我们要知道模块有没有发送 了 /* 通 过 spi 通 讯 方 式 将 模 块 收 到 的 数 据 读 取 到 单 片 机 * uchar SPI_Read ( uchar reg )/这里的reg和上面的reg不一样,他们在不同的作用域,所以不 会有什么干扰,就是看起来会乱 uchar reg_val; CSN = 0; SPI_RW( reg ); reg_val = SPI_RW(0);/0是什么指令呢?到上面看一下,哦, ,原来是读寄存器 指令,返回来的自然是寄存器里面存下来已经接收到的值 CSN = 1; return( reg_val );/将模块接收到的值返回给单片机老大 /* 告 诉 模 块 写 信 人 和 收 信 人 的 地 址 的 函 数 * uchar SPI_Write_Buf( uchar reg, uchar *pBuf, uchar bytes ) uchar status,byte_ctr; CSN = 0; / Set CSN low, init SPI tranaction这不用说了,看时序图 status = SPI_RW( reg ); / Select register to write to and read status byte告诉模块 我准备发送东西 for( byte_ctr = 0; byte_ctr bytes; byte_ctr+ ) / then write all byte in buffer(*pBuf) 告诉模块我要发送东西 SPI_RW( *pBuf+ );/每发出去指针就后移一位,这写法值得学习 CSN = 1; / Set CSN high again这不用说了,看时序图 return( status ); / return nRF24L01 status byte看看模块的状态,知道它是否发送 了还是在偷懒 /*发 *送 *模 *式 *代 *码 */ void TX_Mode(void)/开始我也不习惯TX是发送的意思,总得习惯的,大家都一样下面就 是模块设置,写什么指令,要模块怎样怎样 CE = 0; SPI_RW_Reg( FLUSH_TX, 0x00 );/FLUSH_TX是冲洗发送FIFO数据缓存器的意思, FIFO 是英文First In First Out 的缩写,是一种先进先出的数据缓存器,最好百度一下 SPI_Write_Buf( WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH ); / Writes TX_Address to nRF24L01复杂,其实就是告诉模块发送地址和发送地址位宽,看上面的定义 /也就是我告诉邮递员你要把信送到哪儿去,这是地址。 SPI_Write_Buf(WRITE_REG+RX_ADDR_P0,TX_ADDRESS,TX_ADR_WIDTH); /RX_Addr0 same as TX_Adr for Auto.Ack把写信和收信的地址配对好。 SPI_RW_Reg( WRITE_REG + EN_AA, 0x01 ); / Enable Auto.Ack:Pipe0使能自动回复 通道0我要你模块有自动回复的功能,同样是对模块写指令 SPI_RW_Reg( WRITE_REG + EN_RXADDR, 0x01 ); / Enable Pipe0告诉模块通过那个 通道传送信息,0x01没搞懂 SPI_RW_Reg( WRITE_REG + SETUP_RETR, 0x1a ); / 500us + 86us, 10 retrans.1a 开启自动重发功能 SPI_RW_Reg( WRITE_REG + RF_CH, 40 ); / Select RF channel 40设 置工作频率为40hz SPI_RW_Reg(WRITE_REG+RF_SETUP,0x07);/TX_PWR:0dBm, Datarate:1Mbps,LNA:HCURR发射速率、功耗功能设置 SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); /设置接收数据长度,本次 设置为2字节 SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);/配置收发状态,CRC校验模式以及收发 状态响应方式 CE=1; delay_ms(100);/设置完毕,说白了就是模块的初始化 /*上面对模块初始化好了,那么这个函数就是发送数据啦! * void Transmit( unsigned char * tx_buf ) CE = 0; /StandBy I模式 SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); / 装载接 收端地址 SPI_RW_Reg( FLUSH_TX, 0x00 ); /FLUSH_TX是冲洗发送FIFO数据缓存器的意思,上面出 现过,但是还是讲一下 SPI_Write_Buf( WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH ); / 终于,我们等的就是这 一刻,告诉模块我们要发送的数据和数据位宽 /WR_TX_PLOAD是写发送数据的指令,Tx_Buf是数组名,也是指针,TX_PLOAD_WIDTH是数据 宽度 SPI_RW_Reg( WRITE_REG + CONFIG, 0x0e ); / IRQ收发完成中断响应,16位CRC,主发 送 /CRC是循环冗余码校 验这是模块的工作,我们要他这样做,谁叫他有这功能 CE = 1; /置高CE,激发数据发送 delay_ms( 150 ); /*到主函数啦 * void main( void ) CE = 0; SCK = 0; CSN = 1;/设置模块为发送模式 P1 = 0x00; TX_Mode();/初始化模块使之做好发送工作 /SPI_RW_Reg(FLUSH_RX,0x00); while(1) Transmit(Tx_Buf);/传送数据 Delay(10); sta=SPI_Read(READ_REG + STATUS);/读出模块的状态,我要知道其是否 成功发送了,看下面吧 if(TX_DS) P1=sta; /8位LED显示当前STATUS状态发送中断应使bit5 = 1 灯灭 Delay(100); SPI_RW_Reg(WRITE_REG + STATUS,sta);/不懂 if(MAX_RT) /如果发送超时 P1=0x0f; /发送超时时8位LED灯bit4 = 1 灯灭 Delay(150); SPI_RW_Reg(WRITE_REG + STATUS,sta);/不懂 以下是接收端程序: #include #include #define MODE 0 /MODE=1时为发送代码MODE=0时为接收代码 typedef unsigned char uchar; /*IO 端口定义 sbit MISO = P23; sbit MOSI = P22; sbit SCK = P21; sbit CE = P25; sbit CSN = P20; sbit IRQ = P32; sbit led = P12; sbit led1 = P30; sbit led2 = P31; sbit led3 = P36; sbit led4 = P37; /* uchar bdata sta; /状态标志 sbit RX_DR = sta6; sbit TX_DS = sta5; sbit MAX_RT = sta4; /*NRF24L01* * #define TX_ADR_WIDTH5 / 5 uints TX address width #define RX_ADR_WIDTH5 / 5 uints RX address width #define TX_PLOAD_WIDTH32 / 32 uints TX payload #define RX_PLOAD_WIDTH32 / 32 uints TX payload uchar const TX_ADDRESS TX_ADR_WIDTH = 0x34,0x43,0x10,0x10,0x01; /本地地址 uchar const RX_ADDRESS RX_ADR_WIDTH = 0x34,0x43,0x10,0x10,0x01; /接收地址 ucharcodeTx_BufTX_PLOAD_WIDTH= 0xff,0xee,0x11,0x22,0x33,0xaa,0xbb,0x11,0x22,0x33,0xaa,0xbb, 0x11,0x22,0x33,0xaa, 0xbb,0x11,0x22,0x33,0xaa,0xbb,0x11,0x22,0x33,0xaa,0xbb,0x11,0x22,0x33,0xee,0xff;/发 送数据 uchar Rx_BufRX_PLOAD_WIDTH;/接收数据 /*NRF24L01寄存器指令 * #define READ_REG0x00 / 读寄存器指令 #define WRITE_REG0x20 / 写寄存器指令 #define RD_RX_PLOAD0x61 / 读取接收数据指令 #define WR_TX_PLOAD0xA0 / 写待发数据指令 #define FLUSH_TX0xE1 / 冲洗发送FIFO指令 #define FLUSH_RX0xE2 / 冲洗接收FIFO指令 #define REUSE_TX_PL0xE3 / 定义重复装载数据指令 #define NOP0xFF / 保留 /*SPI(nRF24L01)寄存器地址 * #define CONFIG0x00 / 配置收发状态,CRC校验模式以及收发状态响应方式 #define EN_AA0x01 / 自动应答功能设置 #define EN_RXADDR0x02 / 可用信道设置 #define SETUP_AW0x03 / 收发地址宽度设置 #define SETUP_RETR0x04 / 自动重发功能设置 #define RF_CH0x05 / 工作频率设置 #define RF_SETUP0x06 / 发射速率、功耗功能设置 #define STATUS0x07 / 状态寄存器 #define OBSERVE_TX0x08 / 发送监测功能 #define CD0x09 / 地址检测 #define RX_ADDR_P00x0A / 频道0接收数据地址 #define RX_ADDR_P10x0B / 频道1接收数据地址 #define RX_ADDR_P20x0C / 频道2接收数据地址 #define RX_ADDR_P30x0D / 频道3接收数据地址 #define RX_ADDR_P40x0E / 频道4接收数据地址 #define RX_ADDR_P50x0F / 频道5接收数据地址 #define TX_ADDR0x10 / 发送地址寄存器 #define RX_PW_P00x11 / 接收频道0接收数据长度 #define RX_PW_P10x12 / 接收频道0接收数据长度 #define RX_PW_P20x13 / 接收频道0接收数据长度 #define RX_PW_P30x14 / 接收频道0接收数据长度 #define RX_PW_P40x15 / 接收频道0接收数据长度 #define RX_PW_P50x16 / 接收频道0接收数据长度 #define FIFO_STATUS0x17 / FIFO栈入栈出状态寄存器设置 /*延时函数 */ void Delay( unsigned int s )/长延时 unsigned int i,j; for( i = 0;i 1000; i+ )for( j = 0; j s; j+ ); void delay_ms( unsigned int x )/短延时 unsigned int i,j; i = 0; for( i = 0; i x; i+ ) j = 108; while( j- ); /*IO口模拟SPI总线代码 */ uchar SPI_RW( uchar byte )/SPI边发送边接收,这儿写法值得学习,减少形参 uchar bit_ctr; for( bit_ctr = 0; bit_ctr 8; bit_ctr+ ) MOSI = ( byte /取最高位发送 byte = ( byte 1 );/不断地填补到最高位 SCK = 1; byte |= MISO;/把接收到的数据一位一位的补充到byte中去,这样就不 需要多定义变量 /led=MISO;Delay(150); SCK = 0; return( byte );/byte就是从机的答复 /* 通 过 spi 通 讯 的 方 式 对 模 块 进 行 写 操 作 * uchar SPI_RW_Reg ( uchar reg, uchar value ) / 向寄存器REG写一个字节,同时返回状态字节, 这里关系到模块的操作, /你要给模块发送命令, 然后它回复你表示收到了指 令,然后执行你的指令 uchar status; CSN = 0; status = SPI_RW(reg);/ reg就是我们按照资料给模块的指令,SPI_RW(reg)的 return值就是模块的答复,也就是告诉单片机它现在的状态,它要干什么。 SPI_RW( value );/ value就是我们需要传输的内容,这里就是给它发送我们要 它发送东西的指令,接着我们就把要发送的东西给它。 CSN = 1; return( status );/之所以要return一个status, 是因为我们要知道模块有没有发送 了 /* 通 过 spi 通 讯 方 式 将 模 块 收 到 的 数 据 读 取 到 单 片 机 * uchar SPI_Read ( uchar reg )/这里的reg和上面的reg不一样,他们在不同的作用域,所以不 会有什么干扰,就是看起来会乱 uchar reg_val; CSN = 0; SPI_RW( reg ); reg_val = SPI_RW(0);/0是什么指令呢?到上面看一下,哦, ,原来是读寄存器 指令,返回来的自然是寄存器里面存下来已经接收到的值 CSN = 1; return( reg_val );/将模块接收到的值返回给单片机老大 /* 告 诉 模 块 写 信 人 和 收 信 人 的 地 址 的 函 数 * uchar SPI_Write_Buf( uchar reg, uchar *pBuf, uchar bytes ) uchar status,byte_ctr; CSN = 0; / Set CSN low, init SPI tranaction这不用说了,看时序图 status = SPI_RW( reg ); / Select register to write to and read status byte告诉模块 我准备发送东西 for( byte_ctr = 0; byte_ctr bytes; byte_ctr+ ) / then write all byte in buffer(*pBuf) 告诉模块我要发送东西 SPI_RW( *pBuf+ );/每发出去指针就后移一位,这写法值得学习 CSN = 1; / Set CSN high again这不用说了,看时序图 return( status ); / return nRF24L01 status byte看看模块的状态,知道它是否发送 了还是在偷懒 /*接 * 收 *模 *式 *代 *码 */ uchar SPI_Read_Buf( uchar reg, uchar *pBuf, uchar uchars)/读数据函数 unsigned charstatus,uchar_ctr; CSN = 0; / Set CSN low, init SPI tranaction不用讲,看时序图 status = SPI_RW(reg); / Select register to write to and read status uchar写指令 for(uchar_ctr = 0; uchar_ctr uchars; uchar_ctr+ ) pBuf uchar_ctr = SPI_RW( 0 ); /逐位读出数据 CSN = 1; return( status ); / return nRF24L01 status uchar看状态,知道有模块有没有工作 /* */ /*函数: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,RX_PLOAD_WIDTH);/readreceive payload from RX_FIFO buffer 和发送程序一样,一个是指令,一个是指针,一个是宽度 revale =1; /读取数据完成标志 /Delay(100); SPI_RW_Reg(W
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 跳棋演示软件功能详解
- 2025检验科c反应蛋白在感染性疾病中的应用培训教程
- 消防灭火基础知识
- 检验科社区小科普
- 防疟疾安全教育
- 招聘的程序与方法
- 租借车牌协议书
- 陶瓷合作协议书
- 2025-2026学年安徽省阜阳市五年级道德与法治上册期中考试试卷及答案
- 2025年湘教版八年级道德与法治上册月考考试试题及答案
- 广东省深圳市罗湖区2024-2025学年八年级上学期11月期中考试数学试题(含答案)
- 医疗设备投放协议书
- 数据库备份恢复计划
- 招投标审计知识培训课件
- 2025年版会计继续教育试题及答案
- 2025年公共基础知识试题库附参考答案
- 基于16PF的保险业销售人员选拔与绩效预测:理论、实践与展望
- 2025年大数据行业营销策略创新方案可行性分析报告
- 2024年成人高等考试《政治》(专升本)试题真题及答案
- 2025年网络安全测评师考试试题及答案
- 《犟龟》课件 部编语文三年级上册
评论
0/150
提交评论