新手上路
- 积分
- 36
- 金钱
- 36
- 注册时间
- 2016-10-4
- 在线时间
- 4 小时
|
我的代码是两个STM32F103C8T6最小系统使用硬件SPI1利用NRF24L01进行单向通信,采用外部中断检测IRQ。发送端和接收端自检都顺利通过,发送端的STATUS不断的返回0x1E(即最大重发),接收端的STATUS不断返回0x0E。发送端平均每发送1000-2000次接收端才有可能接收到一次。而且,一旦接收到,两边给出的相应标志位都十分正常。我想知道我那里出现错误了呢?
发送端函数
主函数和中断
[mw_shl_code=applescript,true]#include "stm32f10x.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "nrf24L01.h"
#include "EXTI.h"
#include "Led.h"
u8 Data[]={'A','B','C','D'};
int DataNum=0;
int main(void)
{
delay_init();
uart_init(115200);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
SPIInitMaster(); //主机初始化函数
EXTIInit();
LedInit();
printf("Init down.\r\n");
while(!nrf24L01Check()); //自检
SendConfig(); //发送配置函数
while(1)
{
CE=0;
WriteCom(W_TX_PAYLOAD,Data[DataNum]);
CE=1;
delay_ms(10);
}
}
void EXTI2_IRQHandler()
{
u8 Status;
Status=ReadCom(STATUS,NOP);
// printf("Config Status:%x\r\n",Status);
if(Status&0x10) //达到最大重发次数
{
// printf("Send Failed.\r\n");
Led=~Led;
}
if(Status&0x20) //发送完成并返回ACK
{
printf("Send Success.\r\n");
if(DataNum<12)
{DataNum++;}
else
{DataNum=0;}
}
if(Status&0x40) //接收到数据
{
printf("Receive Message.\r\n");
}
WriteCom(FLUSH_TX,NOP); //清除TX_FIFO
WriteCom(FLUSH_RX,NOP); //清除RX_FIFO
WriteCom(STATUS,Status); //清除所有标志
EXTI_ClearITPendingBit(EXTI_Line2);
GPIO_SetBits(GPIOA,GPIO_Pin_2);
}
[/mw_shl_code]
NRF24L01部分C文件
[mw_shl_code=applescript,true]#include "nrf24L01.h"
#include "delay.h"
#include "usart.h"
//地址编码
u8 AddrCode[]={0xA1,0xA2,0xA3,0xA4,0xA5};
//结构体定义
GPIO_InitTypeDef GPIOSPIConfig;
SPI_InitTypeDef SPIConfig;
/*==========初始化层==========*/
void SPIInitMaster() //主机初始化函数
{
/*主机模式*/
/*PA4_SPI1_NSS PA5_SPI1_SCK PA6_SPI1_MISO PA7_SPI1_MOSI PA3_CE*/
//时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|
RCC_APB2Periph_AFIO|
RCC_APB2Periph_SPI1,ENABLE);
//GPIO
GPIOSPIConfig.GPIO_Mode=GPIO_Mode_IPD;
GPIOSPIConfig.GPIO_Pin=GPIO_Pin_6; //PA6主机接收 MISO
GPIOSPIConfig.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIOSPIConfig);
GPIOSPIConfig.GPIO_Mode=GPIO_Mode_Out_PP;
GPIOSPIConfig.GPIO_Pin=GPIO_Pin_3| //PA3模式选择 CE
GPIO_Pin_4; //PA4片选 CSN
GPIO_Init(GPIOA,&GPIOSPIConfig);
GPIOSPIConfig.GPIO_Mode=GPIO_Mode_AF_PP;
GPIOSPIConfig.GPIO_Pin=GPIO_Pin_7| //PA7主机发送 MOSI
GPIO_Pin_5; //PA5时钟线 SCK
GPIO_Init(GPIOA,&GPIOSPIConfig);
//SPI
SPI_I2S_DeInit(SPI1); //SPI复位
SPIConfig.SPI_Direction=SPI_Direction_2Lines_FullDuplex; //全双工
SPIConfig.SPI_Mode=SPI_Mode_Master; //主机
SPIConfig.SPI_DataSize=SPI_DataSize_8b; //8位字长
SPIConfig.SPI_CPOL=SPI_CPOL_Low; //低电平空闲
SPIConfig.SPI_CPHA=SPI_CPHA_1Edge; //第一个边沿开始采集
SPIConfig.SPI_NSS=SPI_NSS_Soft; //软件片选
SPIConfig.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_8; //8分频
SPIConfig.SPI_FirstBit=SPI_FirstBit_MSB; //高位在前(单数据发送)
SPIConfig.SPI_CRCPolynomial=7; //校验值多项式
SPI_Init(SPI1,&SPIConfig);
//SPI使能
SPI_Cmd(SPI1,ENABLE);
CSN=1;
}
void SPIInitSlave() //从机初始化函数
{
/*从机模式*/
/*PA4_SPI1_NSS PA5_SPI1_SCK PA6_SPI1_MISO PA7_SPI1_MOSI PA3_CE*/
//时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|
RCC_APB2Periph_AFIO|
RCC_APB2Periph_SPI1,ENABLE);
//GPIO
GPIOSPIConfig.GPIO_Mode=GPIO_Mode_AF_PP;
GPIOSPIConfig.GPIO_Pin=GPIO_Pin_6| //PA7从机发送 MISO
GPIO_Pin_5; //PA5时钟线 SCK
GPIOSPIConfig.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIOSPIConfig);
GPIOSPIConfig.GPIO_Mode=GPIO_Mode_Out_PP;
GPIOSPIConfig.GPIO_Pin=GPIO_Pin_3| //PA3模式选择 CE
GPIO_Pin_4; //PA4片选 CSN
GPIO_Init(GPIOA,&GPIOSPIConfig);
GPIOSPIConfig.GPIO_Mode=GPIO_Mode_AF_OD;
GPIOSPIConfig.GPIO_Pin=GPIO_Pin_7; //PA6从机接收 MOSI
GPIO_Init(GPIOA,&GPIOSPIConfig);
//SPI
SPI_I2S_DeInit(SPI1); //SPI复位
SPIConfig.SPI_Direction=SPI_Direction_2Lines_FullDuplex; //全双工
SPIConfig.SPI_Mode=SPI_Mode_Slave; //从机
SPIConfig.SPI_DataSize=SPI_DataSize_8b; //8位字长
SPIConfig.SPI_CPOL=SPI_CPOL_Low; //低电平空闲
SPIConfig.SPI_CPHA=SPI_CPHA_1Edge; //第一个边沿开始采集
SPIConfig.SPI_NSS=SPI_NSS_Soft; //软件片选
SPIConfig.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_8; //8分频
SPIConfig.SPI_FirstBit=SPI_FirstBit_MSB; //高位在前(单数据发送)
SPIConfig.SPI_CRCPolynomial=7; //校验值多项式
SPI_Init(SPI1,&SPIConfig);
//SPI使能
SPI_Cmd(SPI1,ENABLE);
CSN=1;
}
void SendConfig() //点对点发送配置函数
{
// u8 Status[8];
// int Num;
CE=0; //进入待机模式,开始接收指令
// Status[0]=WriteCom(TX_ADDR,AddrCode[0]); //写入TX地址
// Status[1]=WriteCom(RX_ADDR_P0,5); //选择通道,默认5字节宽度
// Status[2]=WriteCom(EN_AA,0x01); //使能自动应答
// Status[3]=WriteCom(EN_RXADDR,AddrCode[0]); //写入RX地址
// Status[4]=WriteCom(SETUP_RETR,0xff); //最大延时,最多重发
// Status[5]=WriteCom(RF_CH,40); //选择通信频率
// Status[6]=WriteCom(RF_SETUP,0x0f); //射频配置,0db增益,2Mbps,低噪声增益开启
// Status[7]=WriteCom(CONFIG,0x0e); //发送模式
WriteData(TX_ADDR,AddrCode,5); //写入TX地址
WriteData(RX_ADDR_P0,AddrCode,5); //写入RX地址
WriteCom(EN_AA,0x01); //写入RX地址自动应答
WriteCom(EN_RXADDR,0x01); //使能数据通道0
WriteCom(SETUP_RETR,0x0f); //最小延时,最多重发
WriteCom(RF_CH,Channel1); //选择通信频率
WriteCom(RF_SETUP,0x0f); //射频配置,0db增益,2Mbps,低噪声增益开启
WriteCom(CONFIG,0x0e); //发送模式
CE=1;
// for(Num=0;Num<8;Num++)
// {
// printf("Status[%d]=%d\r\n",Num,(int)Status[Num]);
// }
}
void ReceiveConfig() //点对点接收配置函数
{
CE=0; //进入待机模式,开始接收指令
WriteData(RX_ADDR_P0,AddrCode,5); //写入RX地址
WriteCom(EN_AA,0x01); //写入RX地址自动应答
WriteCom(EN_RXADDR,0x01); //使能数据通道0
WriteCom(RF_CH,Channel1); //选择通信频率
WriteCom(RX_PW_P0,32); //设置数据宽度
WriteCom(RF_SETUP,0x0f); //射频配置,0db增益,2Mbps,低噪声增益开启
WriteCom(CONFIG,0x0f); //发送模式
CE=1;
}
/*==========数据传输底层==========*/
u8 WriteReadByte(u8 TxData) //收发一字节函数
{
u8 retry=0;
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
{
retry++;
if(retry>200)
return 0;
}
SPI_I2S_SendData(SPI1, TxData); //SPI1发送一个数据
retry=0;
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)//检查指定的SPI标志位设置与否:接受缓存非空标志位
{
retry++;
if(retry>200)
return 0;
}
return SPI_I2S_ReceiveData(SPI1); //返回SPI1最近接收的数据
}
/*==========数据传输层===========*/
u8 WriteCom(u8 RegAddr,u8 Data) //写入函数
{
u8 Status;
CSN=0; //启动nrf24L01
Status=WriteReadByte(W_REGISTER|RegAddr);
WriteReadByte(W_REGISTER|Data);
CSN=1; //关闭nrf24L01
return Status;
}
u8 ReadCom(u8 RegAddr,u8 Data) //读取函数
{
u8 Status;
CSN=0; //启动nrf24L01
Status=WriteReadByte(R_REGISTER|RegAddr);
WriteReadByte(R_REGISTER|Data);
CSN=1; //关闭nrf24L01
return Status;
}
u8 WriteData(u8 RegAddr,u8* DataCode,int Width) //大量数据写入函数
{
u8 Status;
int Num;
CSN=0; //启动nrf24L01
Status=WriteReadByte(W_REGISTER+RegAddr);
// DataCode--; //指针小BUG
for(Num=0;Num<Width;Num++)
{
WriteReadByte(*DataCode); //写入数组中所有数据
// printf("Data[%d]=%x\r\n",Num,(*DataCode));
DataCode++;
}
CSN=1; //关闭nrf24L01
return Status;
}
u8 ReadData(u8 RegAddr,u8* DataCode,int Width) //大量数据读取函数
{
u8 Status;
int Num;
CSN=0; //启动nrf24L01
Status=WriteReadByte(R_REGISTER+RegAddr);
for(Num=0;Num<Width;Num++)
{
DataCode[Num]=WriteReadByte(NOP); //写入数组中所有数据
//printf("Data[%d]=%x\r\n",Num,(*DataCode));
}
CSN=1; //关闭nrf24L01
return Status;
}
/*==========应用层==========*/
char nrf24L01Check() //nrf24L01自检函数
{
u8 DataTrySend[5]={0xA1,0XA2,0XA3,0XA4,0xA5};
u8 DataTryRec[5]={0x00,0x00,0x00,0x00,0x00};
int Num,Check=0;
WriteData(TX_ADDR,DataTrySend,5);
ReadData(TX_ADDR,DataTryRec,5);
for(Num=0;Num<5;Num++)
{
if(DataTrySend[Num]==DataTryRec[Num])
{Check++;}
}
if(Check==5)
{
printf("nrf24L01 check OK.\r\n");
return 1;
}
else
{
printf("nrf24L01 check ERROR.\r\n");
return 0;
}
}
[/mw_shl_code]
NRF24L01部分H文件
[mw_shl_code=applescript,true]#ifndef _NRF24L01_H_
#define _NRF24L01_H_
#include "sys.h"
/*PA4_SPI1_NSS PA5_SPI1_SCK PA6_SPI1_MISO
PA7_SPI1_MOSI PA3_CE*/
/*操作指令*/
#define R_REGISTER 0x00 //读操作前缀
#define W_REGISTER 0x20 //写操作前缀
#define R_RX_PAYLOAD 0x61 //读数据指令
#define W_TX_PAYLOAD 0xA0 //写数据指令
#define FLUSH_TX 0xE1 //清空发送数据
#define FLUSH_RX 0xE2 //清空接收数据
#define NOP 0xFF //空操作,读状态寄存器
/*寄存器地址*/
#define CONFIG 0x00 //基本配置寄存器
#define EN_AA 0x01 //自动应答使能寄存器
#define EN_RXADDR 0x02 //接收地址使能寄存器
#define SETUP_RETR 0x04 //自动重发寄存器
#define RF_CH 0x05 //射频频率设置寄存器
#define RF_SETUP 0x06 //射频配置寄存器
#define STATUS 0x07 //状态寄存器
#define RX_ADDR_P0 0x0A //通道0接收地址
#define TX_ADDR 0x10 //发送地址
#define RX_PW_P0 0x11 //通道0数据宽度
/*通信频道*/
#define Channel1 40
#define Channel2 41
#define Channel3 42
#define Channel4 43
#define Channel5 44
#define Channel6 45
/*使能引脚映射*/
#define IRQ PAin(2)
#define CE PAout(3)
#define CSN PAout(4)
/*==========初始化层==========*/
void SPIInitMaster(void); //主机初始化函数
void SPIInitSlave(void); //从机初始化函数
void SendConfig(void); //点对点发送配置函数
void ReceiveConfig(void); //点对点接收配置函数
/*==========数据传输底层==========*/
u8 WriteReadByte(u8 Data); //收发一字节函数
/*==========数据传输层===========*/
u8 WriteCom(u8 RegAddr,u8 Data); //写入命令函数
u8 ReadCom(u8 RegAddr,u8 Data); //读取函数
u8 WriteData(u8 RegAddr,u8* DataCode,int Width); //大量数据写入函数
u8 ReadData(u8 RegAddr,u8* DataCode,int Width); //大量数据读取函数
/*==========应用层==========*/
char nrf24L01Check(void); //nrf24L01自检函数
#endif
[/mw_shl_code]
接收端函数
主函数和中断
[mw_shl_code=applescript,true]#include "stm32f10x.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "nrf24L01.h"
#include "EXTI.h"
#include "Led.h"
u8 Data[33];
int main(void)
{
delay_init();
uart_init(115200);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
SPIInitMaster(); //主机初始化函数
EXTIInit();
LedInit();
printf("Init down.\r\n");
while(!nrf24L01Check()); //自检
ReceiveConfig();
CE=1;
while(1)
{
// CE=0;
// printf("Config Status:%x\r\n",ReadCom(STATUS,NOP));
// delay_ms(100);
}
}
void EXTI2_IRQHandler()
{
u8 Status;
Status=ReadCom(STATUS,NOP);
printf("Config Status:%x\r\n",Status);
if(Status&0x10) //达到最大重发次数
{
printf("Send Failed.\r\n");
}
if(Status&0x20) //发送完成并返回ACK
{
printf("Send Success.\r\n");
}
if(Status&0x40) //接收到数据
{
printf("Receive Message.\r\n");
Led=~Led;
CSN=0; //启动nrf24L01
WriteReadByte(R_RX_PAYLOAD);
Status=WriteReadByte(NOP);
CSN=1; //关闭nrf24L01
printf("Result:%c\r\n",Status);
}
WriteCom(FLUSH_TX,NOP); //清除TX_FIFO
WriteCom(FLUSH_RX,NOP); //清除RX_FIFO
WriteCom(STATUS,Status); //清除所有标志
EXTI_ClearITPendingBit(EXTI_Line2);
GPIO_SetBits(GPIOA,GPIO_Pin_2);
}
[/mw_shl_code]
NRF24L01部分和发送端一样。
外部中断是非常灵敏,完全没有问题的。
|
|