30、51单片机应用之............无线通讯模块NRF24L01+(一)基础知识篇今天刚调试好,先看图吧!这张是AT89C2051控制NRF24L01+做发射调试。
看看NRF24L01细节吧!这是LCD屏显示:AT89S52做接收测试:正在接收时的显示:接收到数据后显示32个数据值:无线模块NRF24L01+应用上篇结束,敬请期待NRF24L01+下篇的调试部分。
31、51单片机应用之............无线通讯模块NRF24L01+(二)模块调试篇32、51单片机应用之............无线通讯模块NRF24L01+(三)发送与接收模块的联调33、51单片机应用之............无线通讯模块NRF24L01+(四)举例应用34、补充NRF24L01+之————LED调试篇写了前面四篇关于NRF24L01通讯调试的文章,看来大家还是很喜欢,有帮助的。
有很多大学生朋友问我说,我们没有两个LCD来显示调试状态,连一个也没有,能不能用几个LED来显示调试状态呢?因此我就写这篇补充调试的文章,就用P0口的8个LED来显示调试NRF24L01到成功进行数据通讯。
先把51单片机的最小系统准备好,还有8个LED的小电路板,如果你的LED就在系统板上那省了这一步。
8个LED的小板子电路很简单,但你焊接要可靠,不然电路本身都不稳定,后面对判断故障会产生很大影响。
NRF24L01+模块电路还是前面说过的那样:相同的两个模块的板子。
好!假设我们用P0口来作LED显示、用P1口来作模块接口,下面我们先写一段最简单的程序,来确认LED电路,和P0、P1口的完好!#include <reg52.h>#include <intrins.h>#define uint unsigned inttypedef unsigned char uchar;//*********************************//延时函数// 在晶振为12MHz时,延时count毫秒//*********************************void Delayms(uint count){uint i;while(count--){ for(i=0;i<80;i++){}}_nop_();_nop_();_nop_();_nop_();_nop_();}//*********************************// 主函数//*********************************void main(){P0=0x00; //P0口LED点亮P1=0x00; //P1口LED点亮P2=0x00;P3=0x00;Delayms(2000); //延时2秒while(1){P0=~P0;//将P0口数据取反,原来亮的就熄灭P1=~P1;//将P1口数据取反,原来亮的就熄灭P2=~P2;P3=~P3;Delayms(500); //延时半秒}}这是段极简单的程序,用来检测单片机电路连接的正确性,和IO口的工作状态是否正常,为后面调试NRF24L01做好准备。
它的工作状态如下:同样的,把LED的接口再接到P1口,看看它是否一样的在全部闪烁。
做好了这步,准备工作就算完成了。
接下来我们把NRF24L01+的模块插上,要注意,接口要对清楚,电源要连接正确:接下来我们写发送程序://**********************************// NRF24L01+模块发射程序// 用8个LED调试// Txz001 2012.05.16//**********************************#include <reg52.h>typedef unsigned char uchar; //将无符号字节类型重定义为uchartypedef unsigned int uint; //将无符号整数类型重定义为Uint//*********************NRF24L01函数定义****************************void delayms(uint t);//毫秒延时void init_NRF24L01(void); //模块初始化函数uchar SPI_RW(uchar reg); //基本SPI读写时序uchar SPI_Read(uchar reg); //从寄存器reg读一个字节void SetRX_Mode(void); //设置接收模式uchar SPI_RW_Reg(uchar reg, uchar value); //向寄存器写一个字节uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars); // 从缓冲器读出uchars字节的数据uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars); //向缓冲器写进uchars字节的数据void nRF24L01_TxPacket(uchar * tx_buf); //启动一次发送uchar nRF24L01_RxPacket(uchar * rx_buf);//读取接收的数据,放入rx_buf数组//***********NRF24L01模块IO端口定义******************sbit CE=P1^0;sbit CSN =P1^1;sbit SCK =P1^2;sbit MOSI =P1^3;sbit MISO =P1^4;sbit IRQ =P1^5;//*****************NRF24L01常量**********************#define TX_ADR_WIDTH 5 //发送地址宽度5字节#define RX_ADR_WIDTH 5 //接收地址宽度5字节#define TX_PLOAD_WIDTH 32 // 发送数据宽度32字节#define RX_PLOAD_WIDTH 32 //接收数据的宽度32字节uchar const TX_ADDRESS[TX_ADR_WIDTH]= {0x01,0x02,0x03,0x04,0x05}; //本地地址uchar const RX_ADDRESS[RX_ADR_WIDTH]= {0x01,0x02,0x03,0x04,0x05}; //接收地址//*****************NRF24L01寄存器指令*******************#define READ_REG 0x00 // 读寄存器指令#define WRITE_REG 0x20 // 写寄存器指令#define RD_RX_PLOAD 0x61 // 读取接收数据指令#define WR_TX_PLOAD 0xA0 // 写待发数据指令#define FLUSH_TX 0xE1 //清空发送缓冲区//**************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 STA TUS 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 delayms(uint t) //约延时t毫秒{uint i;while(t--){for(i=0;i<125;i++);}}/**********************************************/*函数:uint SPI_RW(uint uchar)/*功能:NRF24L01的SPI写时序/**********************************************/uchar SPI_RW(uchar uuchar){uchar bit_ctr;for(bit_ctr=0;bit_ctr<8;bit_ctr++) // 输出8个位{MOSI = (uuchar & 0x80); //输出uuhar的最高位uuchar = (uuchar << 1); //左移一位SCK = 1; // 将时钟线置‘1’uuchar |= MISO; //同时读取STA TUSSCK = 0; //然后再将时钟线置‘0’}return(uuchar); //返回读取的值}/***********************************************/*函数:uchar SPI_Read(uchar reg)/*功能:NRF24L01的SPI读取一个字节时序/***********************************************/uchar SPI_Read(uchar reg){uchar reg_val;CSN = 0; //CSN置'0',允许指令操作SPI_RW(reg); //写一条reg指令reg_val = SPI_RW(0); //读取reg的值到reg_valCSN = 1; //CSN置'1',禁示操作return(reg_val); //返回读取的值}/***********************************************/*功能:NRF24L01写一个字节到寄存器函数/***********************************************/uchar SPI_RW_Reg(uchar reg, uchar value){uchar status;CSN = 0; // CSN置'0',允许操作status = SPI_RW(reg); //这指令,并读STA TUSSPI_RW(value); //写数据值到regCSN = 1; // CSN置'1',禁止操作return(status); // return nRF24L01 status uchar}/***************************************************************** /*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于写数据:reg:为寄存器地址,/* pBuf:为待写入数据地址,/* uchars:写入数据的个数/*****************************************************************/ uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars){uchar status,uchar_ctr;CSN = 0; //SPI使能status = SPI_RW(reg);for(uchar_ctr=0; uchar_ctr<uchars; uchar_ctr++) //SPI_RW(*pBuf++);CSN = 1; //关闭SPIreturn(status); //}//******************************************/*NRF24L01初始化//******************************************/void init_NRF24L01(void){delayms(1);CE=0; // 射频停止工作CSN=1; // 停止寄存器读写SCK=0; //时种信号停止读写IRQ=1;//中断复位SPI_RW_Reg(WRITE_REG + EN_AA, 0x00); // 频道0自动ACK应答禁止SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x00); //禁止自动发送SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 允许接收地址只有频道0,SPI_RW_Reg(WRITE_REG + RF_CH, 1); // 设置信道工作为2.4GHZ,收发必须一致SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); //设置发射速率为2MHZ,发射功率为最大值0dB}/******************************************************/*函数: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 + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写本地地址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,激发数据发送delayms(1);}//************************************// 主函数//************************************void main(){uchar TxBuf[32];uchar status; //定义一个变量用来装读取到的STA TUS数值init_NRF24L01();//NRF24L01初始化SPI_RW_Reg(WRITE_REG+STA TUS,0XFF); //清状态寄存器status=SPI_Read(STA TUS); //读取状态P0=~status;//P0口显示读取的状态delayms(4000);//显示延时4秒,以便从容看清楚P0=0xff;//清除显示。