硬件平臺: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);