NRF24L01发送实验
相对比较顺利
接收实验倒腾了一晚上
发现连NRF24L01都检测不到
怀疑是管脚配置有问题
详情:http://forum.eepw.com.cn/thread/249476/1
欢迎各路大神来喷
NRF24L01的控制字不少
其实这个实验用到的并不多
/*******************************************************/
#define TX_ADDR_WITDH 5//发送地址宽度设置为5个字节
#define RX_ADDR_WITDH 5//接收地址宽度设置为5个字节
#define TX_DATA_WITDH 4//发送数据宽度1个字节
#define RX_DATA_WITDH 4//接收数据宽度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状态寄存器
SPI1的配置
比较常规,可以参考数据手册和函数说明
void SPI1_Config(void)
{ SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE); //使能SPI1时钟
/* 配置SPI1的复用GPIO */
// PA5--CLK PA7--MOSI 复用推挽输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//PA6--MISO 输入浮空
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*PB2--CE PA1--NSS (GPIOA1驱动CSN) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*PA3--IRQ */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStructure);
SPI1_CE_LOW();
SPI1_NRF_CSN_HIGH();//拉高CSN 失能片选
/* 配置SPI1模块 初始化*/
//声明用来初始化的结构体
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //一次传输8位
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //空闲电平低电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //第一个上升沿采样
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS管理为软件件模式
SPI_InitStructure.SPI_BaudRatePrescaler =SPI_BaudRatePrescaler_8; //波特率预分频8 9MHz
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据传输低位在前
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC校验方式
SPI_Init(SPI1, &SPI_InitStructure); //初始化
// SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Set);
SPI_Cmd(SPI1, ENABLE); //使能SPI1
}//SPI1_Config()
然后是NRF24L01的一系列子函数
这块片子其实比较傻瓜
通信过程全部硬件实现了
仅仅需要进行控制和读写
/*************************************************************
**函数名: SPI_RW_Byte(SPI_TypeDef* SPIx,unsigned char Byte);
**描述 : SPI写Byte
**参数 :
**返回值: u8 STATUS寄存器的内容
**注意 :
************************************************************/
u8 SPI_RW_Byte(SPI_TypeDef* SPIx,unsigned char Byte)
{
while( SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET); //查发送缓冲器是否为空,空即可以发送
SPI_I2S_SendData(SPIx, Byte); //库函数:发送一个字节
//当SPI接收缓冲器为空时等待
while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
return SPI_I2S_ReceiveData(SPIx);
}//SPI_RW_Byte()
/*************************************************************
**函数名: SPI_NRF_Write(char CMD,char* WBuff,char ByteNUM);
**描述 : SPI1写NRF
**参数 :
**返回值: u8 STATUS
**注意 :
************************************************************/
u8 SPI_NRF_Write(SPI_TypeDef* SPIx,char CMD,unsigned char* WBuff,unsigned char ByteNUM)
{
unsigned char i,status;
SPI1_CE_LOW();
SPI1_NRF_CSN_LOW();//使能片选
status=SPI_RW_Byte( SPIx , CMD);
for(i=0;i<ByteNUM;i++)
{
SPI_RW_Byte( SPIx,*WBuff++);
// printf("写入第%d个数据\r\n",ByteNUM);
}
SPI1_NRF_CSN_HIGH();//
return status;
}//SPI_NRF_Write()
/*************************************************************
**函数名: SPI_NRF_Read(SPI_TypeDef* SPIx,char CMD,char* RBuff,char ByteNUM);
**描述 : SPI1写NRF
**参数 :
**返回值: u8 status
**注意 :
************************************************************/
u8 SPI_NRF_Read(SPI_TypeDef* SPIx,char CMD,unsigned char* RBuff,unsigned char ByteNUM)
{
unsigned char i,status;
SPI1_CE_LOW();
SPI1_NRF_CSN_LOW();
status=SPI_RW_Byte( SPIx , CMD);
for(i=0;i< ByteNUM ;i++)
{
RBuff[i]=SPI_RW_Byte(SPIx,NOP); // 取接收缓冲器,一个字节
//printf("读出第%d个数据\r\n",ByteNUM);
}
SPI1_NRF_CSN_HIGH();
return status;
}//SPI_NRF_Read()
/*************************************************************
**函数名: SPI_NRF_MOD_TX()
**描述 : 配置NRF进入 发送模式
**参数 :
**返回值:
**注意 : 仅用于测试 无参无返 可改成带配置参数的模块函数
Tx通道0 地址TX_ADDR=0x05B6B5B4B3
************************************************************/
void SPI_NRF_MOD_TX(void)
{
u8 TX_Array[5];
u8 _TX_RX_ADDR_[5]={0xB3,0xB4,0xB5,0xB6,0x05};
SPI1_CE_LOW();//CE=0 待机模式
TX_Array[0]=0x03;//设置地址宽度 11--5字节 10--4字节 01-3字节 00--不合法
SPI_NRF_Write(SPI1,W_REGISTER+SETUP_AW,TX_Array,1);
TX_Array[0]=0xf3;//建立自动重发 间隔‘1111‘--等待4000+86us 15次
SPI_NRF_Write(SPI1,W_REGISTER+SETUP_RETR,TX_Array,1);
TX_Array[0]=0x02;//射频通道 X000 0010
SPI_NRF_Write(SPI1,W_REGISTER+RF_CH,TX_Array,1);
TX_Array[0]=0x0f;//射频参数寄存器 0000 1111 2Mbps 发射功率 00-18dBm 01-12dBm 10-6dBm 11-0dBm 1--低噪声放大器增益
SPI_NRF_Write(SPI1,W_REGISTER+RF_SETUP,TX_Array,1);
TX_Array[0]=0x3f;//xx11 1111 0-5接收通道允许
SPI_NRF_Write(SPI1,W_REGISTER+EN_RXADDR,TX_Array,1);
TX_Array[0]=0x3f;//xx11 1111 0-5通道允许自动应答
SPI_NRF_Write(SPI1,W_REGISTER+EN_AA,TX_Array,1);
SPI_NRF_Write(SPI1,W_REGISTER+TX_ADDR,_TX_RX_ADDR_,5);//写入接收发送数据的地址,这个地址是接收端收件的凭证
SPI_NRF_Write(SPI1,W_REGISTER+RX_ADDR_P0,_TX_RX_ADDR_,5);//写入接收发送数据的地址,这个地址是接收端收件的凭证
TX_Array[0]=0x0e;//中断全开 发送模式 PRIM_RX=0 PWR_UP=1
SPI_NRF_Write(SPI1,W_REGISTER+CONFIG,TX_Array,1);
TX_Array[0]=0xfe;//1111 xxxx STATUS寄存器 写‘1’清除所有标志
SPI_NRF_Write(SPI1,W_REGISTER+STATUS,TX_Array,1);
SPI1_CE_HIGH();//CE=1 使能发射模式
delay_us(100);//CE拉高需要一定的延时才能进行发送 延时之后 即可通过SPI接口发送TX_PLD
}
/*************************************************************
**函数名: SPI_NRF_MOD_RX()
**描述 : 配置NRF进入 接收模式
**参数 :
**返回值:
**注意 : 仅用于测试 无参无返 可改成带配置参数的模块函数
RX通道0 地址TX_ADDR=0xB3B4B5B605
************************************************************/
void SPI_NRF_MOD_RX(void)
{
u8 TX_Array[5];
u8 _TX_RX_ADDR_[5]={0xB3,0xB4,0xB5,0xB6,0x05};
SPI1_CE_LOW();//CE=0 待机模式
TX_Array[0]=0x03;//允许接收通道0000 0011
SPI_NRF_Write(SPI1,W_REGISTER+EN_RXADDR,TX_Array,1);
TX_Array[0]=0x03;//设置地址宽度 11--5字节 10--4字节 01-3字节 00--不合法
SPI_NRF_Write(SPI1,W_REGISTER+SETUP_AW,TX_Array,1);
TX_Array[0]=0x20;//射频通道 X000 0010
SPI_NRF_Write(SPI1,W_REGISTER+RF_CH,TX_Array,1);
TX_Array[0]=0x0f;//射频参数寄存器 0000 1111 2Mbps 发射功率 00-18dBm 01-12dBm 10-6dBm 11-0dBm 1--低噪声放大器增益
SPI_NRF_Write(SPI1,W_REGISTER+RF_SETUP,TX_Array,1);
TX_Array[0]=0x3f;//xx11 1111 0-5通道允许自动应答
SPI_NRF_Write(SPI1,W_REGISTER+EN_AA,TX_Array,1);
TX_Array[0]=0x04;//xx11 1111 数据通道0 有效数据宽度 (1-32)字节
SPI_NRF_Write(SPI1,W_REGISTER+RX_PW_P0,TX_Array,1);
TX_Array[0]=0xfe;//1111 xxxx STATUS寄存器 写‘1’清除所有标志
SPI_NRF_Write(SPI1,W_REGISTER+STATUS,TX_Array,1);
SPI_NRF_Write(SPI1,W_REGISTER+TX_ADDR,_TX_RX_ADDR_,5);//写入接收发送数据的地址,这个地址是接收端收件的凭证
SPI_NRF_Write(SPI1,W_REGISTER+RX_ADDR_P0,_TX_RX_ADDR_,5);//写入接收发送数据的地址,这个地址是接收端收件的凭证
TX_Array[0]=0x0f;//接收模式 PRIM_RX=1 PWR_UP=1 允许接收终端
SPI_NRF_Write(SPI1,W_REGISTER+CONFIG,TX_Array,1);
SPI1_CE_HIGH();//CE=1 使能发射模式
delay_us(100);//CE拉高需要一定的延时才能进行发送 延时之后 即可通过SPI接口发送TX_PLD
//轮询中断24L01中断的到来 NRF_Read_IRQ()
}
/*************************************************************
**函数名: SPI_NRF_TX_DATAS()
**描述 : 配置NRF发送 数据
**参数 : TBuff[ByteNUM] ByteNUM
**返回值: ErrorStatus
**注意 :
************************************************************/
ErrorStatus SPI_NRF_TX_DATAS(u8* TBuff,u8 ByteNUM)
{
u8 Status[1];
do{
SPI1_CE_LOW();//拉低待机
SPI_NRF_Write(SPI1,W_TX_PAYLOAD,TBuff,ByteNUM);//发送TBuff数组
SPI1_CE_HIGH();//拉低待机
}
while(NRF_Read_IRQ()!=0);//中断产生时,IRQ引脚低电平
SPI_NRF_Write(SPI1, FLUSH_TX,TBuff,0);
SPI1_CE_LOW();//拉低待机
delay_us(100);
SPI_NRF_Read(SPI1,R_REGISTER+STATUS,Status,1);//读取Status
if(Status[0]&0x10)
{
Status[0]&=0x10;
SPI_NRF_Write(SPI1,W_REGISTER+STATUS,Status,1);//
printf("Tx Error!\r\n");//重发超时 发送失败
return ERROR;
}
else
{
Status[0]&=0x20;
SPI_NRF_Write(SPI1,W_REGISTER+STATUS,Status,1);//
printf("Tx Success\r\n");//发送成功
return SUCCESS;
}
}
/*************************************************************
**函数名: SPI_NRF_RX_DATAS()
**描述 : 配置NRF发送 数据
**参数 : RBuff[ByteNUM] ByteNUM
**返回值: ErrorStatus
**注意 :
************************************************************/
ErrorStatus SPI_NRF_RX_DATAS(u8* RBuff)
{
ErrorStatus RX_Status=SUCCESS;
u8 Status[1];
while(NRF_Read_IRQ()!=0);//中断产生时,IRQ引脚低电平
SPI1_CE_LOW();//拉低待机,才能操作寄存器
delay_us(100);
SPI_NRF_Read(SPI1,R_REGISTER+STATUS,Status,1);//读取Status
switch(Status[0]&0x0e)
{
case 0x0e: RX_Status=ERROR; break; //RX_FIFO 空
default : printf("Rx Success!\r\n");//RX_FIFO非空
break;
/*
case 0x00: break; //通道0
case 0x02: break; //通道1
case 0x04: break; //通道2
case 0x06: break; //通道3
case 0x08: break; //通道4
case 0x0A: break; //通道5*/
}
SPI_NRF_Read(SPI1,R_RX_PAYLOAD,RBuff,4);//读RX_FIFO
SPI_NRF_Write(SPI1,W_REGISTER+STATUS,Status,1);//处理状态寄存器标志
return RX_Status;
}
/*************************************************************
**函数名: NRF_Check
**描述 : 检测器件
**参数 :
**返回值: 0:正常,1:有误
**注意 :
************************************************************/
u8 NRF_Check(void)
{
u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
u8 i;
SPI_NRF_Write(SPI1,W_REGISTER+TX_ADDR,buf,5);
SPI_NRF_Read(SPI1,TX_ADDR,buf,5);
for(i=0;i<5;i++)
if(buf[i]!=0XA5)
break;
if(i!=5)
return 1;//检测有误
return 0; //检测无误
}
还是把USART1初始化了一下
方便调试
/*************************************************************
**函数名: usart_Configuration()
**描述 : 配置USART1
**参数 :
**返回值:
**注意 :
************************************************************/
void usart_Configuration()
{
USART_InitTypeDef USART_InitStructure;
USART_ClockInitTypeDef USART_ClockInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* PA10 USART1_Rx */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* USARTx configured as follow:
- BaudRate = 115200 baud
- Word Length = 8 Bits
- One Stop Bit
- No parity
- Hardware flow control disabled (RTS and CTS signals)
- Receive and transmit enabled
*/
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
USART_ClockInit(USART1, &USART_ClockInitStructure);
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_Cmd(USART1, ENABLE);
/* Configure four bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
/* Enable the USART1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 15;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
看看主函数的内容
其实就是USAT1、SPI1初始化
检测NRF24L01的在线情况
然后进入一个数据发送的无条件循环
usart_Configuration();
printf("USART1测试成功!!!!!\r\n");
SPI1_Config();
printf("SPI初始化成功!!!!!!\r\n");
while(NRF_Check());
printf("NRF2401正常在线!!!!\r\n");
SPI_NRF_MOD_TX();
printf("NRF2401发送模式!!!!\r\n");
while(1)
{
Errcode = SPI_NRF_TX_DATAS(Tx_buf,5);
SPI_RW_Byte(SPI1,FLUSH_TX);//清空FIFO
LED_On;
if(Errcode == 1)
{printf("Yeah,All Data TXed\r\n");}
else
{printf("Shit,All Data can not TX\r\n");}
LED_Off;
delay_ms(2500);
}
看看视频:
视频地址:http://player.youku.com/player.php/sid/XNjkzNzMxMDIw/v.swf