nrf24l01的C程序
STM32驱动NRF24L01 C语言程序
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
#define MAX_TX #define TX_OK #define RX_OK /********* #define #define #define #RX_ADR_WIDTH TX_PLOAD_WIDTH RX_PLOAD_WIDTH
Page 3
// // // // // //
/**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO PA7 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = SCK_Pin|MISO_Pin|MOSI_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF0_SPI1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE END 0 */ SPI_HandleTypeDef hspi1; /* SPI1 init function */ void MX_SPI1_Init(void) { hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 7; hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE; hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE; if (HAL_SPI_Init(&hspi1) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } } void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle) { GPIO_InitTypeDef GPIO_InitStruct; if(spiHandle->Instance==SPI1) { /* USER CODE BEGIN SPI1_MspInit 0 */ /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE();
NRF24L01数据通信C程序
Description:
delay 100ms
/**************************************************
void delay(uchar )
{
uchar x;
uchar y;
for(x=0;x<100;x++)
/**************************************************/
void Inituart(void)
{
TMOD = 0x20; //timer1 working mode 1
TL1 = 0xfd; //f7=9600 for 16mhz Fosc,and ...
{
for(y=0;y<100;y++)
_nop_();
}
}
/**************************************************/
void delay_ms(unsigned int x)
{
unsigned int i,j;
i=0;
//管脚定义
sbit CE = P1^0;
sbit CSN= P1^1;
sbit SCK= P1^2;
sbit MOSI= P1^3;
sbit MISO= P1^4;
sbit IRQ = P1^5;
/**************************************************/
return(reg_val); // return register value
NRF24L01收发程序
/******* ******** ******** ******** ******** ******** ******** ******** ******** ******* ******** ******** ******/ uchar SPI_Read (uchar reg) { uchar reg_val; CSN = 0; // CSN low, initiali ze SPI communic ation... SPI_RW(r eg); // Select register to read from.. reg_val = SPI_RW(0 ); // ..then read register value
/*NRF24L 01 初始 化 //****** ******** ******** ******** ******** ******** ******** ******** */ void init_NRF 24L01(vo id) { inerDela y_us(100 ); CE=0; // chip enable CSN=1; // Spi disable SCK=0; // SPI_Writ e_Buf(WR ITE_REG + TX_ADDR, TX_ADDRE SS, TX_ASCK high.. uchar |= MISO; // capture current MISO bit SCK = 0; // ..then set SCK low again } return(u char); // return read uchar } /******* ******** ******** ******** ******** ******** ******** ******** ******** ******* ******** ******** ****** /*函数: uchar SPI_Read (uchar reg) /*功能: NRF24L01 的SPI 时 序
无线模块NRF24L01基于C51单片机双向通讯C语言程序(中文详解)
#include <reg52.h>#include <intrins.h>/********************************************************** *****************************//* NRF24L01 地管脚定义,以及在本程序中地应用,VCC接3.3V 电源,可以通过5V用电压转换芯片/*得到,NC 管脚可以接可以不接,暂时没用途.本程序应用于51或者52单片机,是两个模块进行通讯/*成功地简单指示,现象是:模块1地 KEY1 对应模块1地LED1 和模块2地LED3 ,模块1地 KEY2 对应模/*块1地LED2 和模块2地LED4,发过来也对应./********************************************************** *****************************/typedef unsigned char uchar;typedef unsigned char uint;/************************************NRF24L01端口定义***********************************/sbit NC =P2^0; //没用,不接也可sbit MISO =P2^5; //数字输出(从 SPI 数据输出脚)sbit MOSI =P2^4; //数字输入(从 SPI 数据输入脚)sbit SCK =P1^7; //数字输入(SPI 时钟)sbit CE =P2^1; //数字输入(RX 或 TX 模式选择)sbit CSN =P2^2; //数字输入(SPI片选信号)sbit IRQ =P2^6; //数字输入(可屏蔽中断)/************************************按键***********************************************/sbit KEY1=P3^3;//按键S1sbit KEY2=P3^2;//按键S2/************************************数码管位选******************************************/sbit led1=P1^0; //LED0sbit led2=P1^1; //LED1sbit led3 =P1^2; //LED2sbit led4 =P1^3; //LED3sbit led5 =P1^4; //LED4/*********************************************NRF24L01***********************************/#define TX_ADR_WIDTH 5 // 5 uints TX address width 发送地址宽度#define RX_ADR_WIDTH 5 // 5 uints RX address width 接收地址宽度#define TX_PLOAD_WIDTH 20 // 20 uints TX payload 有效载荷装载货物#define RX_PLOAD_WIDTH 20 // 20 uints TX payloaduint const TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //本地地址uint const RX_ADDRESS[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //接收地址/***************************************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 Delay(unsigned int s); //大延时void inerDelay_us(unsigned char n); //小延时void init_NRF24L01(void); //NRF24L01 初始化uint SPI_RW(uint dat); //根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01读出一字节uchar SPI_Read(uchar reg); //从reg寄存器读一字节void SetRX_Mode(void); //数据接收配置uint SPI_RW_Reg(uchar reg, uchar value); //写数据value到reg寄存器uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars); //从reg寄存器读出bytes个字节,通常用来读取接收通道数据或接收/发送地址uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars); //把pBuf缓存中地数据写入到nRF24L01,通常用来写入发射通道数据或接收/发送地址unsigned char nRF24L01_RxPacket(unsigned char* rx_buf);//数据读取后放入rx_buf接收缓冲区中void nRF24L01_TxPacket(unsigned char * tx_buf);//发送 tx_buf中数据/*****************************************长延时*****************************************/void Delay(unsigned int s){unsigned int i;for(i=0; i<s; i++);for(i=0; i<s; i++);}/********************************************************** ********************************/uint bdata sta; //状态标志sbit RX_DR =sta^6; //RX_DR 为 sta 地第六位sbit TX_DS =sta^5; //TX_DS 为 sta 地第五位sbit MAX_RT =sta^4; //MAX_RT 为 sta 地第四位/********************************************************** ********************************//*延时函数/********************************************************** ********************************/void inerDelay_us(unsigned char n) //延时,us 级{for(;n>0;n--)_nop_();}/********************************************************** ******************************//*NRF24L01初始化/********************************************************** *****************************/void init_NRF24L01(void){inerDelay_us(100);CE=0; // 芯片使能CSN=1; // 禁止 SPISCK=0; // SPI时钟置低SPI_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,如果需要多频道可以参考Page21SPI_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}/********************************************************** ******************************************//*函数:uint SPI_RW(uint uchar)/*功能:NRF24L01地SPI写时序-----根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01 读出一字节/********************************************************** ******************************************/uint SPI_RW(uint dat){uint i;for(i=0;i<8;i++) // 循环8次{MOSI = (dat & 0x80); // dat地最高位输出到MOSI MSB to MOSIdat = (dat << 1); // 从右向左进一位shift next bit into MSB..SCK = 1; // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据Set SCK high..dat |= MISO; //读MISO到 dat 最低位 capture current MISO bitSCK = 0; // SCK置低..then set SCK low again}return(dat); //返回读出地一字节 return read dat}/********************************************************** ******************************************/*函数:uchar SPI_Read(uchar reg)/*功能:NRF24L01地SPI时序-----------从reg寄存器读一字节/********************************************************** ******************************************/uchar SPI_Read(uchar reg){uchar reg_val;CSN = 0; //CSN置低,开始传输数据CSN low, initialize SPI communication...SPI_RW(reg); //选择寄存器 Select register to read from..reg_val = SPI_RW(0); //然后从该寄存器读数据 ..then read registervalueCSN = 1; //CSN拉高,结束数据传输CSN high, terminate SPI communicationreturn(reg_val); //返回寄存器数据 return register value}/********************************************************** ******************************************//*功能:NRF24L01读写寄存器函数/*描述:写数据value到reg寄存器/********************************************************** ******************************************/uint SPI_RW_Reg(uchar reg, uchar value){uchar status;CSN = 0; // CSN置低,开始传输数据CSN low, init SPI transactionstatus = SPI_RW(reg); // 选择寄存器,同时返回状态字select registerSPI_RW(value); // 然后写数据到该寄存器 ..and write value to it..CSN = 1; // CSN拉高,结束数据传输CSN high againreturn(status); // 返回状态寄存器 return nRF24L01 status uchar}/********************************************************** ******************************************//*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据地个数/*描述: 从reg寄存器读出bytes个字节,通常用来读取接收通道数据或接收/发送地址/********************************************************** ******************************************/uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,i;CSN = 0; //CSN置低,开始传输数据 Set CSN low, init SPI tranactionstatus = SPI_RW(reg); //选择寄存器,同时返回状态字Select register to write to and read status uchar for(i=0;i<uchars;i++)pBuf[i] = SPI_RW(0); //逐个字节从nRF24L01读出CSN = 1; //CSN拉高,结束数据传输return(status); //返回状态寄存器return nRF24L01 status uchar}/********************************************************** ***********************************************/*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据地个数/*描述:把pBuf缓存中地数据写入到nRF24L01,通常用来写入发射通道数据或接收/发送地址/********************************************************** ***********************************************/uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,i;CSN = 0; //CSN置低,开始传输数据status = SPI_RW(reg); //选择寄存器,同时返回状态字inerDelay_us(10);for(i=0; i<uchars; i++)SPI_RW(*pBuf++); //逐个字节写入nRF24L01CSN = 1; //CSN拉高,结束数据传输return(status); //返回状态寄存器}/********************************************************** ******************************************//*函数:void SetRX_Mode(void)/*功能:数据接收配置/********************************************************** ******************************************/void SetRX_Mode(void){CE=0;SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);//CRC使能,16位CRC 校验,上电,接收模式CE = 1; // 拉高CE启动接收设备inerDelay_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 bufferrevale =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);// 装载数据SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ 收发完成中断响应,16位CRC,主发送CE=1; //置高CE,激发数据发送}/************************************主函数*********************************************************** */void main(void){unsigned char tf =0;unsigned char TxBuf[20]={0}; // 要发送地数组unsigned char RxBuf[20]={0}; // 接收地数据数组init_NRF24L01() ; //模块初始化led1=1;led2=1;led3 =1;led4 =1; //led 灯关闭Delay(1000);while(1){if(KEY1 ==0 ) //按键 1 按下{TxBuf[1] = 1 ; //赋值tf = 1 ;led1=0; //本地led 灯闪烁led1=1;Delay(200);}if(KEY2 ==0 ) //按键 2 按下{TxBuf[2] =1 ; //赋值tf = 1 ;led2=0; //本地led 灯闪烁Delay(200);led2=1;Delay(200);}if (tf==1) //有键按下{nRF24L01_TxPacket(TxBuf); //发送数据 Transmit Tx buffer dataTxBuf[1] = 0x00; //清零TxBuf[2] = 0x00;tf=0;Delay(1000);}SetRX_Mode(); //设置成接受模式RxBuf[1] = 0x00; //接收地数组相应位清零RxBuf[2] = 0x00;Delay(1000);nRF24L01_RxPacket(RxBuf); //接收数据if(RxBuf[1]|RxBuf[2]){if( RxBuf[1]==1){led3=RxBuf[0];}if( RxBuf[2]==1){led4=RxBuf[4];}Delay(3000); //old is '1000'}RxBuf[1] = 0x00; //清零RxBuf[2] = 0x00;led3=1; //关灯led4=1;}}本程序存在地问题:反应不够灵敏,当在按键1和按键2之间切换地时候,对方地灯闪烁会有一定地延时,另外本程序没有消除按键地抖动.对部分函数地解释:uint SPI_RW(uint dat)最基本地函数,完成 GPIO模拟 SPI 地功能.将输出字节(MOSI)从 MSB 循环输出,同时将输入字节(MISO)从 LSB 循环移入.上升沿读入,下降沿输出. (从 SCK被初始化为低电平可以判断出)uchar SPI_Read(uchar reg); //从reg寄存器读一字节读取寄存器值地函数:基本思路就是通过 READ_REG命令(也就是 0x00+寄存器地址) ,把寄存器中地值读出来.对于函数来说也就是把 reg 寄存器地值读到reg_val 中去.uint SPI_RW_Reg(uchar reg, uchar value); //写数据value到reg寄存器寄存器访问函数:用来设置 24L01 地寄存器地值.基本思路就是通过 WRITE_REG命令(也就是 0x20+寄存器地址)把要设定地值写到相应地寄存器地址里面去,并读取返回值.对于函数来说也就是把 value值写到 reg 寄存器中.需要注意地是,访问 NRF24L01 之前首先要 enable 芯片(CSN=0;) ,访问完了以后再 disable芯片(CSN=1;).uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars); //从reg寄存器读出bytes个字节,通常用来//读取接收通道数据或接收/发送地址接收缓冲区访问函数:主要用来在接收时读取 FIFO 缓冲区中地值.基本思路就是通过READ_REG命令把数据从接收 FIFO(RD_RX_PLOAD)中读出并存到数组里面去.uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars); //把pBuf缓存中地数据写入到nRF24L01,通常//用来写入发发射缓冲区访问函数:主要用来把数组里地数放到发射 FIFO缓冲区中.基本思路就是通过WRITE_REG命令把数据存到发射 FIFO(WR_TX_PLOAD)中去.Tx 模式初始化过程1)写 Tx 节点地地址 TX_ADDR2)写 Rx 节点地地址(主要是为了使能 Auto Ack) RX_ADDR_P0 3)使能 AUTO ACK EN_AA4)使能 PIPE 0 EN_RXADDR5)配置自动重发次数 SETUP_RETR6)选择通信频率 RF_CH7)配置发射参数(低噪放大器增益.发射功率.无线速率) RF_SETUP 8 ) 选择通道0 有效数据宽度 Rx_Pw_P09)配置 24L01 地基本参数以及切换工作模式 CONFIG.Rx 模式初始化过程:初始化步骤 24L01 相关寄存器1)写 Rx 节点地地址 RX_ADDR_P02)使能 AUTO ACK EN_AA3)使能 PIPE 0 EN_RXADDR4)选择通信频率 RF_CH5) 选择通道0 有效数据宽度 Rx_Pw_P06)配置发射参数(低噪放大器增益.发射功率.无线速率) RF_SETUP 7)配置 24L01 地基本参数以及切换工作模式 CONFIG.。
基于NRF24L01的程序
/*****************************************************************************概述:电气工程及其自动化2009级毕业设计课题:无线信息采集系统的设计与实现文件:无线信息采集系统数据接收端功能:接收数据存储、处理、显示、报警等。
编译:Keil uVision4硬件:AT89C52RC日期:2013年5月作者:蒋海鹏(广西大学行健文理学院)注:代码有些杂乱,头文件封装不建议用“类”封装(有显摆嫌疑,此设计只为练习该封装模式)该形式对普通函数调用是个麻烦。
在写管理器时建议采用该模式*****************************************************************************/ #include "StdC52.h"#define DATA_SIZE 6#define SENDTIME 100#define CHANGEDISPLAY 1#define RETURNDISPLAY 0static UCHAR m_BH1750RxBuff[DATA_SIZE];static UCHAR m_DHT11RxBuff[DA TA_SIZE];static UCHAR m_RxBuff[DATA_SIZE];static void LCD_Display_Init(void){C52LCDGET()->LCD_Display_String(LINE_ONE,0,"RH:"); //湿度C52LCDGET()->LCD_Display_String(LINE_ONE,5,"%");C52LCDGET()->LCD_Display_String(LINE_ONE,7,"TEMP:"); //温度C52LCDGET()->LCD_Display_Single(LINE_ONE,0X0E,0XDF-0x30); //0xdf='°',0x43='C'C52LCDGET()->LCD_Display_Single(LINE_ONE,0X0F,0X43-0x30); //0xdf='°',0x43='C'C52LCDGET()->LCD_Display_String(LINE_TWO,0,"LIGHT:"); //光强C52LCDGET()->LCD_Display_String(LINE_TWO,0X0B,"Lx"); //光强单位}static void LCD_Display_MODE(void){UINT TempData;UINT CalData;UCHAR RH1,RH2,TP1,TP2;CalData = (m_BH1750RxBuff[0]<<8) + m_BH1750RxBuff[1]; //合成数据,即光照数据TempData = (CalData*100)/120;C52LCDGET()->LCD_Display_Single(LINE_TWO,6,TempData/10000);C52LCDGET()->LCD_Display_Single(LINE_TWO,7,TempData%10000/1000);C52LCDGET()->LCD_Display_Single(LINE_TWO,8,TempData%1000/100);C52LCDGET()->LCD_Display_Single(LINE_TWO,9,TempData%100/10);C52LCDGET()->LCD_Display_Single(LINE_TWO,0X0A,TempData%10);RH1 = m_DHT11RxBuff[0]/10;RH2 = m_DHT11RxBuff[0]%10;TP1 = m_DHT11RxBuff[2]/10;TP2 = m_DHT11RxBuff[2]%10;C52LCDGET()->LCD_Display_Single(LINE_ONE,3,RH1);C52LCDGET()->LCD_Display_Single(LINE_ONE,4,RH2);C52LCDGET()->LCD_Display_Single(LINE_ONE,0X0C,TP1);C52LCDGET()->LCD_Display_Single(LINE_ONE,0X0D,TP2);}//接收数据static void NRF_RecvSystemData(UCHAR *pUersBuf){static UCHAR l_uCount = NULL;if(C52NRFGET()->NRF_RevDate(pUersBuf)) //读取接受到的数据{switch(l_uCount){case 0X00:m_DHT11RxBuff[l_uCount] = pUersBuf[l_uCount];l_uCount++;break;case 0X01:m_DHT11RxBuff[l_uCount] = pUersBuf[l_uCount];l_uCount++;break;case 0X02:m_DHT11RxBuff[l_uCount] = pUersBuf[l_uCount];l_uCount++;break;case 0X03:m_DHT11RxBuff[l_uCount] = pUersBuf[l_uCount];l_uCount++;break;case 0X04:m_BH1750RxBuff[0] = pUersBuf[l_uCount];l_uCount++;break;case 0X05:m_BH1750RxBuff[1] = pUersBuf[l_uCount];l_uCount = NULL;break;default:l_uCount = NULL;break;}C52LCDGET()->LCD_Display_String(LINE_TWO,0X0E,"Rx"); //接受成功C52LEDGET()->TP_Waring();C52LEDGET()->RH_Waring();C52LEDGET()->LX_Waring();}else{C52LEDGET()->Close_Waring();}}//主要实现各按键功能static void Key_Mode(void){UCHAR uReKey = NULL;static UCHAR m_StroeBuff[10];static UCHAR l_uFlag = NULL;//初始光标地址为3static UCHAR uCursor = 3;static UCHAR Store;uReKey = Key_Scan();if(NULL == l_uFlag){C52NRFGET()->NRF_SetRxMode(); //设置为接受模式NRF_RecvSystemData(m_RxBuff);LCD_Display_MODE();}if(DIS_CHANGE == uReKey){l_uFlag = CHANGEDISPLAY;C52IICGET()->C52IIC_Free(TRUE); //释放总线C52LCDGET()->LCD_Display_Single(LINE_ONE,3,C52IIC_Read(0X01)/10);C52LCDGET()->LCD_Display_Single(LINE_ONE,4,C52IIC_Read(0X01)%10);C52LCDGET()->LCD_Display_Single(LINE_ONE,0X0C,C52IIC_Read(0X11)/10);C52LCDGET()->LCD_Display_Single(LINE_ONE,0X0D,C52IIC_Read(0X11)%10);C52LCDGET()->LCD_Display_Single(LINE_TWO,6,C52IIC_Read(0X21));C52LCDGET()->LCD_Display_Single(LINE_TWO,7,C52IIC_Read(0X22));C52LCDGET()->LCD_Display_Single(LINE_TWO,8,C52IIC_Read(0X23));C52LCDGET()->LCD_Display_Single(LINE_TWO,9,C52IIC_Read(0X24));C52LCDGET()->LCD_Display_Single(LINE_TWO,0X0A,C52IIC_Read(0X25));C52LEDGET()->Close_Waring();}switch(l_uFlag){case LINE_ONE:C52LCDGET()->LCD_Write_Com(0X80+uCursor);C52LCDGET()->LCD_Write_Com(0X0F);if(CURSOR_ADD == uReKey){uCursor++;if(uCursor==5){uCursor = 0X0C;}if(uCursor==0X0E){uCursor = 6;l_uFlag++;}}if(CURSOR_DEC == uReKey){if((uCursor<=4)&&(uCursor>=3)) //4位置时候回3{uCursor--;if(uCursor<3) //如果在3位置回下行末尾{uCursor = 0X0A;l_uFlag++;}}if((uCursor<=0X0D)&&(uCursor>=0X0C)){uCursor--;if(uCursor<0X0C){uCursor = 4;}}}break;case LINE_TWO:C52LCDGET()->LCD_Write_Com(0X80+0X40+uCursor);C52LCDGET()->LCD_Write_Com(0X0F);if(CURSOR_ADD == uReKey){uCursor++;if(uCursor == 0X0B){uCursor = 3;l_uFlag = CHANGEDISPLAY;}}if(CURSOR_DEC == uReKey){if(uCursor>=0X06&&uCursor<=0X0A){uCursor--;if(uCursor<0X06){uCursor = 0X0D;l_uFlag = CHANGEDISPLAY;}}}break;}if(NUM_ADD == uReKey){switch(uCursor){case 0X03:if(++m_StroeBuff[0]>=10) //测量湿度范围20%-95%{m_StroeBuff[0] = 2;}C52LCDGET()->LCD_Display_Single(LINE_ONE,3,m_StroeBuff[0]);break;case 0X04:if(m_StroeBuff[0]!=9){if(++m_StroeBuff[1]>=10){m_StroeBuff[1] = NULL;}}else{if(++m_StroeBuff[1]>=6){m_StroeBuff[1] = NULL;}}C52LCDGET()->LCD_Display_Single(LINE_ONE,4,m_StroeBuff[1]);break;case 0X0C:if(++m_StroeBuff[2]>=6) //测量温度范围0-50{m_StroeBuff[2] = NULL;}C52LCDGET()->LCD_Display_Single(LINE_ONE,0X0C,m_StroeBuff[2]);break;case 0X0D:if(++m_StroeBuff[3]>=10){m_StroeBuff[3] = NULL;}C52LCDGET()->LCD_Display_Single(LINE_ONE,0X0D,m_StroeBuff[3]);break;case 0X06: //光强测量范围1-65535lxif(++m_StroeBuff[4]>=7) //万位最大为6{m_StroeBuff[4] = NULL;}C52LCDGET()->LCD_Display_Single(LINE_TWO,0X06,m_StroeBuff[4]);break;case 0X07:if(m_StroeBuff[4] == 6){if(++m_StroeBuff[5]>=6){m_StroeBuff[5] = NULL;}}else{if(++m_StroeBuff[5]>=10){m_StroeBuff[5] = NULL;}}C52LCDGET()->LCD_Display_Single(LINE_TWO,0X07,m_StroeBuff[5]);break;case 0X08:if((m_StroeBuff[4]==6)&&(m_StroeBuff[5]==5)){if(++m_StroeBuff[6]>=6){m_StroeBuff[6] = NULL;}}else{if(++m_StroeBuff[6]>=10){m_StroeBuff[6] = NULL;}}C52LCDGET()->LCD_Display_Single(LINE_TWO,0X08,m_StroeBuff[6]);break;case 0X09:if((m_StroeBuff[4]==6)&&(m_StroeBuff[5]==5)&&(m_StroeBuff[6]==5)) {if(++m_StroeBuff[7]>=4){m_StroeBuff[7] = NULL;}}else{if(++m_StroeBuff[7]>=10){m_StroeBuff[7] = NULL;}}C52LCDGET()->LCD_Display_Single(LINE_TWO,0X09,m_StroeBuff[7]);break;case 0X0A:if((m_StroeBuff[4]==6)&&(m_StroeBuff[5]==5)\&&(m_StroeBuff[6]==5)&&(m_StroeBuff[7]==3)){if(++m_StroeBuff[8]>=6){m_StroeBuff[8] = NULL;}}else{if(++m_StroeBuff[8]>=10){m_StroeBuff[8] = NULL;}}C52LCDGET()->LCD_Display_Single(LINE_TWO,0X0A,m_StroeBuff[8]);break;}}if(NUM_DEC ==uReKey){switch(uCursor){case 0X03:if(m_StroeBuff[0]>2) //测量湿度范围20%-95%{m_StroeBuff[0]--;}C52LCDGET()->LCD_Display_Single(LINE_ONE,3,m_StroeBuff[0]);break;case 0X04:if(m_StroeBuff[1]>0){m_StroeBuff[1]--;}C52LCDGET()->LCD_Display_Single(LINE_ONE,4,m_StroeBuff[1]);break;case 0X0C:if(m_StroeBuff[2]>0) //测量温度范围0-50{m_StroeBuff[2]--;}C52LCDGET()->LCD_Display_Single(LINE_ONE,0X0C,m_StroeBuff[2]);break;case 0X0D:if(m_StroeBuff[3]>0){m_StroeBuff[3]--;}C52LCDGET()->LCD_Display_Single(LINE_ONE,0X0D,m_StroeBuff[3]);break;case 0X06: //光强测量范围1-65535lxif(m_StroeBuff[4]>0) //万位最大为6{m_StroeBuff[4]--;}C52LCDGET()->LCD_Display_Single(LINE_TWO,0X06,m_StroeBuff[4]);break;case 0X07:if(m_StroeBuff[5]>0){m_StroeBuff[5]--;}C52LCDGET()->LCD_Display_Single(LINE_TWO,0X07,m_StroeBuff[5]);break;case 0X08:if(m_StroeBuff[6]>0){m_StroeBuff[6]--;}C52LCDGET()->LCD_Display_Single(LINE_TWO,0X08,m_StroeBuff[6]);break;case 0X09:if(m_StroeBuff[7]>0){m_StroeBuff[7]--;}C52LCDGET()->LCD_Display_Single(LINE_TWO,0X09,m_StroeBuff[7]);break;case 0X0A:if(m_StroeBuff[8]>0){m_StroeBuff[8]--;}C52LCDGET()->LCD_Display_Single(LINE_TWO,0X0A,m_StroeBuff[8]);break;}}if(NUM_AFFIRM == uReKey) //确定数值存入{l_uFlag = RETURNDISPLAY;uCursor = 3; //光标清回三C52LCDGET()->LCD_Write_Com(0x0C); //不显示光标C52IICGET()->C52IIC_Free(TRUE);Store = m_StroeBuff[0]*10 + m_StroeBuff[1]; //存入数值C52IIC_Write(0X01,Store);Store = NULL;Store = m_StroeBuff[2]*10 + m_StroeBuff[3];C52IIC_Write(0X11,Store);Store = NULL;C52NRFGET()->NRF_SetRxMode(); //设置为接受模式C52IIC_Write(0X21,m_StroeBuff[4]);C52IIC_Write(0X22,m_StroeBuff[5]);C52IIC_Write(0X23,m_StroeBuff[6]);C52IIC_Write(0X24,m_StroeBuff[7]);C52IIC_Write(0X25,m_StroeBuff[8]);}}int main(void){C52NRFGET()->NRF_Init();C52LCDGET()->LCD_Init(); //液晶初始化LCD_Display_Init();C52IICGET()->C52IIC_Init(); //IIC初始化C52IICGET()->C52IIC_SetID(0XA0); //设置器件IDC52IICGET()->C52IIC_SetRate(3);C52IICGET()->C52IIC_Free(TRUE); //释放IIC总线while(TRUE){C52NRFGET()->NRF_SetRxMode(); //设置为接受模式Key_Mode();DelayMs(SENDTIME);}}#include "..\StdC52.h"#include "LCD1602.h"static LCD1602 *hLCDBus = NULL;static LCD1602 m_Instance;static void LCD_Write_Com(UCHAR Com){LCDRS = FALSE;GPIOA = Com;DelayMs(5);LCDEN = TRUE;DelayMs(5);LCDEN= FALSE;}static void LCD_Write_Data(UCHAR Date){LCDRS = TRUE;GPIOA = Date;DelayMs(5);LCDEN = TRUE;DelayMs(5);LCDEN = FALSE;}static void LCD_Display_Single(UCHAR Line, UCHAR Address,UCHAR InData) {switch(Line){case 0x01:LCD_Write_Com(0X80+Address);break;case 0x02:LCD_Write_Com(0X80+0X40+Address);break;default:break;}LCD_Write_Data(0X30+InData);}static void LCD_Display_String(UCHAR Line,UCHAR Address,UCHAR *pBuff){switch(Line){case LINE_ONE:LCD_Write_Com(0X80+Address);break;case LINE_TWO:LCD_Write_Com(0X80+0X40+Address);break;default:break;}while(*pBuff!='\0'){LCD_Write_Data(*pBuff++);}}void LCD_Init(void){C52LCDGET()->LCD_Write_Com(0x38); //设置16X2显示,5X7点阵,8位数据接口C52LCDGET()->LCD_Write_Com(0x0c); //设置开显示,不显示光标C52LCDGET()->LCD_Write_Com(0x06); //写一个字符后地址指针加1C52LCDGET()->LCD_Write_Com(0x01); //显示清零,数据指针清零}static void NEW(void){hLCDBus = &m_Instance;hLCDBus->LCD_Init = LCD_Init;hLCDBus->LCD_Write_Com = LCD_Write_Com;hLCDBus->LCD_Write_Data = LCD_Write_Data;hLCDBus->LCD_Display_Single = LCD_Display_Single;hLCDBus->LCD_Display_String = LCD_Display_String;}LCD1602 *C52LCDGET(void){NEW();return hLCDBus;}----------------------------------------------------------------------------------------------------------------------#include "..\StdC52.h"#include "Globle.h"void DelayMs(UINT TimeMs){UCHAR Time;UINT Count;for(Count = TimeMs; Count>0; Count--)for(Time = 0;Time<110;Time++);}---------------------------------------------------------------------------------------------------------------------- #include "..\StdC52.h"#include "NRF24L01.h"//状态标志static UCHAR BDA TA m_Status;sbit RX_DR = m_Status^6;sbit TX_DS = m_Status^5;sbit MAX_RT = m_Status^4;//NRF对象指针static NRF *hNRFBus = NULL;//NRF实例static NRF m_Instance;//发送地址static UCHAR code TxAddr[]={0x34,0x43,0x10,0x10,0x01};//NRF24L01初始化函数void NRF_Init(void){DelayMs(2); //让系统什么都不干CE = FALSE; //待机模式1CSN = TRUE;SCK = FALSE;IRQ = TRUE;}//SPI时序函数static UCHAR NRF_SPI(UCHAR uDate){UCHAR i;for(i=0;i<8;i++){if(uDate&0x80){MOSI = TRUE;}else{MOSI = FALSE; // byte最高位输出到MOSI}uDate<<=1; // 低一位移位到最高位SCK = TRUE;if(MISO) // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据{uDate|=0x01; // 读MISO到byte最低位}SCK = FALSE; // SCK置低}return(uDate); // 返回读出的一字节}//SPI读寄存器一字节函数static UCHAR NRF_ReadReg(UCHAR RegAddr){UCHAR BackDate;CSN = FALSE; //启动时序NRF_SPI(RegAddr); //写寄存器地址BackDate=NRF_SPI(R_REGISTER); //写入读寄存器指令CSN = TRUE;return(BackDate); //返回状态}//SPI写寄存器一字节函数static UCHAR NRF_WriteReg(UCHAR RegAddr,UCHAR uDate){UCHAR BackDate;CSN = FALSE; //启动时序BackDate = NRF_SPI(RegAddr); //写入地址NRF_SPI(uDate); //写入值CSN = TRUE;return(BackDate);}//SPI读取RXFIFO寄存器的值//寄存器地址,读取数据存放变量,读取数据长度, 用于接收static UCHAR NRF_ReadRxDate(UCHAR RegAddr,UCHAR *RxDate,UCHAR Len){UCHAR BackDate,i;CSN = FALSE; //启动时序BackDate=NRF_SPI(RegAddr); //写入要读取的寄存器地址for(i=0;i<Len;i++) //读取数据{RxDate[i] = NRF_SPI(R_REGISTER);}CSN = TRUE;return(BackDate);}//SPI写入TXFIFO寄存器的值寄存器地址,写入数据存放变量,读取数据长度,用于发送static UCHAR NRF_WriteTxDate(UCHAR RegAddr,UCHAR *TxDate,UCHAR Len){UCHAR BackDate,i;CSN = FALSE;BackDate=NRF_SPI(RegAddr); //写入要写入寄存器的地址for(i=0;i<Len;i++) //写入数据{NRF_SPI(*TxDate++);}CSN = TRUE;return(BackDate);}//NRF设置为发送模式并发送数据/*void NRF_SetTxMode(UCHAR *TxDate){CE = FALSE;NRF_WriteTxDate(W_REGISTER+TX_ADDR,TxAddr,TX_ADDR_WITDH); //写寄存器指令+接收地址使能指令+接收地址+地址宽度NRF_WriteTxDate(W_REGISTER+RX_ADDR_P0,TxAddr,TX_ADDR_WITDH); //为了应答接收设备,接收通道0地址和发送地址相同NRF_WriteTxDate(W_TX_PAYLOAD,TxDate,TX_DA TA_WITDH); //写入数据NRF_WriteReg(W_REGISTER+EN_AA,0x01); // 使能接收通道0自动应答NRF_WriteReg(W_REGISTER+EN_RXADDR,0x01); // 使能接收通道0NRF_WriteReg(W_REGISTER+SETUP_RETR,0x0a); // 自动重发延时等待250us+86us,自动重发10次NRF_WriteReg(W_REGISTER+RF_CH,0x40); // 选择射频通道0x40NRF_WriteReg(W_REGISTER+RF_SETUP,0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益NRF_WriteReg(W_REGISTER+CONFIG,0x0e); // CRC 使能,16位CRC校验,上电CE = TRUE;DelayMs(5); //保持10us秒以上} *///NRF设置为接收模式void NRF_SetRxMode(void){CE = FALSE;NRF_WriteTxDate(W_REGISTER+RX_ADDR_P0,TxAddr,TX_ADDR_WITDH); // 接收设备接收通道0使用和发送设备相同的发送地址NRF_WriteReg(W_REGISTER+EN_AA,0x01); // 使能接收通道0自动应答NRF_WriteReg(W_REGISTER+EN_RXADDR,0x01); // 使能接收通道0NRF_WriteReg(W_REGISTER+RF_CH,0x40); // 选择射频通道0x40NRF_WriteReg(W_REGISTER+RX_PW_P0,TX_DATA_WITDH); // 接收通道0选择和发送通道相同有效数据宽度NRF_WriteReg(W_REGISTER+RF_SETUP,0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益*/NRF_WriteReg(W_REGISTER+CONFIG,0x0f); // CRC 使能,16位CRC校验,上电,接收模式CE = TRUE;DelayMs(5); //保持10us 秒以上//检测应答信号/*BOOL NRF_CheckACK(void){ //用于发射m_Status = NRF_ReadReg(R_REGISTER+STATUS); // 返回状态寄存器if(TX_DS||MAX_RT) //发送完毕中断{NRF_WriteReg(W_REGISTER+STA TUS,NOP); // 清除TX_DS或MAX_RT中断标志CSN = FALSE;NRF_SPI(FLUSH_TX); //用于清空FIFO !!关键!!不然会出现意想不到的后果!!!大家记住!!CSN = TRUE;return(FALSE);}elsereturn(TRUE);} *///判断是否接收收到数据,接到就从RX取出用于接收模式UCHAR NRF_RevDate(UCHAR *RevDate){BOOL l_bRevFlags = NULL;m_Status = NRF_ReadReg(R_REGISTER+STATUS); //发送数据后读取状态寄存器if(RX_DR) // 判断是否接收到数据{CE = FALSE; //SPI使能NRF_ReadRxDate(R_RX_PAYLOAD,RevDate,RX_DA TA_WITDH); // 从RXFIFO读取数据l_bRevFlags = TRUE; //读取数据完成标志}else{l_bRevFlags = FALSE;}NRF_WriteReg(W_REGISTER+STA TUS,NOP); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标return(l_bRevFlags);}//创建static void New(void){hNRFBus = &m_Instance;hNRFBus->NRF_Init = NRF_Init;// hNRFBus->NRF_SetTxMode = NRF_SetTxMode;hNRFBus->NRF_SetRxMode = NRF_SetRxMode;hNRFBus->NRF_RevDate = NRF_RevDate;}//获取NRF实例句柄NRF *C52NRFGET(void){New();return hNRFBus;}---------------------------------------------------------------------------------------------------------------------- #include "..\StdC52.h"#include "C52IIC.h"#define ReWrTime 10//IIC对象指针static IIC *hIICBus = NULL;//IIC实例static IIC m_Instance;//IIC速率static UINT m_Baudrate = 3;//器件地址static UCHAR m_DeviceID = 0X00;//IIC总线延时static void IICBusDelay(UINT uTime){while(uTime--);}//模拟IIC总线的起始位static void IICBusStart(void){SDA = TRUE; //SDA = 1SCL = TRUE; //SCK = 1IICBusDelay(20);SDA = FALSE; //SDA = 0IICBusDelay(20);}//模拟IIC总线的停止位static void IICBusStop(){SDA = FALSE; //SDA = 0SCL = FALSE; //SCK = 0IICBusDelay(20);SCL = TRUE; //SCK = 1IICBusDelay(20);SDA = TRUE; //SDA = 1IICBusDelay(20);}//读IIC_SDA引脚电平static BOOL SDARead(void){UCHAR i;SCL = TRUE;IICBusDelay(20);while((TRUE == SDA)&&(i<0XFF))i++;if(SDA){return TRUE;}return FALSE;}//模拟IIC总线写一个字节数据(返回ACK)static BOOL IICBusWriteByte(UCHAR WRData){UCHAR i,ACK;for(i=0;i<8;i++){SCL = FALSE; //SCK = 0if( WRData&0x80 ){SDA = TRUE;}else{SDA = FALSE;}IICBusDelay(m_Baudrate);SCL = TRUE; // SCK = 1IICBusDelay(m_Baudrate);WRData = WRData<<1;}SCL = FALSE; //SCK = 0IICBusDelay(m_Baudrate);SCL = TRUE; //SCK = 1ACK = SDARead(); //读取SDA口高无响应,低响应IICBusDelay(m_Baudrate);SCL = FALSE; //SCK = 0SDA = TRUE; //SDA = 1IICBusDelay(m_Baudrate);return ACK;}//模拟IIC总线读一个字节数据static UCHAR IICBusReadByte(BOOL bIsACK){UCHAR i,RDData = NULL;for(i=0;i<8;i++){RDData = RDData<<1;SCL = FALSE; //SCK = 0IICBusDelay(m_Baudrate);SCL = TRUE; //SCK = 1if( SDARead() == TRUE ){RDData = RDData|0x01;}IICBusDelay(m_Baudrate);}if(bIsACK){SCL = FALSE; //SCK = 0SDA = FALSE; //SDA = 0IICBusDelay(m_Baudrate);SCL = TRUE; //SCK = 1IICBusDelay(m_Baudrate);SCL = FALSE; //SCK = 0 }else{SCL = FALSE; //SCK = 0SDA = TRUE; //SDA = 1IICBusDelay(m_Baudrate);SCL = TRUE; //SCK = 1IICBusDelay(m_Baudrate);SCL = FALSE; //SCK = 0 }return RDData;}//设置IIC速度void C52IIC_SetRate(UINT Rate){m_Baudrate = Rate;}//设置IIC器件地址void C52IIC_SetID(UCHAR ID){m_DeviceID = ID;}//写IIC数据BOOL C52IIC_Write(UCHAR Adress,UCHAR DATA) {UCHAR Vale = TRUE;UINT16 i = 0;IICBusStart();if(IICBusWriteByte(m_DeviceID)){Vale = FALSE;goto Exit;}if(IICBusWriteByte(Adress)){Vale = FALSE;goto Exit;}if(IICBusWriteByte(DATA)){Vale = FALSE;goto Exit;}Exit:IICBusStop();//根据不同芯片特性,设置读取速率DelayMs(ReWrTime);return Vale;}//读IIC数据UCHAR C52IIC_Read(UCHAR Adress) {UCHAR InData;IICBusStart();if(IICBusWriteByte(m_DeviceID)){goto Exit;}if(IICBusWriteByte(Adress)){goto Exit;}IICBusStart();if(IICBusWriteByte(m_DeviceID+1)){goto Exit;}InData = IICBusReadByte(FALSE); Exit:IICBusStop();//根据不同芯片特性,设置读取速率DelayMs(ReWrTime);return InData;}//初始化IICvoid C52IIC_Init(void){SDA = TRUE;IICBusDelay(20);SCL = TRUE;IICBusDelay(20);}//释放\占用IIC总线void C52IIC_Free(BOOL bIsFree){if(bIsFree){SCL = TRUE;SDA = TRUE;}else{SCL = FALSE;SDA = FALSE;}}//创建IICstatic void new(void){hIICBus = &m_Instance;hIICBus->C52IIC_SetRate = C52IIC_SetRate;hIICBus->C52IIC_SetID = C52IIC_SetID;hIICBus->C52IIC_Init = C52IIC_Init;hIICBus->C52IIC_Free = C52IIC_Free;}//获取IIC实例句柄IIC *C52IICGET(void){new();return hIICBus;}---------------------------------------------------------------------------------------------------------------------- #include "..\StdC52.h"#include "C52KEY.h"//读取IO口static UCHAR Read_GPIO(void){UCHAR uByte = NULL;uByte |= GPIO_KEY1;uByte = uByte << 1;uByte |= GPIO_KEY2;uByte = uByte << 1;uByte |= GPIO_KEY3;uByte = uByte << 1;uByte |= GPIO_KEY4;uByte = uByte << 1;uByte |= GPIO_KEY5;uByte = uByte << 1;uByte |= GPIO_KEY6;uByte = uByte << 2;return uByte;}static BOOL Key_Press(void){UCHAR uTemp;uTemp = Read_GPIO();uTemp &= 0XFC;if(uTemp!=0XFC)DelayMs(10);if(uTemp!=0XFC){return TRUE;}else{return FALSE;}}UCHAR Key_Scan(void){UCHAR KeyCode;DelayMs(10);if(Key_Press()){KeyCode = Read_GPIO();switch(KeyCode){case 0XF8:KeyCode = 0X01;break;case 0XF4:KeyCode = 0X02;break;case 0XEC:KeyCode = 0X03;break;case 0XDC:KeyCode = 0X04;break;case 0XBC:KeyCode = 0X05;break;case 0X7C:KeyCode = 0X06;break;default:KeyCode = NULL;break;}while(Key_Press());}else{KeyCode = NULL;}return KeyCode;}---------------------------------------------------------------------------------------------------------------------- #include "..\StdC52.h"#include "C52W ARING.h"static LED *hLEDBus = NULL;static LED m_Instance;static void TP_Waring(void){LED_TP = FALSE;}static void TP_Close(void){LED_TP = TRUE;}static void RH_Waring(void){LED_RH = FALSE;}static void RH_Close(void){LED_RH = TRUE;}static void LX_Waring(void){LED_LX = FALSE;}static void LX_Close(void){LED_LX = TRUE;}static void Close_Waring(void){LED_TP = TRUE;LED_RH = TRUE;LED_LX = TRUE;}static void New(void){hLEDBus = &m_Instance;hLEDBus->TP_Waring = TP_Waring;hLEDBus->RH_Waring = RH_Waring;hLEDBus->LX_Waring = LX_Waring;hLEDBus->TP_Close = TP_Close;hLEDBus->TP_Close = RH_Close;hLEDBus->TP_Close = LX_Close;hLEDBus->Close_Waring = Close_Waring;LED *C52LEDGET(void) {New();return hLEDBus;}。
NRF24L01无线串口开发板程序详解
1.源程序开发环境建立1.1程序编译软件编译软件用keil C51,打开安装文件,一路点击下一步即可完成。
1.2程序下载软件使用STC ISP下载软件。
2.源程序文件整体结构工程中,只有一个main.c文件,所有程序都写在这个文件里面。
Reg51.h是包含的头文件。
是不是非常简单!3.源程序执行流程无线数据处理程序:串口数据处理程序:4.串口配置函数void serial_open(void){SCON = 0X50;AUXR |= 0X04;TL2 = 0Xc0; // 9600TH2 = 0Xfd;AUXR|=0X10;}此串口配置函数,利用单片机内部的定时器2作为波特率发生器。
共用到4个寄存器:SCON AUXR TL2 TH2SM0和SM1的位决定串口工作的4种方式:程序中,SCON=0X50,即SM0=0 SM1=1,即串口工作在“方式1”;REN=1,允许串口接收数据。
TL2和TH2是定时器2的高位和低位寄存器。
程序中,首先AUXR|=0X40,最后AUXR|=0X10。
即首先把T2x12置1,然后把T2R置1。
即首先把定时器2设置为1T模式,然后把定时器打开。
5.串口发送数据函数void senddata(uchar data_buf){SBUF = data_buf;while(!TI);TI = 0;}用到了寄存器SBUF和寄存器SCON中的TI位。
SBUF寄存器是串口收发数据缓存寄存器,放到这个寄存器中的数据,会通过串口发送出去,接收到的串口数据,也会放到这个寄存器中。
也就是串口接收和发送都是使用这个寄存器。
程序中,SBUF=data_buf,就是把data_buf给了SBUF,单片机自动把SBUF里面的数据发送到串口。
TI是串口发送数据完成标志位,当串口发送完一个数据,此位置1,置位后,需要通过软件清0。
所以通过while(!TI),来检测TI位,达到检测串口是否发送完数据的目的。
Linux下驱动2.4G无线模块(NRF24L01)
/jammy_lee/Linux下驱动2.4G无线模块(NRF24L01)linux驱动2010-02-06 11:29:45 阅读613 评论6 字号:大中小订阅NRF24L01使用的SPI协议通信,这里并没有用到s3c2440自带的SPI功能,而是直接用IO口模拟SPI。
而根据Datasheet所示,NRF24L01的SPI接速率为0~8Mbps,因此需要在读写时序上加上适当的延时。
驱动程序:/************************************************************///文件名:nrf24l01.c//功能:linux下的nrf24l01驱动程序//使用说明: (1)// (2)// (3)// (4)//作者:jammy-lee//日期:2010-01-11/************************************************************/#include <linux/config.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/miscdevice.h>#include <linux/devfs_fs_kernel.h>#include <asm/uaccess.h>#include <asm/hardware.h>#include <asm/arch/regs-gpio.h>typedef unsigned int uint16 ;typedef unsigned char uint8 ;/*//和引脚相关的宏定义#define CE S3C2410_GPF3#define CE_OUTP S3C2410_GPF3_OUTP #define SCK S3C2410_GPF4#define SCK_OUTP S3C2410_GPF4_OUTP#define MISO S3C2410_GPG3#define MISO_INP S3C2410_GPG3_INP#define IRQ S3C2410_GPG0#define IRQ_OUTP S3C2410_GPG0_OUTP #define MOSI S3C2410_GPG5#define MOSI_OUTP S3C2410_GPG5_OUTP #define CSN S3C2410_GPG6#define CSN_OUTP S3C2410_GPG6_OUTP *///和引脚相关的宏定义#define CSN S3C2410_GPF3#define CSN_OUTP S3C2410_GPF3_OUTP #define MOSI S3C2410_GPF4#define MOSI_OUTP S3C2410_GPF4_OUTP #define IRQ S3C2410_GPG3#define IRQ_INP S3C2410_GPG3_INP#define MISO S3C2410_GPG0#define MISO_INP S3C2410_GPG0_INP#define SCK S3C2410_GPG5#define SCK_OUTP S3C2410_GPG5_OUTP#define CE S3C2410_GPG6#define CE_OUTP S3C2410_GPG6_OUTP#define DEVICE_NAME "NRF24L01" //设备名称,在可以/proc/devices 查看#define NRF24L01_MAJOR 241 //主设备号#define TxBufSize 32uint8 TxBuf[TxBufSize]={0x01,0x02,0x03,0x4,0x05,0x06,0x07,0x08,0x09,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x30,0x31,0x32,};//NRF24L01端口定义#define CE_OUT s3c2410_gpio_cfgpin(CE, CE_OUTP) //数据线设置为输出#define CE_UP s3c2410_gpio_pullup(CE, 1) //打开上拉电阻#define CE_L s3c2410_gpio_setpin(CE, 0) //拉低数据线电平#define CE_H s3c2410_gpio_setpin(CE, 1) //拉高数据线电平#define SCK_OUT s3c2410_gpio_cfgpin(SCK, SCK_OUTP) //数据线设置为输出#define SCK_UP s3c2410_gpio_pullup(SCK, 1) //打开上拉电阻#define SCK_L s3c2410_gpio_setpin(SCK, 0) //拉低数据线电平#define SCK_H s3c2410_gpio_setpin(SCK, 1) //拉高数据线电平#define MISO_IN s3c2410_gpio_cfgpin(MISO, MISO_INP) //数据线设置为输出#define MISO_UP s3c2410_gpio_pullup(MISO, 1) //打开上拉电阻#define MISO_STU s3c2410_gpio_getpin(MISO) //数据状态#define IRQ_IN s3c2410_gpio_cfgpin(IRQ, IRQ_INP) //数据线设置为输出#define IRQ_UP s3c2410_gpio_pullup(IRQ, 1) //打开上拉电阻#define IRQ_L s3c2410_gpio_setpin(IRQ, 0) //拉低数据线电平#define IRQ_H s3c2410_gpio_setpin(IRQ, 1) //拉高数据线电平#define MOSI_OUT s3c2410_gpio_cfgpin(MOSI, MOSI_OUTP) //数据线设置为输出#define MOSI_UP s3c2410_gpio_pullup(MOSI, 1) //打开上拉电阻#define MOSI_L s3c2410_gpio_setpin(MOSI, 0) //拉低数据线电平#define MOSI_H s3c2410_gpio_setpin(MOSI, 1) //拉高数据线电平#define CSN_OUT s3c2410_gpio_cfgpin(CSN, CSN_OUTP) //数据线设置为输出#define CSN_UP s3c2410_gpio_pullup(CSN, 1) //打开上拉电阻#define CSN_L s3c2410_gpio_setpin(CSN, 0) //拉低数据线电平#define CSN_H s3c2410_gpio_setpin(CSN, 1) //拉高数据线电平//NRF24L01#define TX_ADR_WIDTH 5 // 5 uint8s TX address width#define RX_ADR_WIDTH 5 // 5 uint8s RX address width#define TX_PLOAD_WIDTH 32 // 20 uint8s TX payload#define RX_PLOAD_WIDTH 32 // 20 uint8s TX payloaduint8 const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址uint8 const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址//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栈入栈出状态寄存器设置uint8 init_NRF24L01(void);uint8 SPI_RW(uint8 tmp);uint8 SPI_Read(uint8 reg);void SetRX_Mode(void);uint8 SPI_RW_Reg(uint8 reg, uint8 value);uint8 SPI_Read_Buf(uint8 reg, uint8 *pBuf, uint8 uchars); uint8 SPI_Write_Buf(uint8 reg, uint8 *pBuf, uint8 uchars); unsigned char nRF24L01_RxPacket(unsigned char* rx_buf); void nRF24L01_TxPacket(unsigned char * tx_buf);//全局变量uint8 opencount = 0;//uint8 sta; //状态标志#define RX_DR 6#define TX_DS 5#define MAX_RT 4//NRF24L01初始化uint8 init_NRF24L01(void){/*CE_UP;SCK_UP;MISO_UP;IRQ_UP;MOSI_UP;CSN_UP;*/MISO_UP;CE_OUT;CSN_OUT;SCK_OUT;MOSI_OUT;MISO_IN;IRQ_IN;udelay(500);CE_L; // chip enablendelay(60);CSN_H; // Spi disablendelay(60);SCK_L; // Spi clock line init highndelay(60);SPI_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,如果需要多频道可以参考Page21SPI_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,发射功率为最大值0dBSPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收发完成中断响应,16位CRC ,主接收mdelay(1000);nRF24L01_TxPacket(TxBuf);SPI_RW_Reg(WRITE_REG+STATUS,0XFF);printk("test 1 \n");mdelay(1000);/*nRF24L01_TxPacket(TxBuf);SPI_RW_Reg(WRITE_REG+STATUS,0XFF);printk("test 2 \n");mdelay(1000);nRF24L01_TxPacket(TxBuf);SPI_RW_Reg(WRITE_REG+STATUS,0XFF);printk("test 3 \n");mdelay(1000);nRF24L01_TxPacket(TxBuf);SPI_RW_Reg(WRITE_REG+STATUS,0XFF);printk("test 4 \n");mdelay(1000);*/return (1);}//函数:uint8 SPI_RW(uint8 tmp)//功能:NRF24L01的SPI写时序tmpuint8 SPI_RW(uint8 tmp){uint8 bit_ctr;for(bit_ctr=0 ;bit_ctr<8 ;bit_ctr++) // output 8-bit {if(tmp & 0x80) // output 'tmp', MSB to MOSIMOSI_H;elseMOSI_L;tmp <<= 1; // shift next bit into MSB..SCK_H; // Set SCK high..ndelay(60);tmp |= MISO_STU; // capture current MISO bitSCK_L; // ..then set SCK low againndelay(60);}return(tmp); // return read tmp}//函数:uint8 SPI_Read(uint8 reg)//功能:NRF24L01的SPI时序uint8 SPI_Read(uint8 reg){uint8 reg_val;CSN_L; // CSN low, initialize SPI communication...ndelay(60);SPI_RW(reg); // Select register to read from..reg_val = SPI_RW(0); // ..then read registervalueCSN_H; // CSN high, terminate SPI communication ndelay(60);return(reg_val); // return register value}//功能:NRF24L01读写寄存器函数uint8 SPI_RW_Reg(uint8 reg, uint8 value){uint8 status;CSN_L; // CSN low, init SPI transactionndelay(60);status = SPI_RW(reg); // select registerSPI_RW(value); // ..and write value to it..CSN_H; // CSN high againndelay(60);return(status); // return nRF24L01 status uint8}//函数:uint8 SPI_Read_Buf(uint8 reg, uint8 *pBuf, uint8 uchars)//功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数uint8 SPI_Read_Buf(uint8 reg, uint8 *pBuf, uint8 uchars){uint8 status,uint8_ctr;CSN_L; // Set CSN low, init SPI tranactionndelay(60);status = SPI_RW(reg); // Select register to write to and read status uint8for(uint8_ctr=0;uint8_ctr<uchars;uint8_ctr++){pBuf[uint8_ctr] = SPI_RW(0); //ndelay(20);}CSN_H;ndelay(60);return(status); // return nRF24L01 status uint8}//函数:uint8 SPI_Write_Buf(uint8 reg, uint8 *pBuf, uint8 uchars)//功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数uint8 SPI_Write_Buf(uint8 reg, uint8 *pBuf, uint8 uchars){uint8 status,uint8_ctr;CSN_L; //SPI使能ndelay(60);status = SPI_RW(reg);for(uint8_ctr=0; uint8_ctr<uchars; uint8_ctr++) //{SPI_RW(*pBuf++);ndelay(20);}CSN_H; //关闭SPIndelay(60);return(status); //}//函数:void SetRX_Mode(void)//功能:数据接收配置void SetRX_Mode(void){CE_L;ndelay(60);// SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收发完成中断响应,16位CRC ,主接收//udelay(1);CE_H;udelay(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(STA TUS); // 读取状态寄存其来判断数据接收状况if(sta & (1<<RX_DR)) // 判断是否接收到数据{CE_L; //SPI使能udelay(50);SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO bufferrevale =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_L; //StandBy I模式ndelay(60);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_H; //置高CE,激发数据发送udelay(10);}//文件的写函数static ssize_t nrf24l01_write(struct file *filp, const char *buffer,size_t count, loff_t *ppos){if( copy_from_user( &TxBuf, buffer, count ) ); //从内核空间复制到用户空间{printk("Can't Send Data !");return -EFAULT;}nRF24L01_TxPacket(TxBuf);SPI_RW_Reg(WRITE_REG+STATUS,0XFF);printk("OK! \n");return(10);//的读函数static ssize_t nrf24l01_read(struct file *filp, char *buffer, size_t count, loff_t *ppos){nRF24L01_TxPacket(TxBuf);SPI_RW_Reg(WRITE_REG+STATUS,0XFF);printk("read \n");return (10);}static int nrf24l01_open(struct inode *node, struct file *file) {uint8 flag = 0;if(opencount == 1)return -EBUSY;flag = init_NRF24L01();mdelay(100);if(flag == 0){printk("uable to open device!\n");return -1;}else{opencount++;printk("device opened !\n");return 0;}static int nrf24l01_release(struct inode *node, struct file *file){opencount--;printk(DEVICE_NAME " released !\n");return 0;}static struct file_operations nrf24l01_fops = {.owner = THIS_MODULE,.open = nrf24l01_open,.write = nrf24l01_write,.read = nrf24l01_read,.release = nrf24l01_release,};static int __init nrf24l01_init(void){int ret;printk("Initial driver for NRF24L01......................\n");ret = register_chrdev(NRF24L01_MAJOR, DEVICE_NAME, &nrf24l01_fops);mdelay(10);if (ret < 0){printk(DEVICE_NAME " can't register major number\n");return ret;}else{printk(DEVICE_NAME " register success\n");return 0;}}static void __exit nrf24l01_exit(void){unregister_chrdev(NRF24L01_MAJOR, DEVICE_NAME);printk("NRF24L01 unregister success \n");}module_init(nrf24l01_init);module_exit(nrf24l01_exit);MODULE_AUTHOR("jammy_lee@");MODULE_DESCRIPTION("nrf24l01 driver for TQ2440"); MODULE_LICENSE("GPL");测试程序:/************************************************************///文件名:test_ds18b20.c//功能:测试linux下的ds18b20程序//使用说明: (1)// (2)// (3)// (4)//作者:jammy-lee//日期:2010-01-18/************************************************************/#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/select.h>#include <sys/time.h>#include <errno.h>unsigned char TxBuf[32] = {0x00};int main(void){int fd = -1;int count = 1;//fd = open("/dev/nrf24l01", 0);fd = open("/dev/nrf24l01", O_RDWR); //打开nrf24l01为可读写文件if(fd < 0){perror("Can't open /dev/nrf24l01 \n");exit(1);}printf("open /dev/nrf24l01 success \n");while(count <= 5){write(fd, &TxBuf , sizeof(TxBuf));printf("Sending %d time \n", count);usleep(100*1000);count++;}close(fd);}。
NRF24L01的发送与接收程序
#include <reg52.h>#include <intrins.h>typedef unsigned char uchar;typedef unsigned char uint;//****************************************NRF24L01端口定义sbit MISO =P1^5;sbit MOSI =P1^1;sbit SCK =P1^6;sbit CE =P1^7;sbit CSN =P1^2;sbit IRQ =P1^0;//************************************按键sbit KEY1=P3^4;//************************************蜂明器sbit LED=P3^5;//**************#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 payloaduint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址//***************************************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 Delay(unsigned int s);void inerDelay_us(unsigned char n);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);//*****************************************长延时void Delay(unsigned int s){unsigned int i;for(i=0; i<s; i++);for(i=0; i<s; i++);}//*****************************************************************************uint bdata sta; //状态标志sbit RX_DR =sta^6;sbit TX_DS =sta^5;sbit MAX_RT =sta^4;/******************************************************************************/*延时函数void inerDelay_us(unsigned char n){for(;n>0;n--)_nop_();}//*****************************************************************************/*NRF24L01初始化//*****************************************************************************/void init_NRF24L01(void){inerDelay_us(100);CE=0; // chip enableCSN=1; // Spi disableSCK=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,如果需要多频道可以参考Page21SPI_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,发射功率为最大值0dBSPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收发完成中断响应,16位CRC ,主接收}/******************************************************************************/*函数:uint SPI_RW(uint uchar)/*功能:NRF24L01的SPI写时序/******************************************************************************uint SPI_RW(uint uchar){uint bit_ctr;for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit{MOSI = (uchar & 0x80); // output 'uchar', MSB to MOSIuchar = (uchar << 1); // shift next bit into MSB..SCK = 1; // Set SCK high..uchar |= MISO; // capture current MISO bitSCK = 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_ctr<uchars;uchar_ctr++)pBuf[uchar_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_ctr<uchars; uchar_ctr++) //SPI_RW(*pBuf++);CSN = 1; //关闭SPIreturn(status); //}/*****************************************************************************//*函数:void SetRX_Mode(void)/*功能:数据接收配置/*****************************************************************************/void SetRX_Mode(void){CE=0;// SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收发完成中断响应,16位CRC ,主接收CE = 1;inerDelay_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 bufferrevale =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); // 装载数据SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送CE=1; //置高CE,激发数据发送inerDelay_us(10);}//************************************串口初始化void StartUART( void ){ //波特率4800SCON = 0x50;TMOD = 0x20;TH1 = 0xFA;TL1 = 0xFA;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,temp;uchar RxBuf[32];init_NRF24L01() ;StartUART();Delay(6000);while(1){SetRX_Mode();if(nRF24L01_RxPacket(RxBuf)){LED=0;temp++;for(i=0;i<32;i++){R_S_Byte(RxBuf[i]);Delay(600);}}LED=1;Delay(600);}}#include <reg52.h>#include <intrins.h>typedef unsigned char uchar;typedef unsigned char uint;//****************************************NRF24L01端口定义sbit MISO =P1^5;sbit MOSI =P1^1;sbit SCK =P1^6;sbit CE =P1^7;sbit CSN =P1^2;sbit IRQ =P1^0;//************************************按键sbit KEY1=P3^4;//************************************蜂明器sbit LED=P3^5;//***********************************发送缓冲区uchar TxBuf[32]={0x01,0x02,0x03,0x4,0x05,0x06,0x07,0x08,0x09,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x30,0x31,0x32,}; ////*********************************************NRF24L01*********************** #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 payloaduint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址//***************************************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 Delay(unsigned int s);void inerDelay_us(unsigned char n);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);//*****************************************长延时void Delay(unsigned int s){unsigned int i;for(i=0; i<s; i++);for(i=0; i<s; i++);}//*****************************************************************************uint bdata sta; //状态标志sbit RX_DR =sta^6;sbit TX_DS =sta^5;sbit MAX_RT =sta^4;/******************************************************************************/*延时函数/*****************************************************************************/void inerDelay_us(unsigned char n){for(;n>0;n--)_nop_();}//*****************************************************************************/*NRF24L01初始化//****************/void init_NRF24L01(void){inerDelay_us(100);CE=0; // chip enableCSN=1; // Spi disableSCK=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,如果需要多频道可以参考Page21SPI_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,发射功率为最大值0dBSPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送}/**************/*函数:uint SPI_RW(uint uchar)/*功能:NRF24L01的SPI写时序/******************/uint SPI_RW(uint uchar){uint bit_ctr;for(bit_ctr=0;bit_ctr<8;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 bitSCK = 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_ctr<uchars;uchar_ctr++)pBuf[uchar_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_ctr<uchars; uchar_ctr++) //SPI_RW(*pBuf++);CSN = 1; //关闭SPIreturn(status); //}/********************//*函数:void SetRX_Mode(void)/*功能:数据接收配置/**********************/void SetRX_Mode(void){CE=0;SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收发完成中断响应,16位CRC ,主接收inerDelay_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 bufferrevale =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); // 装载数据// SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送CE=1; //置高CE,激发数据发送inerDelay_us(10);}//************************************主函数void main(void){uchar temp =0;init_NRF24L01() ;nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer dataDelay(6000);P0=0xBF;{nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer data LED=0;Delay(10000); //可变SPI_RW_Reg(WRITE_REG+STATUS,0XFF);LED=1;Delay(8000);}}。
NRF24L01的发送与接收程序
#include <> #include <>typedef unsigned char uchar;typedef unsigned char uint;SCK = 1;uchar |= MISO; then set SCK low again}return(uchar); .SPI_RW(reg);reg_val = SPI_RW(0); then read registervalueCSN = 1; and write value to it..CSN = 1;SCK = 1;uchar |= MISO; then set SCK low again}return(uchar); .SPI_RW(reg);reg_val = SPI_RW(0); then read registervalueCSN = 1; and write value to it..CSN = 1; // CSN high again/* 函数: 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 tranaction return(status); }// return nRF24L01 status ucharstatus = SPI_RW(reg); // Select register to write to and read status ucharfor(uchar_ctr=0;uchar_ctr<uchars;uchar_ctr++)pBuf[uchar_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_ctr<uchars; uchar_ctr++) //SPI_RW(*pBuf++);CSN = 1; // 关闭SPIreturn(status); ///********************//* 函数:void SetRX_Mode(void)/* 功能:数据接收配置/**********************/void SetRX_Mode(void){CE=0;SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); 接收CE = 1;inerDelay_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 frombuffer// IRQ 收发完成中断响应, 16 位 CRC,主 FIFOSPI_RW_Reg(WRITE_REG+STATUS,sta); // 接收到数据后RX_DR,TX_DS,MAX_P都置高为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); // 装载数据// SPI_RW_Reg(WRITE_REG + CONFIG, OxOe); // IRQ 收发完成中断响应,16 位CRC 主发送CE=1; //置高CE激发数据发送inerDelay_us(1O);}//************************************ void main(void){uchar temp =O;init_NRF24LO1() ;nRF24LO1_TxPacket(TxBuf);Delay(6OOO);PO=OxBF;主函数// Transmit Tx buffer datawhile(1)nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer dataLED=0;Delay(10000); // 可变SPI_RW_Reg(WRITE_REG+STATUS,0XFF);LED=1;Delay(8000);}。
NRF24L01接收程序
/*************************************************头文件:NRF24L01.h**文件名: NRF24L01.c**创建人: 动车组**日期: 2012-8-21•**功能描述:用NRF24L01发送一定字节数的数据或者接收数据**占用资源:四位控制SPI总线的IO线和1位NRF24L01模式控制引脚** 占用一个中段***********************************************/#include"nrf24l01.h"uchar code TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址uchar code RX_ADDRESS_0[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01};//为了应答接收设备,接收通道0地址和发送地址相同//uchar code RX_ADDRESS_1[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01};//接收通道1地址//通道1-5最有最低字节不一样//uchar code RX_ADDRESS_2[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01};//接收通道2地址//且写地址的时候是低字节先写//uchar code RX_ADDRESS_3[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01};//接收通道3地址//uchar code RX_ADDRESS_4[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01};//接收通道4地址//uchar code RX_ADDRESS_5[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01};//接收通道5地址bit RX_OK = 0; //接收数据完成标志,在中断中置位bit TX_OK = 1; //数据发送完毕标志,在中断置位由于第一次要可以发送所以初值为1bit MAX_RT_OK=0; //发送次数超过设置的次数的标志在中断置位uchar bdata sta = 0x00; //状态标志sbit RX_DR =sta^6;sbit TX_DS =sta^5;sbit MAX_RT =sta^4;/************************************以下是SPI的读写函数*********************************************//****************************************************************************** **********************/*函数:uchar SPI_RW(uchar date)/*功能:SPI一个字节写时序/****************************************************************************** **********************/uchar SPI_RW(uchar byte){SCK = 0;for(i=0; i<8; i++) // 循环8次{MOSI = (byte & 0x80); // byte最高位输出到MOSIbyte <<= 1; // 低一位移位到最高位SCK = 1; // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据byte |= MISO; // 读MISO到byte最低位SCK = 0; // SCK置低}return(byte); // 返回读出的一字节}/****************************************************************************** **********************/*函数:uchar SPI_Read(uchar reg)/*功能:SPI 从reg中读出一个字节时序/****************************************************************************** **********************/uchar SPI_Read(uchar reg){uchar reg_val;CSN = 0; // CSN置低,开始传输数据SPI_RW(reg); // 选择寄存器reg_val = SPI_RW(0); // 然后从该寄存器读数据CSN = 1; // CSN拉高,结束数据传输return(reg_val); // 返回寄存器数据}/****************************************************************************** **********************//*功能:SPI 在reg中写入数据value函数/****************************************************************************** **********************/void SPI_RW_Reg(uchar reg, uchar value){CSN = 0; // CSN置低,开始传输数据SPI_RW(reg); // 选择寄存器,同时返回状态字SPI_RW(value); // 然后写数据到该寄存器CSN = 1; // CSN拉高,结束数据传输}/****************************************************************************** **********************//*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于SPI连读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出/****************************************************************************** **********************/void SPI_Read_Buf(uchar reg, uchar * pBuf, uchar bytes){uchar i;CSN = 0; // CSN置低,开始传输数据SPI_RW(reg); // 选择寄存器,同时返回状态字for(i=0; i<bytes; i++)pBuf[i] = SPI_RW(0); // 逐个字节从nRF24L01读出CSN = 1; // CSN拉高,结束数据传输}/****************************************************************************** ***************************/*函数:uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于SPI连写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数/****************************************************************************** ***************************/void SPI_Write_Buf(uchar reg, uchar * pBuf, uchar bytes){uchar i;CSN = 0; // CSN置低,开始传输数据SPI_RW(reg); // 选择寄存器,同时返回状态字for(i=0; i<bytes; i++)SPI_RW(pBuf[i]); // 逐个字节写入nRF24L01CSN = 1; // CSN拉高,结束数据传输}/*************************以下是nrf24l01的应用层函数*******************************************/void nrf_delay(){uint a=130*10;while(a--);}/*************************************************************************** NRF24L01初始化/**************************************************************************/ void init_NRF24L01(void){CE=0; // 待机// SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // 配置寄存器设置为接收模式SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 通道0自动ACK应答允许0x01SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 允许接收地址只有通道0,如果需要多频道可以参考Page21 0x01// SPI_RW_Reg(WRITE_REG + SETUP_AW, 0x03); // 收发地址宽度设置为5个字节SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x0a); // 等待250+86us 重发10次SPI_RW_Reg(WRITE_REG + RF_CH, 0); // 设置信道工作为2.4GHZ,收发必须一致SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); //设置发射速率为1MHZ,发射功率为最大值0dBSPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS_0, RX_ADR_WIDTH); // 为了应答接收设备,接收通道0地址和发送地址相同SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写本地发送地址SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节EX1=1; //开外部中断1IT1=1; //下降沿触发EA=1; //开总中断}/***************************************************************************/*设置模式:b为0时是发送模式为1时是接收模式*//**************************************************************************/ void Set_Mode(char b){CE=0;SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e+b); // IRQ收发完成中断响应,16位CRC ,主接收CE = 1; // 模式转换要等待130Usnrf_delay();}/****************************************************************************** *****************************/*函数:bit nRF24L01_TxPacket(unsigned char * tx_buf)/*功能:发送tx_buf中数据返回1数据发送/****************************************************************************** ****************************/bit nRF24L01_TxPacket(uchar * tx_buf){bit val=0;if(TX_OK){TX_OK=0;CE=0; //StandBy I模式SPI_RW_Reg(WRITE_REG+STATUS,sta); //发送完数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志// CSN = 0; // CSN置低,开始传输数据// SPI_RW(FLUSH_TX);//数据成功发送到了接收端,此时状态寄存器的TX_DS位置高并把数据从TX FIFO中清除掉//所以这里就不要再清除TX FIFO了// CSN = 1; // CSN置低,开始传输数据SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 装载数据SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送CE=1; //置高CE,激发数据发送val = 1;}else if(MAX_RT_OK){MAX_RT_OK=0;SPI_RW_Reg(WRITE_REG+STATUS,sta); //发送完数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志CSN = 0; // CSN置低,开始传输数据SPI_RW(FLUSH_TX); //MAX_RT位置高,不清除TX FIFO 中的数据所以这里要清除TX FIFOCSN = 1;TX_OK=1;}return val;}/****************************************************************************** ************************//*函数:bit nRF24L01_RxPacket(uchar* rx_buf)/*功能:数据读取后放如rx_buf接收缓冲区中/****************************************************************************** ************************/bit nRF24L01_RxPacket(uchar* rx_buf){bit revale=0;if(RX_OK) // 判断是否接收到数据{RX_OK=0; //接收数据标志清零CE = 0; //SPI使能SPI_Read_Buf(RD_RX_PLOAD,rx_buf,RX_PLOAD_WIDTH);// read receive payload from RX_FIFO bufferSPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志CSN = 0; // CSN置低,开始传输数据SPI_RW(FLUSH_RX); //用于清空FIFO !!CSN = 1; // CSN置低,开始传输数据revale =1; //读取数据完成标志Set_Mode(1); //重新设置为接收模式}return revale;}/*NRF24L01 IRQ引脚产生的中断函数*/void Int_1() interrupt 2{sta=SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状况if(RX_DR) //接收到数据了RX_OK=1;if(TX_DS) //数据发送完毕TX_OK=1;if(MAX_RT)MAX_RT_OK=1;}/**************************************************//*************************************************文件名: NRF24L01.h**创建人: 动车组**日期: 2012-8-21•**功能描述:用NRF24L01发送一定字节数的数据或者接收数据**占用资源:四位控制SPI总线的IO线和1位NRF24L01模式控制引脚** 占用一个中段***********************************************/#ifndef __NRF24L01_H__#define __NRF24L01_H__#include <REG52.H>#define uint unsigned int#define uchar unsigned char//********************SPI 引脚号********************************sbit M ISO=P1^6; // 7 主入从出sbit SCK =P1^7; // 5 SPI 时钟由主机产生sbit CSN =P3^7; // 4 SPI使能为1时SPI禁止sbit MOSI=P1^5; // 6 主出从入//********************NRF24L01引脚*********************sbit CE =P3^6;sbit IRQ =P3^3; //中断引脚#define TX_PLOAD_WIDTH 32 // 发送字节数在这里设置发送和接收要一样#define RX_PLOAD_WIDTH 32 // 接收字节数在这里设置void init_NRF24L01(void); //NRF24L01初始化已经中断初始化了void Set_Mode(char b);///*设置模式:b为0时是发送模式为1时是接收模式*/bit nRF24L01_TxPacket(uchar * tx_buf);//发送tx_buf中数据返回1数据发送bit nRF24L01_RxPacket(uchar* rx_buf) ;//返回1时数据读取后放如rx_buf接收缓冲区中否则没有数据#define TX_ADR_WIDTH 5 // 5 uints TX address width#define RX_ADR_WIDTH 5 // 5 uints RX address width//***************************************NRF24L01寄存器指令**********************************#define READ_REG 0x00 // 读寄存器指令/**************************************************000A AAAA 读配置寄存器;AAAAA 指出读操作的寄存器地址**************************************************/#define WRITE_REG 0x20 // 写寄存器指令/****************************************************************************** **************001A AAAA 写配置寄存器;AAAAA 指出写操作的寄存器地址只有在掉电模式和待机模式下可操作******************************************************************************* **************/#define RD_RX_PLOAD 0x61 // 读取接收数据指令/****************************************************************************** **************0110 0001 读RX有效数据;1-32字节,读操作全部从字节0开始,当读RX有效数据完成后FIFO寄存器中有效数据被清除;应用于接收模式下******************************************************************************* **************/#define WR_TX_PLOAD 0xA0 // 写待发数据指令/****************************************************************************** ***************1010 0000 写TX有效数据,1-32字节写操作,从字节0开始;应用于发射模式下/****************************************************************************** ***************/#define FLUSH_TX 0xE1 // 冲洗发送FIFO指令/****************************************************************************** ***************1110 0001 清除TX FIFO 寄存器,应用于发射模式下*********************************************************************************************/#define FLUSH_RX 0xE2 // 冲洗接收FIFO指令/****************************************************************************** ***************1110 0010 清除RX FIFO 寄存器;应用于接收模式下.在传输应答信号过程中不应执行此指令,也就是说若传输应答信号过程中执行此指令的话,将使得应答信号不能被完整的传输******************************************************************************* **************/#define REUSE_TX_PL 0xE3 // 定义重复装载数据指令/****************************************************************************** ***************1110 0011 重新使用上一包有效数据,当CE为高过程中数据包被不断的重新发射在发射数据包过程中必须禁止数据包重利用功能******************************************************************************* **************/#define NOP 0xFF // 保留/****************************************************************************** ***************1111 1111 空操作,可以用来读状态寄存器******************************************************************************* **************///*************************************SPI(nRF24L01)寄存器地址*******************************#define CONFIG 0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式/****************************************************************************** ***************寄存器位复位值类型描述reserved 7 0 R/W 默认为0MASK_RX_DR 6 0 R/W 可屏蔽中断RX_RD,1:IRQ引脚不显示RX_RD中断;0:RX_RD中断产生时IRQ引脚电平为低MASK_TX_DS 5 0 R/W 可屏蔽中断TX_DS,1:IRQ引脚不显示TX_DS中断;0:TX_DS中断产生时IRQ引脚电平为低MASK_MAX_RT 4 0 R/W 可屏蔽中断MAX_RT,1:IRQ引脚不显示TX_DS 中断;0:MAX_RT中断产生时IRQ引脚电平为低EN_CRC 3 1 R/W CRC使能.如果EN_AA中任意一位为高,则EN_CRC强迫为高CRCO 2 0 R/W CRC 模式:‘0’-8 位CRC 校验;‘1’-16 位CRC 校验PWR_UP 1 0 R/W 1:上电;0:掉电PRIM_RX 0 0 R/W 1:接收模式0:发射模式******************************************************************************* **************/#define EN_AA 0x01 // 自动应答功能设置此功能禁止后可与nRF2401 通讯/****************************************************************************** ***************位7:6保留(00) 位5:0(11 1111):数据通道5-0自动应答允许******************************************************************************* **************/#define EN_RXADDR 0x02 // 可用信道设置接收地址允许/****************************************************************************** ***************位7:6保留(00) 位5:0(00 0011):接收数据通道5-0允许******************************************************************************* **************/#define SETUP_AW 0x03 // 收发地址宽度设置/****************************************************************************** ***************位7:2保留(0000 00) 位1:0(11):接收/发射地址宽度00:无效;01:三字节;10:四字节;11:五字节******************************************************************************* **************/#define SETUP_RETR 0x04 // 自动重发功能设置/****************************************************************************** ***************位7:4(0000) 自动重发延时= ((位7:4)+1)*250+86us延时时间是指一包数据发送完成到下一包数据开始发射之间的时间间隔位3:0(0011):自动重发计数自动重发(位3:0)次例如复位值是自动重发3次******************************************************************************* **************/#define RF_CH 0x05 // 工作频率设置/****************************************************************************** ***************位7保留(0) 位6:0(000 0010):设置nRF24L01 工作通道频率******************************************************************************* **************/#define RF_SETUP 0x06 // 射频寄存器/****************************************************************************** ***************位7:5保留(000) 位4(0):PLL_LOCK 允许;仅应用于测试模式位3(1): 数据传输率:‘0’–1Mbps ‘1’2 Mbps位2:1保留(11) 发射功率:00-18dBm 01-12dBm 10-6dBm 11 0dBm 位0(1) 低噪声放大器增益******************************************************************************* **************/#define STATUS 0x07 // 状态寄存器/****************************************************************************** ***************寄存器位复位值类型描述Reserved 7 0 R/W 默认为0RX_DR 6 0 R/W 接收数据中断,当接收到有效数据后置一,写‘1’清除中断TX_DS 5 0 R/W 数据发送完成中断,当数据发送完成后产生中断.如果工作在自动应答模式下,只有当接收到应答信号后此位置一,写‘1’清除中断MAX_RT 4 0 R/W 达到最多次重发中断,写‘1’清除中断如果MAX_RT中断产生,则必须清除后系统才能进行通讯RX_P_NO 3:1 111 R 接收数据通道号000-101:数据通道号110:未使用111:RX FIFO 寄存器为空TX_FULL 0 0 R TX_FIFO寄存器满标志1:TX FIFO 寄存器满0: TX FIFO 寄存器未满,有可用空间******************************************************************************* **************/#define OBSERVE_TX 0x08 // 发送监测功能/****************************************************************************** ***************寄存器位复位值类型描述PLOS_CNT 7:4 0000 R 数据包丢失计数器,当写RF_CH 寄存器时此寄存器复位,当丢失15个数据包后此寄存器重启ARC_CNT 3:0 0000 R 重发计数器,发送新数据包时此寄存器复位******************************************************************************* **************/#define CD 0x09 // 地址检测载波检测/****************************************************************************** ***************寄存器位复位值类型描述Reserved 7:1 000000 RCD 0 0 R 载波检测******************************************************************************* **************/#define RX_ADDR_P0 0x0A // 频道0接收数据地址/****************************************************************************** ***************寄存器位复位值类型描述RX_ADDR_P0 39:0 0xE7E7E7E7E7 R/W 数据通道0接收地址最大长度5个字节先写低字节所写字节数量由SETUP_AW设定******************************************************************************* **************/#define RX_ADDR_P1 0x0B // 频道1接收数据地址 (0xC2C2C2C2C2)#define RX_ADDR_P2 0x0C // 频道2接收数据地址 (0xC2C2C2C2C3)#define RX_ADDR_P3 0x0D // 频道3接收数据地址 (0xC2C2C2C2C4)#define RX_ADDR_P4 0x0E // 频道4接收数据地址 (0xC2C2C2C2C5)#define RX_ADDR_P5 0x0F // 频道5接收数据地址 (0xC2C2C2C2C6)#define TX_ADDR 0x10 // 发送地址寄存器先写低字节,在增强型ShockBurstTM模式下RX_ADDR_P0与此地址相等#define RX_PW_P0 0x11 // 接收频道0接收数据长度位7:6保留(00);(位5:0)个字节有效数据宽度(00 0000)#define RX_PW_P1 0x12 // 接收频道1接收数据长度同上#define RX_PW_P2 0x13 // 接收频道2接收数据长度同上#define RX_PW_P3 0x14 // 接收频道3接收数据长度同上#define RX_PW_P4 0x15 // 接收频道4接收数据长度同上#define RX_PW_P5 0x16 // 接收频道5接收数据长度同上#define FIFO_STATUS 0x17 // FIFO栈入栈出状态寄存器设置/****************************************************************************** ***************寄存器位复位值类型描述Reserved 7 0 R/W 默认为0TX_REUSE 6 0 R 若TX_REUSE=1,则当CE位高电平状态时,不断发送上一数据包TX_REUSE 通过SPI 指令REUSE_TX_PL 设置通过W_TX_PALOAD或FLUSH_TX 复位TX_FULL 5 0 R TX FIFO 寄存器满标志1:TX FIFO 寄存器满0: TX FIFO 寄存器未满有可用空间TX_EMPTY 4 1 R TX FIFO 寄存器空标志1:TX FIFO 寄存器空0: TX FIFO 寄存器非空Reserved 3:2 00 R/W 墨认为00RX_FULL 1 0 R RX FIFO 寄存器满标志1:RX FIFO 寄存器满0: RX FIFO 寄存器未满有可用空间RX_EMPTY 0 1 R RX FIFO 寄存器空标志1:RX FIFO 寄存器空0: RX FIFO 寄存器非空******************************************************************************* **************/#endif/****************************/#include <REG52.H>#include"C_Ko.h"#include"nrf24l01.h"#define uchar unsigned char#define uint unsigned intvoid main(){uchar tab[32];uchar i;UA TR_Init(); //串口初始化init_NRF24L01(); //NRF24L01初始化已经中断初始化了Set_Mode(1); //为1时是接收模式*/while(1){if(nRF24L01_RxPacket(tab)){for(i=0;i<32;i++){Uatr_Print_Char(tab[i]);Uatr_Prints("\t\n");}}}}/***********串口程序在这里!/view/5282ded1195f312b3169a5a0.html?st=1 ***************/。
浅谈基于NRF24L01无线SPI通信协议的理解及VC
浅谈基于NRF24L01无线SPI通信协议的理解及
VC++6.0的模拟
#include<stdio.h>
#define uchar unsigned char //类型定义
uchar ch=0x63,mosi; //ch为待传输数据
uchar MISO,MOSI; //SPI通信MISO和MOSI的两根线,由于仿真,没有设置SCK
void main()
{ int i;
for(i=0;i<8;i++) //满足一个字节,即8个二进制位后,运算结束
{ MOSI=(ch&0x80); //MOSI与0x80即1000 0000作与运算
MOSI=(MOSI!=0); //如果MOSI为1000 0000 则不等于0为真为1 否则为0,因为单片机引脚只有0 1两种状态
ch=(ch<<1); //将ch左移,最右边用0补齐
MISO=MOSI; //将MOSI传输到NRF24L01,NRF24L01并将MOSI得到的0或1输入到单片机
printf("%d",MISO); //输出MISO 检查
ch|=MISO; //将MISO 与ch作或运算,相当于将ch左移后,将最左边挤出的数值转移到最右边
}
实验结果如下图。
NRF24L01多路通讯调试成功的关键--附程序文件
NRF24L01多路通讯调试成功的关键(附基于串口助手的无线通讯工具源代码)本文档部分容摘自网络,由于按照网上教程调试总不成功,特此分享自己的失败经验(红字加重)。
一、收发端共同的设置1、设置信道工作频率(收发必须一致)如:SPI_RW_Reg(WRITE_REG+RF_CH,40);2、设置发射速率(2mbps或1mbps)和发射功率(收发必须一致);如:SPI_RW_Reg(WRITE_REG+RF_SETUP,0x0f); //发射速率为2Mbps,发射功率最大为0dB二、接收端的设置(最关键)1、设置频道0-5,自动ACK应答允许如: SPI_RW_Reg(WRITE_REG+EN_AA,0x3f);2、设置接收通道全部允许如: SPI_RW_Reg(WRITE_REG+EN_RXADDR,0x3f);3、向发送地址寄存器写入本地地址(5byte)4、向各个频道的接收地址寄存器写入接收地址(调试成不成功的关键)频道0:5个字节的地址频道1:5个字节的地址(和频道0的地址必须不同)频道2:1个字节的地址(为该通道发射机地址的最后一个字节·)有一个配置为发射模式的24l01要通过该通道与接收机通信,发射机的本地地址为{0x37,0xa1,0xb3,0xc9,0xda};则接收机频道2的地址为(0x37)频道3:1个字节的地址(同上)频道4:1个字节的地址(同上)频道5:1个字节的地址(同上)5、向每个频道(用那个写那个,需要在上面配置允许通道接收和ack·)接收数据长度寄存器写入接收数据宽度(最快均为32)频道n:SPI_RW_Reg(WRITE_REG + RX_PW_Pn, RX_PLOAD_WIDTH);如:频道5:SPI_RW_Reg(WRITE_REG + RX_PW_P5, RX_PLOAD_WIDTH);6、配置为接收模式如:SPI_RW_Reg(WRITE_REG+CONFIG,0x0f);下面附上我的程序/***************************头文件******************************/#ifndef __NRF24L01_H__#define __NRF24L01_H__sbit CE = P1^2;sbit CSN = P1^3;sbit IRQ = P1^4;sbit MOSI = P1^5;sbit MISO = P1^6;sbit SCK = P1^7;void NRF24L01_init(); //初始化模块uchar TX_packet(uchar *tx_buf); //返回值判断是否成功uchar RX_packet(uchar *rx_buf); //返回值判断是否成功void TX_MODE(); //发送模式void RX_MODE(); //接收模式//****************************************************************//// SPI(nRF24L01) commands#define READ_REG 0x00 // Define read command to register#define WRITE_REG 0x20 // Define write command to register#define RD_RX_PLOAD 0x61 // Define RX payload register address#define WR_TX_PLOAD 0xA0 // Define TX payload register address#define FLUSH_TX 0xE1 // Define flush TX register command#define FLUSH_RX 0xE2 // Define flush RX register command#define REUSE_TX_PL 0xE3 // Define reuse TX payload register command#define NOP 0xFF // Define No Operation, might be used to read status register//***************************************************//// SPI(nRF24L01) registers(addresses)#define CONFIG 0x00 // 'Config' register address#define EN_AA 0x01 // 'Enable Auto Acknowledgment' register address #define EN_RXADDR 0x02 // 'Enabled RX addresses' register address#define SETUP_AW 0x03 // 'Setup address width' register address#define SETUP_RETR 0x04 // 'Setup Auto. Retrans' register address#define RF_CH 0x05 // 'RF channel' register address#define RF_SETUP 0x06 // 'RF setup' register address#define STATUS 0x07 // 'Status' register address#define OBSERVE_TX 0x08 // 'Observe TX' register address#define CD 0x09 // 'Carrier Detect' register address#define RX_ADDR_P0 0x0A // 'RX address pipe0' register address#define RX_ADDR_P1 0x0B // 'RX address pipe1' register address#define RX_ADDR_P2 0x0C // 'RX address pipe2' register address#define RX_ADDR_P3 0x0D // 'RX address pipe3' register address#define RX_ADDR_P4 0x0E // 'RX address pipe4' register address#define RX_ADDR_P5 0x0F // 'RX address pipe5' register address#define TX_ADDR 0x10 // 'TX address' register address#define RX_PW_P0 0x11 // 'RX payload width, pipe0' register address#define RX_PW_P1 0x12 // 'RX payload width, pipe1' register address#define RX_PW_P2 0x13 // 'RX payload width, pipe2' register address#define RX_PW_P3 0x14 // 'RX payload width, pipe3' register address #define RX_PW_P4 0x15 // 'RX payload width, pipe4' register address #define RX_PW_P5 0x16 // 'RX payload width, pipe5' register address #define FIFO_STATUS 0x17 // 'FIFO Status Register' register address//***************************************************************//#endif/*********************************程序***********************************/ #include<reg52.h>#include"define.h"#include"DELAY.h"#include"NRF24L01.h"uchar code TX_ADDRESS[5] = {0,1,1,1,1};uchar code RX_ADDRESS_P0[5] = {0,1,1,1,1};uchar code RX_ADDRESS_P1[5] = {1,1,1,1,1};uchar code RX_ADDRESS_P2[1] = {2};uchar code RX_ADDRESS_P3[1] = {3};uchar code RX_ADDRESS_P4[1] = {4};uchar code RX_ADDRESS_P5[1] = {5};uchar code Data_width = 1;uchar code Data_rt = 15;uchar SPI_RW(uchar dat) // SPI读写指令{uchar i;for(i=0;i<8;i++){SCK = 0;MOSI = (dat&0x80);dat <<= 1;SCK = 1;dat |= MISO;}SCK = 0;return dat;}uchar NRF24L01_read_reg(uchar reg) //读某个寄存器的状态{uchar value;CSN=0; //拉低CSN,允许操作SPI_RW(reg); //写寄存器指令value = SPI_RW(0); //读寄存器值CSN=1; //拉高CSN,禁止操作return value; //返回寄存器状态}uchar NRF24L01_write_reg(uchar reg,uchar value) //写向某个寄存器写指令,并读出状态{uchar status;CSN=0; //拉低CSN,允许操作status = SPI_RW(reg); //写寄存器指令,并读出寄存器状态SPI_RW(value); //写寄存器值CSN=1; //拉高CSN,禁止操作return status; //返回寄存器之前的值}uchar NRF24L01_read_buf(uchar reg,uchar *pbuf,uchar n){uchar i,status;CSN=0; //拉低CSN,允许操作status = SPI_RW(reg); //写寄存器指令,并读出寄存器状态for(i=0;i<n;i++)pbuf[i] = SPI_RW(0);//从寄存器读出一字节数据CSN = 1; //拉高CSN,禁止操作return status;}uchar NRF24L01_write_buf(uchar reg,uchar *pbuf,uchar n){uchar i,status;CSN=0; //拉低CSN,允许操作status = SPI_RW(reg); //写寄存器指令,并读出寄存器状态for(i=0;i<n;i++)SPI_RW(pbuf[i]); //写一字节数据到寄存器CSN = 1; //拉高CSN,禁止操作return status;}void NRF24L01_init(){CE = 0; //射频电路工作使能,高电平工作,低电平停止CSN = 1; //SPI操作高电平允许,低电平禁止SCK = 0; //时钟拉低,禁止读写寄存器IRQ = 1; //中断复位,等待产生中断信号NRF24L01_write_reg(WRITE_REG + EN_AA, 0x3f); //所有接受通道允许自动应答NRF24L01_write_reg(WRITE_REG + EN_RXADDR, 0x3f); //接收通道全部打开NRF24L01_write_reg(WRITE_REG + SETUP_AW, 0x03); //设置接收/发射地址宽度为5字节NRF24L01_write_reg(WRITE_REG + SETUP_RETR, Data_rt); //自动发送间隔250+86us,次数15NRF24L01_write_reg(WRITE_REG + RF_CH, 0x00); //设置信道工作为2.4Ghz,收发必须一致NRF24L01_write_reg(WRITE_REG + RX_PW_P0, Data_width); //设置通道0数据字节数NRF24L01_write_reg(WRITE_REG + RX_PW_P1, Data_width); //设置通道1数据字节数NRF24L01_write_reg(WRITE_REG + RX_PW_P2, Data_width); //设置通道2数据字节数NRF24L01_write_reg(WRITE_REG + RX_PW_P3, Data_width); //设置通道3数据字节数NRF24L01_write_reg(WRITE_REG + RX_PW_P4, Data_width); //设置通道4数据字节数NRF24L01_write_reg(WRITE_REG + RX_PW_P5, Data_width); //设置通道5数据字节数NRF24L01_write_reg(WRITE_REG + RF_SETUP, 0x0f); //发送速率为1Mhz,发送功率最大值0dbNRF24L01_write_buf(WRITE_REG + TX_ADDR,TX_ADDRESS,5); //写本机地地址NRF24L01_write_buf(WRITE_REG + RX_ADDR_P0,RX_ADDRESS_P0,5); //写数据通道0接收机地址NRF24L01_write_buf(WRITE_REG + RX_ADDR_P1,RX_ADDRESS_P1,5); //写数据通道1接收机地址NRF24L01_write_buf(WRITE_REG + RX_ADDR_P2,RX_ADDRESS_P2,1); //写数据通道2接收机地址NRF24L01_write_buf(WRITE_REG + RX_ADDR_P3,RX_ADDRESS_P3,1); //写数据通道3接收机地址NRF24L01_write_buf(WRITE_REG + RX_ADDR_P4,RX_ADDRESS_P4,1); //写数据通道4接收机地址NRF24L01_write_buf(WRITE_REG + RX_ADDR_P5,RX_ADDRESS_P5,1); //写数据通道5接收机地址void RX_MODE(){NRF24L01_write_reg(WRITE_REG + CONFIG, 0x0f);//IRQ收发完成中断响应,16位CRC,接收模式CE = 1;}void TX_MODE(){NRF24L01_write_reg(WRITE_REG + CONFIG, 0x0e);//IRQ收发完成中断响应,16位CRC,发送模式CE = 1;}uchar TX_packet(uchar *tx_buf){uchar tx_flag = 1;CE = 0; //停止射频电路工作NRF24L01_write_reg(WRITE_REG + STATUS,0xff); //清除中断标志位NRF24L01_write_buf(WR_TX_PLOAD,tx_buf,Data_width); //装载要发送的数据CE = 1; //置高CE,激发数据发送Delay_ms(Data_rt/2);if(NRF24L01_read_reg(STATUS)&0x10)tx_flag = 0;return(tx_flag);}uchar RX_packet(uchar *rx_buf){uchar revalue = 0,sta;sta = NRF24L01_read_reg(STATUS); //读状态寄存器if(sta&0x40) //如果接受中断标志位为1{CE = 0; //SPI使能NRF24L01_read_buf(RD_RX_PLOAD,rx_buf,Data_width); //读取数据revalue = 1; //读取数据完成标志置1NRF24L01_write_reg(WRITE_REG + STATUS,0xff); //清除中断标志位}CE = 1;return revalue;//返回读取数据完成标志}。
nrf接收c程序
sbit LED=P0^0;
uchar code TX_Addr[]={0x34,0x43,0x10,0x10,0x01};
uchar code TX_Buffer[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
uchar RX_Buffer[RX_DATA_WITDH];
#define EN_RX_ADDR 0x02 // 接收通道使能寄存器
#define SETUP_AW 0x03 // 地址宽度设置寄存器
#define SETUP_RETR 0x04 // 自动重发设置寄存器
#define RF_CH 0x05 // 射频通道频率设置寄存器
#define W_TX_PLOAD 0xA0 // 写TX FIFO有效数据,1-32字节,写操作从字节0开始,应用于发射模式
#define FLUSH_TX 0xE1 // 清除TX FIFO寄存器,应用于发射模式
#define FLUSH_RX 0xE2 // 清除RX FIFO寄存器,应用于接收模式
}
void nRF24L01_Init(void)
{
_delay_us(2000);
CE=0;
CSN=1;
SCKI_RW(uchar byte)
{
uchar i;
for(i=0;i<8;i++)
{
if(byte&0x80)
reg_value=SPI_RW(reg);
for(i=0;i<Dlen;i++)
{
SPI_RW(TX_Dat_Buffer[i]);
NRF24L01无线模块C语言程序
NRF24L01无线模块C语言程序24MHz晶振#include#include#include#include#include#include#define U8 unsigned char#define U16 unsigned int#define TX_ADDR_WITDH 5 //发送地址宽度设置为5个字节#define RX_ADDR_WITDH 5 //接收地址宽度设置为5个字节#define TX_DATA_WITDH 1//发送数据宽度1个字节#define RX_DATA_WITDH 1//接收数据宽度1个字节#define R_REGISTER 0x00//读取配置寄存器#define W_REGISTER 0x20//写配置寄存器#define R_RX_PAYLOAD 0x61//读取RX有效数据#define W_TX_PAYLOAD 0xa0//写TX有效数据#define FLUSH_TX 0xe1//清除TXFIFO寄存器#define FLUSH_RX 0xe2//清除RXFIFO寄存器#define REUSE_TX_PL 0xe3//重新使用上一包有效数据#define NOP 0xff//空操作#define CONFIG 0x00//配置寄存器#define EN_AA 0x01//使能自动应答#define EN_RXADDR 0x02//接收通道使能0-5个通道#define SETUP_AW 0x03//设置数据通道地址宽度3-5 #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//P0通道数据宽度设置#define RX_PW_P1 0x12//P1通道数据宽度设置#define RX_PW_P2 0x13//P2通道数据宽度设置#define RX_PW_P3 0x14//P3通道数据宽度设置#define RX_PW_P4 0x15//P4通道数据宽度设置#define RX_PW_P5 0x16//P5通道数据宽度设置#define FIFO_STATUS 0x17//FIFO状态寄存器//NRF24L01U8 NRFACK();U8 NRFSPI(U8 date);U8 NRFReadReg(U8 RegAddr);U8 NRFWriteReg(U8 RegAddr,U8 date);U8 NRFReadRxDate(U8 RegAddr,U8 *RxDate,U8 DateLen);U8 NRFWriteTxDate(U8 RegAddr,U8 *TxDate,U8 DateLen);U8 NRFRevDate(U8 *RevDate);void NRFSetTxMode(U8 *TxDate);void NRF24L01Int();void NRFSetRXMode();U8 CheckACK();void Delay(U16 t);U8 bdata sta;//mainvoid Delay_10ms(U16 del);bit CE=P1^4; //RX/TX模式选择端sbit IRQ=P1^1; //可屏蔽中断端sbit CSN=P1^6; //SPI片选端//就是SSsbit MOSI=P1^0; //SPI主机输出从机输入端1sbit MISO=P1^2; //SPI主机输入从机输出端sbit SCLK=P1^3; //SPI时钟端U8 code TxAddr[]={0x34,0x43,0x10,0x10,0x01};//发送地址U8 bdata sta; //状态标志sbit RX_DR=sta^6;sbit TX_DS=sta^5;sbit MAX_RT=sta^4;void Delay(U16 t){U16 x,y;for(x=t;x>0;x--)for(y=110;y>0;y--);}U8 NRFSPI(U8 date){U8 i;for(i=0;i<8;i++) // 循环8次{if(date&0x80)MOSI=1;elseMOSI=0; // byte最高位输出到MOSIdate<<=1; // 低一位移位到最高位SCLK=1;if(MISO) // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据date|=0x01; // 读MISO到byte最低位 SCLK=0; // SCK置低}return(date); // 返回读出的一字节}void NRF24L01Int(){Delay(2);//让系统什么都不干CE=0; //待机模式1CSN=1;SCLK=0;IRQ=1;}U8 NRFReadReg(U8 RegAddr){U8 BackDate;CSN=0;//启动时序NRFSPI(RegAddr);//写寄存器地址BackDate=NRFSPI(0x00);//写入读寄存器指令CSN=1;return(BackDate); //返回状态}U8 NRFWriteReg(U8 RegAddr,U8 date){U8 BackDate;CSN=0;//启动时序BackDate=NRFSPI(RegAddr);//写入地址NRFSPI(date);//写入值CSN=1;return(BackDate);}U8 NRFReadRxDate(U8 RegAddr,U8 *RxDate,U8 DateLen){ //寄存器地址//读取数据存放变量//读取数据长度//用于接收 U8 BackDate,i;CSN=0;//启动时序BackDate=NRFSPI(RegAddr);//写入要读取的寄存器地址for(i=0;i{RxDate[i]=NRFSPI(0);}CSN=1;return(BackDate);}U8 NRFWriteTxDate(U8 RegAddr,U8 *TxDate,U8 DateLen){ //寄存器地址//写入数据存放变量//读取数据长度//用于发送 U8 BackDate,i;CSN=0;BackDate=NRFSPI(RegAddr);//写入要写入寄存器的地址for(i=0;i{NRFSPI(*TxDate++);}CSN=1;return(BackDate);}void NRFSetTxMode(U8 *TxDate){//发送模式CE=0;NRFWriteTxDate(W_REGISTER+TX_ADDR,TxAddr,TX_ADDR_WITDH);//写寄存器指令+接收地址使能指令+接收地址+地址宽度NRFWriteTxDate(W_REGISTER+RX_ADDR_P0,TxAddr,TX_ADDR_WITDH);//为了应答接收设备,接收通道0地址和发送地址相同NRFWriteTxDate(W_TX_PAYLOAD,TxDate,TX_DATA_WITDH);//写入数据NRFWriteReg(W_REGISTER+EN_AA,0x01); // 使能接收通道0自动应答NRFWriteReg(W_REGISTER+EN_RXADDR,0x01); // 使能接收通道0NRFWriteReg(W_REGISTER+SETUP_RETR,0x0a); // 自动重发延时等待250us+86us,自动重发10次NRFWriteReg(W_REGISTER+RF_CH,0x40); // 选择射频通道0x40NRFWriteReg(W_REGISTER+RF_SETUP,0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益NRFWriteReg(W_REGISTER+CONFIG,0x0e); // CRC使能,16位CRC 校验,上电CE=1;Delay(5);//保持10us秒以上}//主要接收模式void NRFSetRXMode(){CE=0;NRFWriteTxDate(W_REGISTER+RX_ADDR_P0,TxAddr,TX_ADDR_WITDH); // 接收设备接收通道0使用和发送设备相同的发送地址NRFWriteReg(W_REGISTER+EN_AA,0x01);// 使能接收通道0自动应答NRFWriteReg(W_REGISTER+EN_RXADDR,0x01); // 使能接收通道0NRFWriteReg(W_REGISTER+RF_CH,0x40);// 选择射频通道0x40NRFWriteReg(W_REGISTER+RX_PW_P0,TX_DATA_WITDH); // 接收通道0选择和发送通道相同有效数据宽度NRFWriteReg(W_REGISTER+RF_SETUP,0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益*/NRFWriteReg(W_REGISTER+CONFIG,0x0f); / / CRC使能,16位CRC校验,上电,接收模式CE = 1;Delay(5);//保持10us秒以上}U8 CheckACK(){ //用于发射sta=NRFReadReg(R_REGISTER+STATUS);// 返回状态寄存器if(TX_DS||MAX_RT) //发送完毕中断{NRFWriteReg(W_REGISTER+STATUS,0xff); // 清除TX_DS或MAX_RT 中断标志CSN=0;NRFSPI(FLUSH_TX);//用于清空FIFO !!关键!!不然会出现意想不到的后果!!!大家记住!!CSN=1;return(0);}elsereturn(1);}//用于接收模式U8 NRFRevDate(U8 *RevDate){U8 RevFlags=0;sta=NRFReadReg(R_REGISTER+STATUS);//发送数据后读取状态寄存器 if(RX_DR) // 判断是否接收到数据{CE=0; //SPI使能NRFReadRxDate(R_RX_PAYLOAD,RevDate,RX_DATA_WITDH);// 从RXFIFO读取数据RevFlags=1; //读取数据完成标志}NRFWriteReg(W_REGISTER+STATUS,0xff); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标return(RevFlags);}void Delay_10ms(U16 del){U16 i,j;for(i=0; i<del; i++)for(j=0; j<1827; j++) //这个是通过软件仿真得出的数;}// 做发射main(){U8 TxDate[1]={0};NRF24L01Int();Delay(6000);while(1){if(KEY==0){if(KEY==0){Delay_10ms(2);TxDate[0]=0x08;//发射按键标识值NRFSetTxMode(TxDate);while(CheckACK());TxDate[0]=0;}}}}//// 做接收:一直处于接受模式查询所得到的值是不是0x08 main(){U8 x;U8 RxBuf[1]={0};NRF24L01Int();Delay(6000);while(1){NRFSetRXMode();NRFRevDate(RxBuf);x=RxBuf[0];if(x==0x08)//0x08为发射部分所发送的按键标识{////加入所要执行的功能函数//当然了这里用到单片机io口的时候需要在之前定义//还有就是发送程序中的KEY也需要之前定义好 RxBuf[0]=0;}}}。
nrf24l01的调试测试程序
nrf24l01的调试测试程序参考了很多程序,经过测试,才看懂nrf24l01的状态机,在看数据手册时很多地方都不懂后来看了关于调试的文章再自己测试了一下某些功能,只测试了一边发送,一边接收的功能,做的很妥跟网上的程序相差无几。
#include <REG51.H>#include 'NRF24L01.h'#define TX_ADDR_WIDTH 5 //本地发射地址宽度#define RX_ADDR_WIDTH 5 //本地接收地址宽度#define TX_DATA_WIDTH 3 //发送数据字节数最大字节数为32字节#define RX_DATA_WIDTH 3 //接收数据字节数unsigned char code TX_ADDRESS[TX_ADDR_WIDTH]={0x78,0x78,0x78,0x78,0x78}; //发射通道地址unsigned char code RX_ADDRESS_P0[RX_ADDR_WIDTH]={0x78,0x78,0x78,0x78,0x78 }; //接收通道地址unsigned char bdata status; //定义一个位与字节都可以访问的变量用来监控IRQ中断信号sbit RX_DR=status^6; //当接收到有效数据后变为1sbit TX_DR=status^5; //当数据发送完成后产生中断,在自动应答模式中接收到应答信号后为1sbit MAX_RT=status^4; //当达到最大重发次数后变为1,产生此中断后必须清零后才能再次通讯void usdelay(void) //误差 -0.149305555556us 12us{unsigned char a,b;for(b=1;b>0;b--)for(a=2;a>0;a--);}void usdelay130(void) //误差 -0.451388888889us{unsigned char a,b;for(b=11;b>0;b--)for(a=4;a>0;a--);}unsigned char SPI_RW(unsigned char uchar) //SPI协议{unsigned char i;for(i=0;i<8;i++){SCK=0;MOSI=uchar&0x80; //从字节高位向NRF24L01写数据uchar=uchar<<1;SCK=1;uchar=uchar|MISO; //接收从NRF24L01发过来的数据SCK=0;}return uchar; //返回读取的值}unsigned char SPI_read(unsigned char reg) //SPI读操作两个字节完成读一次 reg:读指令{unsigned char bl;CSN=0;SPI_RW(reg); //第一个字节写读某个寄存器的指令此时返回值为状态寄存器的值bl=SPI_RW(0); //第二个字节返回所需要的寄存器的值CSN=1;return bl;unsigned char SPI_write(unsigned char reg,unsigned char value) //SPI写操作写一个字节的数据先写指令说明往哪个寄存器写数据,reg:指令,value:数据{unsigned char status;CSN=0;status=SPI_RW(reg); //写指令并返回状态寄存器的值SPI_RW(value); //写数据CSN=1;return status; //返回状态寄存器的值}unsigned char SPI_read_more(unsigned char reg,unsigned char *puf_read,unsigned char width) //读取多个数据 reg:指令,*puf 存储数据的指针,width:要读取数据的长度{unsigned char i,status;CSN=0;status=SPI_RW(reg); //写指令并返回状态寄存器的值for(i=0;i<width;i++) //循环读出数据puf_read[i]=SPI_RW(0); //将循环读出的数据存储在一个数组中}CSN=1;return status;}unsigned char SPI_write_more(unsigned char reg,unsigned char *puf_write,unsigned char width) //写多个数据 reg:指令,*puf:要写的数据,width:数据长度{unsigned char i,status;CSN=0;status=SPI_RW(reg); //写指令并返回状态寄存器的值for(i=0;i<width;i++) //循环写入数据{SPI_RW(*puf_write++);}CSN=1;return status;}void receive_model() //接收模式初始化配置{CE=0; //掉电模式此时PWR_UP为0CSN=1; //停止寄存器读写SCK=0; //时钟信号停止读写IRQ=1; //中断复位SPI_write_more(WRITE_REG+RX_ADDR_P0,RX_ADDRESS_P0, RX_ADDR_WIDTH); //写本地接收的地址SPI_write(WRITE_REG+EN_AA,0x00); //失能自动应答SPI_write(WRITE_REG+EN_RXADDR,0x01); //接收通道0允许SPI_write(WRITE_REG+RF_CH,0x00); //通信频率 2.4GSPI_write(WRITE_REG+RX_PW_P0,TX_DATA_WIDTH); //设置数据通道0传输数据宽度为3个字节SPI_write(WRITE_REG+RF_SETUP,0x09); //设置发射参数:传输速率,发射功率SPI_write(WRITE_REG+CONFIG,0x0F); //配置寄存器,设置CRC 和工作模式(接收模式)CE=1; //启动}void send_model() //发射模式初始化配置{CE=0; //掉电模式此时PWR_UP为0CSN=1; //停止寄存器读写SCK=0; //时钟信号停止读写IRQ=1; //中断复位SPI_write_more(WRITE_REG+TX_ADDR,TX_ADDRESS,TX_AD DR_WIDTH); //写本地发射地址SPI_write_more(WRITE_REG+RX_ADDR_P0,RX_ADDRESS_P0,RX_ADDR_WIDTH); //写本地接收(主要用来使能自动应答) SPI_write(WRITE_REG+EN_AA,0x00); //失能自动应答功能SPI_write(WRITE_REG+EN_RXADDR,0x00); //失能接收通道0 SPI_write(WRITE_REG+SETUP_RETR,0x00); //失能自动重发SPI_write(WRITE_REG+RF_CH,0x00); //通信频率 2.4GSPI_write(WRITE_REG+RX_PW_P0,RX_DATA_WIDTH); //设置接收数据长度为3个字节SPI_write(WRITE_REG+RF_SETUP,0x09); //设置发射参数:传输速率2MHZ,发射功率SPI_write(WRITE_REG+CONFIG,0x0e); //配置寄存器,设置CRC 和工作模式(发射模式)CE=1; //启动}void send_data(unsigned char *pArray) //发送数据{CE=0; //停止射频工作,待机模式1//SPI_write_more(WRITE_REG+RX_ADDR_P0,TX_ADDRESS,TX_ADD R_WIDTH); //装载接收端地址此地址单对单发送时可只初始化一次SPI_write_more(WR_TX_PLOAD,pArray,3); //向nrf24l01传入要发送的数据// SPI_write(WRITE_REG+CONFIG,0x0e); //IRQ收发完成中断响应,16位CRC,发送模式此功能在但对单发送时可初始化一次CE=1; //置高CE,激发数据usdelay(); //10us的延时}unsigned char read_data(unsigned char *pArray) //读取接收的数据 *pArray:传入存放数据的数组{unsigned char mark;CE=1; //接收模式usdelay130(); //等待130usstatus=SPI_read(STATUS); //读取状态寄存器的值来判断数据的接收情况if(RX_DR==1){CE=0; //接收完数据变成待机模式1SPI_read_more(RD_RX_PLOAD,pArray,RX_DATA_WIDTH); //读取数据并将其存放在RX_DATA中mark=1; //读取完成标志}SPI_write(WRITE_REG+STATUS,status); //清除中断标志位return mark;}/************************************************************** ************************************************/void main(){unsigned char mark,i; //接收完成标志delay(1000);receive_model(); //接收模式初始化配置delay(1000);while(1){mark=read_data(RX_DATA);if(mark==1){i++;SPI_write(FLUSH_RX,0); //清空RX_FIFO 中的缓存数据接受不像发送会自动清空缓存区的数据if(RX_DATA[0]==0&&RX_DATA[1]==1&&RX_DATA[2]==2) {led0=0;delay(100);RX_DATA[0]=0;RX_DATA[1]=0;RX_DATA[2]=0;}mark=0;}SPI_read(STATUS); //读状态寄存器SPI_read(FIFO_STATUS); //读FIFO状态led0=1;}}。
NRF24l01一对一双向通信程序(已调通)
以下程序参考多个网络程序后,经调试并且已经调通,可以稍加修改即可使用经测试可实现双向通信发送方本程序实现功能:从52单片机串口读入数据后通过24L01发送//24L01发送#include <reg52.h>#include <intrins.h>typedef unsigned char uchar;typedef unsigned char uint;//*******************NRF24L01端口定义***************************************sbit MISO =P1^4;sbit MOSI =P1^3;sbit SCK =P1^2;sbit CE =P1^0;sbit CSN =P1^1;sbit IRQ =P1^5;//************按键***************************************************//sbit KEY1=P3^6;//sbit KEY2=P3^7;//****************数码管位选*********************************************//sbit led3=P2^0;//sbit led2=P2^1;//sbit led1=P2^2;//sbit led0=P2^3;//**************蜂明器***************************************************//sbit BELL=P3^4;//*************数码管0-9编码*******************************************//uchar seg[10]={0xC0,0xCF,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //0~~9段码//******************************NRF24L01*************************************#define TX_ADR_WIDTH 5 // 5 uints TX address width#define RX_ADR_WIDTH 5 // 5 uints RX address width#define TX_PLOAD_WIDTH 10 // 20 uints TX payload#define RX_PLOAD_WIDTH 10 // 20 uints TX payloaduint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址//********************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 Delay(unsigned int s);void inerDelay_us(unsigned char n);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);//*******************长延时*****************************************void Delay(unsigned int s){unsigned int i;for(i=0; i<s; i++);for(i=0; i<s; i++);}//**********************************************************************uint bdata sta; //状态标志sbit RX_DR =sta^6;sbit TX_DS =sta^5;sbit MAX_RT =sta^4;/*******************************延时函数******/void inerDelay_us(unsigned char n){for(;n>0;n--)_nop_();}//******************************************NRF24L01初始化***************/ void init_NRF24L01(void){inerDelay_us(100);CE=0; // chip enableCSN=1; // Spi disableSCK=0; //SPI_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,如果需要多频道可以参考Page21SPI_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}/****************************************************************************** **********************/*函数:uint SPI_RW(uintuchar)/*功能:NRF24L01的SPI写时序/****************************************************************************** **********************/uint SPI_RW(uint uchar){uint bit_ctr;for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit{MOSI = (uchar& 0x80); // output 'uchar', MSB to MOSIuchar = (uchar<< 1); // shift next bit into MSB..SCK = 1; // Set SCK high..uchar |= MISO; // capture current MISO bitSCK = 0; // ..then set SCK low again }return(uchar); // return read uchar}/****************************************************************************** **********************/*函数:ucharSPI_Read(ucharreg)/*功能: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}/****************************************************************************** **********************//*函数:uintSPI_Read_Buf(ucharreg, uchar *pBuf, ucharuchars)/*功能: 用于读数据,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_ctr<uchars;uchar_ctr++)pBuf[uchar_ctr] = SPI_RW(0); //CSN = 1;return(status); // return nRF24L01 status uchar}/****************************************************************************** ***************************/*函数:uintSPI_Write_Buf(ucharreg, uchar *pBuf, ucharuchars)/*功能: 用于写数据:为寄存器地址,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_ctr<uchars; uchar_ctr++) //SPI_RW(*pBuf++);CSN = 1; //关闭SPIreturn(status); //}/****************************************************************************************************//*函数:void SetRX_Mode(void)/*功能:数据接收配置/****************************************************************************** **********************/void SetRX_Mode(void){CE=0;SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收发完成中断响应,16位CRC ,主接收CE = 1;inerDelay_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 bufferrevale =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); // 装载数据SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送CE=1; //置高CE,激发数据发送inerDelay_us(10);}//*********************************************// unsigned char tf =0;unsigned char TxBuf[10]={0}; //unsigned char RxBuf[10]={0};//*********************************************//************************************主函数************************************************************void main(void){//%%%%%%%单片机串口初始化//SCON=0x50;//SCON:模式1,8-bitUART,使能接收:REN=1TMOD=0x20;TH1=0xfd;//波特率9600初值TL1=0xfd;TR1=1;EA=1;//打开总中断ES=1;//打开串口中断//%%%%%%%%%%%%%//init_NRF24L01() ;//上面保留三句移到了全局变量while(1){nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer dataDelay(1000);// SPI_RW_Reg(WRITE_REG+STATUS,0xff);//清零状态寄存器?//***************************************************************************** ******************SetRX_Mode();nRF24L01_RxPacket(RxBuf);SBUF=RxBuf[0];//存放到本单片机串口输出??Delay(600);//??}}void UART_SER() interrupt 4{//uchar Temp;//定义临时变量if(RI){RI=0;//标志位清零//读入缓冲区的值TxBuf[0]=SBUF;//把输入的save到TxBuf里// Delay(1000);//??}if(TI)//如果是发送标志位,清零TI=0;}接收方:以下程序参考多个网络程序后,经调试并且已经调通,可以稍加修改即可使用本程序实现功能:24L01接收到数据后通过52单片机串口输出到电脑端查看,同时又把数据回传(发送)实现双向通信#include <reg52.h>#include <intrins.h>typedef unsigned char uchar;typedef unsigned char uint;//*******************NRF24L01端口定义*************************************** sbit MISO =P1^4;sbit MOSI =P1^3;sbit SCK =P1^2;sbit CE =P1^0;sbit CSN =P1^1;sbit IRQ =P1^5;//******************************NRF24L01*************************************#define TX_ADR_WIDTH 5 // 5 uints TX address width#define RX_ADR_WIDTH 5 // 5 uints RX address width#define TX_PLOAD_WIDTH 10 // 20 uints TX payload#define RX_PLOAD_WIDTH 10 // 20 uints TX payloaduint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址//********************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 Delay(unsigned int s);void inerDelay_us(unsigned char n);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);//*******************长延时*****************************************void Delay(unsigned int s){unsigned int i;for(i=0; i<s; i++);for(i=0; i<s; i++);}//********************************************************************** uint bdata sta; //状态标志sbit RX_DR =sta^6;sbit TX_DS =sta^5;sbit MAX_RT =sta^4;/*******************************延时函数******/void inerDelay_us(unsigned char n){for(;n>0;n--)_nop_();}//******************************************NRF24L01初始化***************/ void init_NRF24L01(void){inerDelay_us(100);CE=0; // chip enableCSN=1; // Spi disableSCK=0; //SPI_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,如果需要多频道可以参考Page21SPI_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}/****************************************************************************** **********************/*函数:uint SPI_RW(uintuchar)/*功能:NRF24L01的SPI写时序/****************************************************************************** **********************/uint SPI_RW(uint uchar){uint bit_ctr;for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit{MOSI = (uchar& 0x80); // output 'uchar', MSB to MOSIuchar = (uchar<< 1); // shift next bit into MSB..SCK = 1; // Set SCK high..uchar |= MISO; // capture current MISO bitSCK = 0; // ..then set SCK low again }return(uchar); // return read uchar}/****************************************************************************** **********************/*函数:ucharSPI_Read(ucharreg)/*功能: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}/****************************************************************************** **********************//*函数:uintSPI_Read_Buf(ucharreg, uchar *pBuf, ucharuchars)/*功能: 用于读数据,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_ctr<uchars;uchar_ctr++)pBuf[uchar_ctr] = SPI_RW(0); //CSN = 1;return(status); // return nRF24L01 status uchar}/****************************************************************************** ***************************/*函数:uintSPI_Write_Buf(ucharreg, uchar *pBuf, ucharuchars)/*功能: 用于写数据:为寄存器地址,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_ctr<uchars; uchar_ctr++) //SPI_RW(*pBuf++);CSN = 1; //关闭SPIreturn(status); //}/****************************************************************************** **********************//*函数:void SetRX_Mode(void)/*功能:数据接收配置/****************************************************************************** **********************/void SetRX_Mode(void){CE=0;SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收发完成中断响应,16位CRC ,主接收CE = 1;inerDelay_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 bufferrevale =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); // 装载数据SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送CE=1; //置高CE,激发数据发送inerDelay_us(10);}//*********************************************// unsigned char tf =0;unsigned char TxBuf[10]={0}; //unsigned char RxBuf[10]={0};//*********************************************//*********************************************//************************************主函数************************************************************void main(void){//%%%%%%%单片机串口初始化//SCON=0x50;//SCON:模式1,8-bitUART,使能接收:REN=1TMOD=0x20;TH1=0xfd;//波特率9600初值TL1=0xfd;TR1=1;EA=1;//打开总中断ES=1;//打开串口中断init_NRF24L01() ;//上面保留三句移到了全局变量while(1){SetRX_Mode();nRF24L01_RxPacket(RxBuf);TxBuf[0]=RxBuf[0];SBUF=RxBuf[0];nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer data // SPI_RW_Reg(WRITE_REG+STATUS,0xff);//清零状态寄存器?Delay(1000);}}void UART_SER() interrupt 4{if(RI){RI=0;}if(TI)//如果是发送标志位,清零TI=0;}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
NRF24L01使用文档
基于c8051f330单片机
目录
芯片简介 (3)
1 NRF24L01功能框图 (4)
2 NRF24L01状态机 (5)
3 Tx与Rx的配置过程 (7)
3.1 Tx模式初始化过程 (7)
3.2 Rx模式初始化过程 (8)
4控制程序详解 (9)
4.1函数介绍 (9)
4.1.1 uchar SPI_RW(uchar byte) (9)
4.1.2 uchar SPI_RW_Reg (uchar reg, uchar value) (10)
4.1.3 uchar SPI_Read (uchar reg); (10)
4.1.4 uchar SPI_Read_Buf (uchar reg, uchar *pBuf, uchar bytes); (11)
4.1.5 uchar SPI_Write_Buf (uchar reg, uchar *pBuf, uchar bytes); (11)
4.1.6 void RX_Mode(void) (12)
4.1.7 void TX_Mode(void) (13)
4.2 NRF24L01相关命令的宏定义 (13)
4.3 NRF24L01相关寄存器地址的宏定义 (14)
5实际通信过程示波器图 (16)
1)发射节点CE与IRQ信号 (17)
2)SCK与IRQ信号(发送成功) (18)
3)SCK与IRQ信号(发送不成功) (19)
内部使用-严禁用于商业用途by aaa1982
芯片简介
NRF24L01是NORDIC公司最近生产的一款无线通信通信芯片,采用FSK调制,内部集成NORDIC自己的Enhanced Short Burst协议。
可以实现点对点或是1对6的无线通信。
无线通信速度可以达到2M(bps)。
NORDIC公司提供通信模块的GERBER文件,可以直接加工生产。
嵌入式工程师或是单片机爱好者只需要为单片机系统预留5个GPIO,1个中断输入引脚,就可以很容易实现无线通信的功能,非常适合用来为MCU系统构建无线通信功能。