📄 nrf24l01.c
字号:
#define NRF_GLOBALS
#include "..\App\includes.h"
#include "NRF24L01.h"
#include "demo.h"
/***************************************************/
//#define uchar unsigned char
//#define TX_ADR_WIDTH 5 // 5 bytes TX(RX) address width
//#define TX_PLOAD_WIDTH 20 // 20 bytes TX payload
//uchar TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01}; // Define a static TX address
//uchar rx_buf[TX_PLOAD_WIDTH];
//uchar tx_buf[TX_PLOAD_WIDTH]={"1234567890abcdefghij"};
//uchar flag;
//uchar rx_com_buffer[10];
//uchar tx_com_buffer[10];
GPIO_InitTypeDef GPIO_InitStructure;
/**************************************************/
void SPI_CS(uchar a){
if(a==1) GPIO_SetBits(GPIOB, GPIO_Pin_12); /*开*/
else GPIO_ResetBits(GPIOB, GPIO_Pin_12); /*关*/
}
void SPI_DOUT(uchar a){
if(a==1) GPIO_SetBits(GPIOB, GPIO_Pin_15); /*开*/
else GPIO_ResetBits(GPIOB, GPIO_Pin_15); /*关*/
}
void SPI_CLK(uchar a){
if(a==1) GPIO_SetBits(GPIOB, GPIO_Pin_13); /*开*/
else GPIO_ResetBits(GPIOB, GPIO_Pin_13); /*关*/
}
void MODE_CE(uchar a){ /*NRF24L01 模式控制引脚CE*/
if(a==1) GPIO_SetBits(GPIOC, GPIO_Pin_6); /*开*/
else GPIO_ResetBits(GPIOC, GPIO_Pin_6); /*关*/
}
void SPI2_NRF24L01_Init(void)
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* 使能SPI2,GPIOB时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2 ,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/* 配置SPI2接口: SCK=PB13,MISO=PB14,MOSI=PB15 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;/*复用推挽输出*/
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* 配置PB12推挽输出模式, 有于片选 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;/*推挽输出*/
GPIO_Init(GPIOB, &GPIO_InitStructure);
/*配置NRF24L01模式引脚CE=PC6 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;/*推挽输出*/
GPIO_Init(GPIOC, &GPIO_InitStructure);
/*配置NRF24L01 中断控制引脚IRQ=PB8 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;/*输入下拉*/
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_8); /*开*/
NotSelect_SDR();
/* SPI2接口参数配置 */
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI2, &SPI_InitStructure);
/* 使能SPI2接口 */
SPI_Cmd(SPI2, ENABLE);
}
uchar SPI2_NRF_SendByte(u8 byte)
{
/* 当DR寄存器不为空时循环 */
while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
//NotSelect_Flash(); while(1);
/* 通过SPI2外设发送数据 */
SPI_I2S_SendData(SPI2, byte);
/* 等待接收数据 */
while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
/* 返回从SPI总线读取的数据 */
return SPI_I2S_ReceiveData(SPI2);
}
uchar SPI_RW_Reg(unsigned char data1,unsigned char data2)
{
unsigned int Data = 0,a;
Select_SDR();
Data=SPI2_NRF_SendByte(data1);
SPI2_NRF_SendByte(data2);
NotSelect_SDR();
return(Data);
}
uchar SPI_Write_Buf(BYTE reg, BYTE *pBuf, BYTE bytes)
{
uchar status,byte_ctr;
Select_SDR(); /* CSN置低, 初始化SPI传输*/
status=SPI2_NRF_SendByte(reg);
for(byte_ctr=0; byte_ctr<bytes; byte_ctr++) /* 将所有字节写入缓冲*/
{
/*发送字节*/
SPI2_NRF_SendByte(*pBuf++);
//SPI_I2S_SendData(SPI2,*pBuf++);
}
NotSelect_SDR(); /*CSN置高 */
return(status); /* 返回nRF24L01 状态*/
}
/*SPI读*/
unsigned char SPI_Read(BYTE reg)
{
unsigned char Data;
Select_SDR();
SPI2_NRF_SendByte(reg);
Data=SPI2_NRF_SendByte(0);
NotSelect_SDR();
return (Data);
}
u8 SPI_Read_Buf(BYTE reg, BYTE *pBuf, BYTE bytes)
{
uchar status,i;
Select_SDR(); /*CSN置低*/
status=SPI2_NRF_SendByte(reg);
for(i=0; i<bytes; i++) /* 数据写入缓存 */
{
/* 发送字节*/
pBuf[i]=SPI2_NRF_SendByte(0);
//SPI_I2S_SendData(SPI2,*pBuf++);
}
NotSelect_SDR(); /*CSN置高*/
return(status); /*返回NRF24L01状态*/
}
void SPI_SDR_SendByte1(unsigned int spi_add,unsigned int spi_data)
{
unsigned char bitcnt,a;
SPI_CS(0);
for(bitcnt=0;bitcnt<16;bitcnt++)
{
if(((spi_add<<bitcnt)&0x8000)>0) SPI_DOUT(1);
else SPI_DOUT(0);
SPI_CLK(0);
SPI_CLK(1);
}
for(bitcnt=0;bitcnt<16;bitcnt++)
{
if(((spi_data<<bitcnt)&0x8000)>0) SPI_DOUT(1);
else SPI_DOUT(0);
SPI_CLK(0);
SPI_CLK(1);
}
SPI_CLK(0);
SPI_CS(1);
}
unsigned int SPI_SDR_ReadByte1(unsigned int spi_add)
{
unsigned int i=0;
unsigned int temp8=0;
SPI_CS(0);
for(i=0;i<16;i++)
{
if(((spi_add<<i)&0x8000)>1)
SPI_DOUT(1);
else
SPI_DOUT(0);
SPI_CLK(0);
SPI_CLK(1);
}
//pPio1->PIO_CODR = SPI_CLK;
for(i=0;i<16;i++)
{
SPI_CLK(1);
SPI_CLK(0);
temp8=temp8<<1;
//if( (pPio1->PIO_PDSR & SPI_IN ) == SPI_IN ) temp8=temp8+1;
}
SPI_CLK(1);
SPI_CLK(0);
//P_CPLD1->spi_fs=0x01;
SPI_CS(1);
return(temp8);
}
/**************************************************
Function: init_io();
Description:
flash led one time,chip enable(ready to TX or RX Mode),
Spi disable,Spi clock line init high
/**************************************************/
void init_io(void)
{
SPI_CS(1); /*片选置1*/
MODE_CE(0); /*CE置0*/
//SPI_CLK(0); // Spi clock line init high
}
/**************************************************/
/*延时函数*/
void delay_ms(unsigned int x)
{
unsigned int i,j;
i=0;
for(i=0;i<x;i++)
{
j=108;
while(j--);
}
}
/**************************************************/
/**************************************************
Function: SPI_RW();
Description:
Writes one byte to nRF24L01, and return the byte read
from nRF24L01 during write, according to SPI protocol
/**************************************************/
/*uchar SPI_RW(uchar byte)
{
uchar bit_ctr;
for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit
{
MOSI = (byte & 0x80); // output 'byte', MSB to MOSI
byte = (byte << 1); // shift next bit into MSB..
SCK = 1; // Set SCK high..
byte |= MISO; // capture current MISO bit
SCK = 0; // ..then set SCK low again
}
return(byte); // return read byte
} */
/**************************************************/
/**************************************************
Function: SPI_RW_Reg();
Description:
Writes value 'value' to register 'reg'
/**************************************************/
/**************************************************/
/**************************************************/
/**************************************************
Function: SPI_Read_Buf();
Description:
Reads 'bytes' #of bytes from register 'reg'
Typically used to read RX payload, Rx/Tx address
/**************************************************/
/*uchar SPI_Read_Buf(BYTE reg, BYTE *pBuf, BYTE bytes)
{
uchar status,byte_ctr;
CSN = 0; // Set CSN low, init SPI tranaction
status = SPI_RW(reg); // Select register to write to and read status byte
for(byte_ctr=0;byte_ctr<bytes;byte_ctr++)
pBuf[byte_ctr] = SPI_RW(0); // Perform SPI_RW to read byte from nRF24L01
CSN = 1; // Set CSN high again
return(status); // return nRF24L01 status byte
} */
/**************************************************/
/**********************************************************************
*函数名: RX_Mode()
*功能描述:初始化NRF24L01到接收模式,设置接收地址,写有效接收数据宽度
*选择射频通道,速率及低噪声放大器增益,初始化,后CE置高,NRF24L01
*接收数据包准备就绪.
**********************************************************************/
void RX_Mode(void)
{ it_msg=0;
init_io();
/*TX地址*/
TX_ADDRESS[0]=0x34;
TX_ADDRESS[1]=0x43;
TX_ADDRESS[2]=0x10;
TX_ADDRESS[3]=0x10;
TX_ADDRESS[4]=0x01;
MODE_CE(0);
/*收发使用相同的地址*/
SPI_Write_Buf(WRITE_REG1 + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);
/*使能自动应答通道0*/
SPI_RW_Reg(WRITE_REG1 + EN_AA, 0x01);
SPI_RW_Reg(WRITE_REG1 + EN_RXADDR, 0x01);
/*选择射频通道40*/
SPI_RW_Reg(WRITE_REG1 + RF_CH, 40);
/*接收/发送有效负载数据长度相等*/
SPI_RW_Reg(WRITE_REG1 + RX_PW_P0, TX_PLOAD_WIDTH);
/*发射功率:0dBm, 数据速率:2Mbps, 低噪声放大增益:HCURR */
if(nrf_baud==0) SPI_RW_Reg(WRITE_REG1 + RF_SETUP, 0x0f);
else SPI_RW_Reg(WRITE_REG1 + RF_SETUP, 0x07);
/*设置PWR_UP位, 使能CRC(2 bytes)校验,PRIM_RX位,RX_DR位*/
SPI_RW_Reg(WRITE_REG1 + CONFIG, 0x0f);
MODE_CE(1);/*CE置1,使能接收模式*/
// This device is now ready to receive one packet of 16 bytes payload from a TX device sending to address
// '3443101001', with auto acknowledgment, retransmit count of 10, RF channel 40 and datarate = 2Mbps.
}
/**********************************************************************
*函数名: TX_Mode()
*功能描述:初始化NRF24L01到发送模式,设置发送地址,设置接收自动应答功能
*选择射频通道,速率及发射功率,使能PWR_UP,PRIM_TX,CRC校验=2字节初始化,
*CE置高并维持10us,NRF24L01准备发送数据包并接收应答信号.
**********************************************************************/
void TX_Mode(void)
{
/*模式引脚CE=0*/
MODE_CE(0);
/*写发送地址TX_ADDR到nRF24L01*/
SPI_Write_Buf(WRITE_REG1 + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);
/*使能自动应答功能时发送/接收地址须相等*/
SPI_Write_Buf(WRITE_REG1 + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);
//SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // Writes data to TX payload
/*使能通道0自动应答*/
SPI_RW_Reg(WRITE_REG1 + EN_AA, 0x01);
/*使能通道0*/
SPI_RW_Reg(WRITE_REG1 + EN_RXADDR, 0x01);
/*500us + 86us, 10次重发*/
SPI_RW_Reg(WRITE_REG1 + SETUP_RETR, 0x1a);
/*选择射频通道40*/
SPI_RW_Reg(WRITE_REG1 + RF_CH, 40);
/*设置发射功率:0dBm, 数据速率:2Mbps, 低噪声放大增益:HCURR*/
if(nrf_baud==0) SPI_RW_Reg(WRITE_REG1 + RF_SETUP, 0x0f);
else SPI_RW_Reg(WRITE_REG1 + RF_SETUP, 0x07);
/* 设置PWR_UP位,使能CRC校验=2字节,PRIM_TX,MAX_RT,TX_DS寄存器位使能*/
SPI_RW_Reg(WRITE_REG1 + CONFIG, 0x0e);
//SPI_RW_Reg(WRITE_REG1+ CONFIG, 0x02);//0x0E);
MODE_CE(1);
}
void NRF24L01_TX(unsigned char * tx_buf)
{
MODE_CE(0);
/*自动应答时收发地址相等*/
SPI_Write_Buf(WRITE_REG1 + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);
/*写数据到TX_PLD*/
SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH);
MODE_CE(1);
}
/**********************************************************************
*函数名: NRF24L01_TXBUF()
*功能描述:发送数据缓冲内容="1234567890abcdefghij ,
*配置发送地址,I/O配置等
**********************************************************************/
void NRF24L01_TXBUF(void)
{
uchar a,i=0;
TX_ADDRESS[0]=0x34;
TX_ADDRESS[1]=0x43;
TX_ADDRESS[2]=0x10;
TX_ADDRESS[3]=0x10;
TX_ADDRESS[4]=0x01;
//TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};
init_io();
//LED1=1;
it_msg=0;
SPI_RW_Reg(WRITE_REG1+STATUS,0xff);
SPI_RW_Reg(0xe1,0);
SPI_RW_Reg(0xe2,0);
TX_Mode(); /* 发送模式* /
delay_ms(100);
NRF24L01_TX(tx_buf);
while(i==0)
{
if(it_msg!=0){
it_msg=0;
a=SPI_Read(READ_REG1+STATUS);
/*发送达到最大重发次数*/
if((a&0x10)>0){
/*清除发送缓冲区*/
SPI_RW_Reg(0xe1,0);
/*清除07寄存器中断标志*/
SPI_RW_Reg(WRITE_REG1+STATUS,0xff);
//if(led_flash==1) GPIO_SetBits(GPIOB, GPIO_Pin_5);
//else Led_OFF();
memcpy(status_buf, "Object NO ACK! ", 20);
i=1;
}
else if((a&0x20)>0){/*发射后收到应答*/
/*清除发送缓冲区*/
SPI_RW_Reg(0xe1,0);
/*清除07寄存器中断标志*/
SPI_RW_Reg(WRITE_REG1+STATUS,0xff);
//if(led_flash==1) GPIO_SetBits(GPIOB, GPIO_Pin_5);
//else Led_OFF();
memcpy(status_buf, "Send OK! ", 20);
i=1;
}
}
u8 NRF24L01_RxPacket()
{u8 flag=0;
u8 status;
if(it_msg!=0){
it_msg=0;
/*读取状态寄存其来判断数据接收状况*/
status=SPI_Read(READ_REG1+STATUS);
if(status & 0x40) /*判断是否接收到数据*/
{
/*从接收缓冲区读有效数据*/
SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);
flag =1; /*读取数据完成标志*/
//if(led_flash==1){ Led_ON(); }
//else if(led_flash==0){ Led_OFF();}
memcpy(status_buf, "Recive OK! ", 20);
/*接收到数据后RX_DR,TX_DS,MAX_RT都置高为1,通过写1来清楚中断标志*/
SPI_RW_Reg(WRITE_REG1+STATUS, status);
}
}
return flag;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -