硬件平台:STM32F103+NRF24L01
nrf24l01.h
#ifndef __NRF24L01_H
#define __NRF24L01_H
extern Uchar nrfFlag;
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//*********************************************NRF24L01*************************************
extern Uchar nrfWorkState;
extern Uchar g_rf_status;
extern Uchar g_rf_rx_buf[0x30];
//#define RX_DR g_rf_status^6
//#define TX_DS g_rf_status^5
//#define MAX_RT g_rf_status^4
#define RX_DR (g_rf_status&0x40)
#define TX_DS (g_rf_status&0x20)
#define MAX_RT (g_rf_status&0x10)
//24L01发送接收数据宽度定义
#define TX_ADR_WIDTH 5 //5字节的地址宽度
#define RX_ADR_WIDTH 5 //5字节的地址宽度
#define TX_PLOAD_WIDTH 6 //32字节的用户数据宽度
#define RX_PLOAD_WIDTH 6 //32字节的用户数据宽度
//Uchar const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址
//Uchar const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址
//***************************************NRF24L01寄存器指令*******************************************************
#define READ_REG_NRF 0x00 //读配置寄存器,低5位为寄存器地址
#define WRITE_REG_NRF 0x20 //写配置寄存器,低5位为寄存器地址
#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 MAX_TX 0x10 //达到最大发送次数中断
#define TX_OK 0x20 //TX发送完成中断
#define RX_OK 0x40 //接收到数据中断
#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栈入栈出状态寄存器设置
//**************************************************************************************
//////////////////////////////////////////////////////////////////////////////////////////////////////////
extern void NRF_IRQ_Init(void);
extern void NRF24L01_Init(void);//初始化
extern void NRF24L01_RX_Mode(void);//配置为接收模式
extern void NRF24L01_TX_Mode(void);//配置为发送模式
extern Uchar NRF24L01_Write_Buf(Uchar reg, Uchar *pBuf, Uchar Uchars);//写数据区
extern Uchar NRF24L01_Read_Buf(Uchar reg, Uchar *pBuf, Uchar Uchars);//读数据区
extern Uchar NRF24L01_Read_Reg(Uchar reg); //读寄存器
extern Uchar NRF24L01_Write_Reg(Uchar reg, Uchar value);//写寄存器
extern Uchar NRF24L01_Check(void);//检查24L01是否存在
extern Uchar NRF24L01_TxPacket(Uchar *txbuf);//发送一个包的数据
extern Uchar NRF24L01_RxPacket(Uchar *rxbuf);//接收一个包的数据
extern void NRF24L01_CheckRecvData(void);
#endif
nrf24l01.c
Uchar nrfFlag;
Uchar nrfWorkState;
Uchar g_rf_status; // RF状态寄存器的值
Uchar g_rf_rx_buf[0x30];
Uchar TX_ADDRESS[TX_ADR_WIDTH]={0x01,0x02,0x03,0x04,0xA5}; // 定义RF接收应用地址
Uchar RX_ADDRESS[TX_ADR_WIDTH]= {0x01,0x02,0x03,0x04,0xA6}; // 定义RF发送工厂地址
Uchar RX_ADDRESS_APP[TX_ADR_WIDTH]= {0x01,0x02,0x03,0x04,0xA6}; // 定义RF接收工厂地址
//SPI写寄存器
//reg:指定寄存器地址
//value:写入的值
extern Uchar NRF24L01_Write_Reg(Uchar reg,Uchar value)
{
Uchar status;
SPISemGet();
//NRF24L01_CSN=0; //使能SPI传输
NRF24L01_CSN_Low();
status =SPI_FLASH_SendByte(reg);//发送寄存器号
SPI_FLASH_SendByte(value); //写入寄存器的值
//NRF24L01_CSN=1; //禁止SPI传输
NRF24L01_CSN_High();
SPISemPut();
return(status); //返回状态值
}
//读取SPI寄存器值
//reg:要读的寄存器
extern Uchar NRF24L01_Read_Reg(Uchar reg)
{
Uchar reg_val;
SPISemGet();
NRF24L01_CSN_Low(); //使能SPI传输
SPI_FLASH_SendByte(reg); //发送寄存器号
reg_val=SPI_FLASH_SendByte(0XFF);//读取寄存器内容
NRF24L01_CSN_High(); //禁止SPI传输
SPISemPut();
return(reg_val); //返回状态值
}
//在指定位置读出指定长度的数据
//reg:寄存器(位置)
//*pBuf:数据指针
//len:数据长度
//返回值,此次读到的状态寄存器值
extern Uchar NRF24L01_Read_Buf(Uchar reg,Uchar *pBuf,Uchar len)
{
Uchar status,Uchar_ctr;
NRF24L01_CSN_Low(); //使能SPI传输
status=SPI_FLASH_SendByte(reg);//发送寄存器值(位置),并读取状态值
for(Uchar_ctr=0;Uchar_ctr<len;Uchar_ctr++)pBuf[Uchar_ctr]=SPI_FLASH_SendByte(0XFF);//读出数据
//NRF24L01_CSN=1; //关闭SPI传输
NRF24L01_CSN_High();
return status; //返回读到的状态值
}
//在指定位置写指定长度的数据
//reg:寄存器(位置)
//*pBuf:数据指针
//len:数据长度
//返回值,此次读到的状态寄存器值
extern Uchar NRF24L01_Write_Buf(Uchar reg, Uchar *pBuf, Uchar len)
{
Uchar status,Uchar_ctr;
NRF24L01_CSN_Low(); //使能SPI传输
status = SPI_FLASH_SendByte(reg);//发送寄存器值(位置),并读取状态值
for(Uchar_ctr=0; Uchar_ctr<len; Uchar_ctr++)SPI_FLASH_SendByte(*pBuf++); //写入数据
NRF24L01_CSN_High(); //关闭SPI传输
return status; //返回读到的状态值
}
//检测24L01是否存在
//返回值:0,成功;1,失败
extern Uchar NRF24L01_Check(void)
{
Uchar buf[TX_ADR_WIDTH];
//NRF24L01_Write_Buf(WRITE_REG_NRF+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH);//写入5个字节的地址.
#ifdef NRF_MODE_SEND
NRF24L01_Read_Buf(TX_ADDR,buf,5); //读出写入的地址
#else
NRF24L01_Read_Buf(RX_ADDR_P0,buf,5); //读出写入的地址
#endif
// DEBUGBUFFER("NRF24L01_Check", buf, 5);
#ifdef NRF_MODE_SEND
if (Buffercmp(TX_ADDRESS, buf, RX_ADR_WIDTH) == PASSED)
#else
if (Buffercmp(RX_ADDRESS, buf, RX_ADR_WIDTH) == PASSED)
#endif
{
nrfWorkState = 1;
return 1;//检测24L01错误
}
nrfWorkState = 0;
return 0; //检测到24L01
}
//启动NRF24L01发送一次数据
//txbuf:待发送数据首地址
//返回值:发送完成状况
extern Uchar NRF24L01_TxPacket(Uchar *txbuf)
{
NRF24L01_Write_Reg(FLUSH_TX,0); // 清除TX的FIFO
NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//写数据到TX BUF 32个字节
return 0;//其他原因发送失败
}
//启动NRF24L01发送一次数据
//txbuf:待发送数据首地址
//返回值:0,接收完成;其他,错误代码
extern Uchar NRF24L01_RxPacket(Uchar *rxbuf)
{
Uchar state = 0;
state=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值
NRF24L01_Write_Reg(WRITE_REG_NRF+STATUS,state); //清除TX_DS或MAX_RT中断标志
if(state&RX_OK)//接收到数据
{
NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据
NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
return 0;
}
return 1;//没收到任何数据
}
//该函数初始化NRF24L01到RX模式
//设置RX地址,写RX数据宽度,选择RF频道,波特率和LNA HCURR
//当CE变高后,即进入RX模式,并可以接收数据了
extern void NRF24L01_RX_Mode(void)
{
NRF24L01_CE_Low();
NRF24L01_Write_Reg(WRITE_REG_NRF + CONFIG, 0x0f); // 上电, CRC为2 bytes,接收模式,允许RX_DR产生中断
NRF24L01_CE_High();
}
//该函数初始化NRF24L01到TX模式
//设置TX地址,写TX数据宽度,设置RX自动应答的地址,填充TX发送数据,选择RF频道,波特率和LNA HCURR
//PWR_UP,CRC使能
//当CE变高后,即进入RX模式,并可以接收数据了
//CE为高大于10us,则启动发送.
extern void NRF24L01_TX_Mode(void)
{
NRF24L01_CE_Low();
//设置接收包数据长度
NRF24L01_Write_Reg(WRITE_REG_NRF + RX_PW_P0, TX_PLOAD_WIDTH); // PIPE0 接收数据包长度
NRF24L01_Write_Reg(WRITE_REG_NRF+CONFIG,0x0e); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
NRF24L01_CE_High();
}
extern void NRF24L01_CheckRecvData(void)
{
Uchar buf[0x40];
if(NRF24L01_RxPacket(buf)==0)//一旦接收到信息,则显示出来.
{
DEBUGBUFFER("NRF24L01 RECV", buf, 32);
}
}
//初始化24L01的IO口
extern void NRF24L01_Init(void)
{
#ifdef NRF_MODE_SEND
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = PIN_NRF24L01_IRQ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //IRQ 输入
GPIO_Init(PORT_NRF24L01_IRQ, &GPIO_InitStructure);
#else
NRF_IRQ_Init();
#endif
//NRF24L01_CE=0; //使能24L01
// NRF24L01_CSN=1; //SPI片选取消
NRF24L01_CE_Low();
NRF24L01_CSN_High();
NRF24L01_Write_Buf(WRITE_REG_NRF + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 设置发射地址及长度
NRF24L01_Write_Buf(WRITE_REG_NRF + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 设置接收地址及长度
NRF24L01_Write_Buf(WRITE_REG_NRF + RX_ADDR_P1, RX_ADDRESS_APP, RX_ADR_WIDTH); // 设置接收地址及长度
//SPI_Write_Reg(WRITE_REG + EN_AA, 0x01); // 启动自动应答功能
NRF24L01_Write_Reg(WRITE_REG_NRF+ EN_AA, 0x00); // 关闭自动应答功能
//SPI_Write_Reg(WRITE_REG + EN_RXADDR, 0x01); // PIPE0接收数据
NRF24L01_Write_Reg(WRITE_REG_NRF + EN_RXADDR, 0x03); // PIPE0,PIPE1接收数据
//SPI_Write_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 自动重传10次
NRF24L01_Write_Reg(WRITE_REG_NRF + SETUP_RETR, 0x00); // 禁止重传
NRF24L01_Write_Reg(WRITE_REG_NRF + RF_CH, 40); // RF频率2440MHz
//SPI_Write_Reg(WRITE_REG + RF_SETUP, 0x0f); // 发射功率0dBm, 传输速率2Mbps,
NRF24L01_Write_Reg(WRITE_REG_NRF + RF_SETUP, 0x27); // 发射功率0dBm, 传输速率250kbps,
NRF24L01_Write_Reg(WRITE_REG_NRF + RX_PW_P0, TX_PLOAD_WIDTH); // PIPE0 接收数据包长度
NRF24L01_Write_Reg(WRITE_REG_NRF + RX_PW_P1, TX_PLOAD_WIDTH); // PIPE1 接收数据包长度
}
extern void NRF_IRQ_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* Connect EXTI Line to GPIO Pin */
GPIO_EXTILineConfig(PORT_SRC_NRF_IRQ, PIN_SRC_NRF_IRQ);
/* Configure EXTI line */
EXTI_InitStructure.EXTI_Line = EXTI_LINE_NRF_IRQ;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/* Enable and set EXTI Interrupt to the highest priority */
NVIC_InitStructure.NVIC_IRQChannel = EXIT_IRQN_NRF_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
EXTI_ClearITPendingBit(EXTI_LINE_NRF_IRQ);
// EXTI_GenerateSWInterrupt(EXTI_LINE_PFO); // test
}
extern void EXTI1_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_LINE_NRF_IRQ) != RESET)
{
EXTI_ClearITPendingBit(EXTI_LINE_NRF_IRQ);
if (!nrfFlag)
{
nrfFlag = 1;
}
g_rf_status=NRF24L01_Read_Reg(STATUS); // 读出状态值
if(RX_DR){
NRF24L01_Read_Buf(RD_RX_PLOAD,g_rf_rx_buf,RX_PLOAD_WIDTH); // 读出FIFO的数据
NRF24L01_Write_Reg(FLUSH_RX,0); // 清除RX的FIFO
}
NRF24L01_Write_Reg(WRITE_REG_NRF+STATUS,0x70); // 清除所有中断标志
}
}
1.做主机时初始化相关流程
NRF24L01_Init();
NRF24L01_TX_Mode();
发送数据
u8 recvData[TX_PLOAD_WIDTH]={数据};
NRF24L01_TxPacket(recvData);
2.做从机时初始化相关流程
NRF24L01_Init();
NRF24L01_RX_Mode();
每收到一次有效数据发生一次中断
g_rf_status=NRF24L01_Read_Reg(STATUS); // 读出状态值
if(RX_DR){
NRF24L01_Read_Buf(RD_RX_PLOAD,g_rf_rx_buf,RX_PLOAD_WIDTH); // 读出FIFO的数据
NRF24L01_Write_Reg(FLUSH_RX,0); // 清除RX的FIFO
//DEBUGBUFFER("NRF", g_rf_rx_buf, TX_PLOAD_WIDTH);
}
NRF24L01_Write_Reg(WRITE_REG_NRF+STATUS,0x70);