nrf24L01通信收发程序

技术设计 · 2017/11/11
← 返回技术文章

u8 Receive_data=0;u8 tmp_buf[32];const u8 TX_ADDRESS[TX_A...

u8 Receive_data=0;

u8 tmp_buf[32];

const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //发送地址

const u8 RX_ADDRESS[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //发送地址

//初始化24L01的IO口

void NRF24L01_Init(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);

//配置PA4即CE

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;

GPIO_Init(GPIOA,&GPIO_InitStructure);

//配置PC5即IRQ

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;

//GPIO_Init(GPIOC,&GPIO_InitStructure);

GPIO_Init(GPIOB,&GPIO_InitStructure); //改为B5

SPIx_Init(); //初始化SPI

NRF24L01_CE=0; //使能24L01,ce置低,进入待机模式I

NRF24L01_CSN=1; //SPI片选取消

}

void NRF24L01_EXTI_RX(void)

{

EXTI_InitTypeDef EXTI_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

//链接PC5到EXTI5

//改为链接PB5到EXTI5

GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource5);

//配置EXTI5

EXTI_InitStructure.EXTI_Line=EXTI_Line5;

EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;

EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;

EXTI_InitStructure.EXTI_LineCmd=ENABLE;

EXTI_Init(&EXTI_InitStructure);

//中断设置,优先级寄存器划分

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

//中断

NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;

NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;

NVIC_Init(&NVIC_InitStructure);

}

//检测24L01是否存在

//返回值:0,成功;1,失败

u8 NRF24L01_Check(void)

{

u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};

u8 i;

SPIx_SetSpeed(SPI_SPEED_8); //spi速度为9Mhz(24L01的最大SPI时钟为10Mhz)

NRF24L01_Write_Buf(write_reg+TX_ADDR,buf,5);//写入5个字节的地址.

NRF24L01_Read_Buf(TX_ADDR,buf,5); //读出写入的地址

for(i=0;i<5;i++)if(buf[i]!=0XA5)break;

if(i!=5)return 1;//检测24L01错误

return 0; //检测到24L01

}

//SPI写寄存器

//reg:指定寄存器地址

//value:写入的值

u8 NRF24L01_Write_Reg(u8 reg,u8 value)

{

u8 status;

NRF24L01_CSN=0; //使能SPI传输

status =SPIx_ReadWriteByte(reg);//发送寄存器号

SPIx_ReadWriteByte(value); //写入寄存器的值

NRF24L01_CSN=1; //禁止SPI传输

return(status); //返回状态值

}

//读取SPI寄存器值

//reg:要读的寄存器

u8 NRF24L01_Read_Reg(u8 reg)

{

u8 reg_val;

NRF24L01_CSN = 0; //使能SPI传输

SPIx_ReadWriteByte(reg); //发送寄存器号

reg_val=SPIx_ReadWriteByte(0XFF);//读取寄存器内容

NRF24L01_CSN = 1; //禁止SPI传输

return(reg_val); //返回状态值

}

//在指定位置读出指定长度的数据

//reg:寄存器(位置)

//*pBuf:数据指针

//len:数据长度

//返回值,此次读到的状态寄存器值

u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len)

{

u8 status,u8_ctr;

NRF24L01_CSN = 0; //使能SPI传输

status=SPIx_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值

for(u8_ctr=0;u8_ctr<len;u8_ctr++)pBuf[u8_ctr]=SPIx_ReadWriteByte(0XFF);//读出数据

NRF24L01_CSN=1; //关闭SPI传输

return status; //返回读到的状态值

}

//在指定位置写指定长度的数据

//reg:寄存器(位置)

//*pBuf:数据指针

//len:数据长度

//返回值,此次读到的状态寄存器值

u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len)

{

u8 status,u8_ctr;

NRF24L01_CSN = 0; //使能SPI传输

status = SPIx_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值

for(u8_ctr=0; u8_ctr<len; u8_ctr++)SPIx_ReadWriteByte(*pBuf++); //写入数据

NRF24L01_CSN = 1; //关闭SPI传输

return status; //返回读到的状态值

}

//启动NRF24L01发送一次数据

//txbuf:待发送数据首地址

//返回值:发送完成状况

u8 NRF24L01_TxPacket(u8 *txbuf)

{

u8 sta;

SPIx_SetSpeed(SPI_SPEED_8);//spi速度为9Mhz(24L01的最大SPI时钟为10Mhz)

NRF24L01_CE=0;

NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//写数据到TX BUF 32个字节

NRF24L01_CE=1;//启动发送

while(NRF24L01_IRQ!=0);//等待发送完成

sta=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值

NRF24L01_Write_Reg(write_reg+STATUS,sta); //清除TX_DS或MAX_RT中断标志

if(sta&MAX_TX)//达到最大重发次数

{

NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器

return MAX_TX;

}

if(sta&TX_OK)//发送完成

{

return TX_OK;

}

NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器

return 0xff;//其他原因发送失败

}

//启动NRF24L01发送一次数据

//txbuf:待发送数据首地址

//返回值:0,接收完成;其他,错误代码

u8 NRF24L01_RxPacket(u8 *rxbuf)

{

u8 sta;

SPIx_SetSpeed(SPI_SPEED_8); //spi速度为9Mhz(24L01的最大SPI时钟为10Mhz)

sta=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值

NRF24L01_Write_Reg(write_reg+STATUS,sta); //清除RX_DR或MAX_RT中断标志

if(sta&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模式,并可以接收数据了

void RX_Mode(void)

{

NRF24L01_CE=0;

NRF24L01_Write_Buf(write_reg+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址

NRF24L01_Write_Reg(write_reg+EN_AA,0x01); //使能通道0的自动应答

NRF24L01_Write_Reg(write_reg+EN_RXADDR,0x01);//使能通道0的接收地址

NRF24L01_Write_Reg(write_reg+RF_CH,40); //设置RF通信频率

NRF24L01_Write_Reg(write_reg+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度

NRF24L01_Write_Reg(write_reg+RF_SETUP,0x0f);//设置TX发射参数,0db增益,2Mbps,低噪声增益开启

NRF24L01_Write_Reg(write_reg+CONFIG, 0x0f);//配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式

NRF24L01_CE = 1; //CE为高,进入接收模式

}

//该函数初始化NRF24L01到TX模式

//设置TX地址,写TX数据宽度,设置RX自动应答的地址,填充TX发送数据,选择RF频道,波特率和LNA HCURR

//PWR_UP,CRC使能

//当CE变高后,即进入RX模式,并可以接收数据了

//CE为高大于10us,则启动发送.

void TX_Mode(void)

{

NRF24L01_CE=0;//拉低CE进入待机模式I,因为发送和接收模式的启动是通过拉高CE实现的

NRF24L01_Write_Buf(write_reg+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址

NRF24L01_Write_Buf(write_reg+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK

NRF24L01_Write_Reg(write_reg+EN_AA,0x01); //使能通道0的自动应答

NRF24L01_Write_Reg(write_reg+EN_RXADDR,0x01); //使能通道0的接收地址

NRF24L01_Write_Reg(write_reg+SETUP_RETR,0x2a);//设置自动重发间隔时间:750us + 86us;最大自动重发次数:10次

NRF24L01_Write_Reg(write_reg+RF_CH,40); //设置RF通道为40 ,fo=2400+RF-CH mhz

NRF24L01_Write_Reg(write_reg+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启

NRF24L01_Write_Reg(write_reg+CONFIG,0x0e); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,发送模式,开启所有中断

NRF24L01_CE=1;//CE为高,10us后启动发送

}