本帖最后由 怀揣少年梦 于 2021-3-10 19:45 编辑
一、背景:因之前在搞小四轴,一直卡在无线模块,后来买了两个模块来测试自己的程序,是否是正确的。正好此时申请到AT32开发板,过年一直在测试。现发出来给大家参考或者指教一下。
二、模块是安信可的2.4GHz si24r1无线通信模块。
三、测试过程:用户按键按一下,实现发送与接收。开机第一次能正常收发,第二次再按就只会产生发送完成中断。再按就产生重发次数中断。断电再按键就会收发成功。过了几天才发现问题,原来没有清理状态寄存器里的status.清理就可以了。
四、程序:
1)主程序
上传不了。会乱码
2)中断程序
void EXTI9_5_IRQHandler(void)
{
u8 state;
if(EXTI_GetFlagStatus(EXTI_Line9) != RESET)
{
EXTI_ClearIntPendingBit(EXTI_Line9);
SI24R1_CE_Low;
state = SI24R1_Read_Reg(R_REGISTER+STATUS);
/* 发送完成中断*/
if(state & TX_DS)
{
TX_Flag=true;
SI24R1_Set_Mode(IT_RX);
SI24R1_Write_Reg(R_REGISTER+STATUS,TX_DS);
SI24R1_Write_Reg(FLUSH_TX,0xff);
3)配置程序(两个模块配置一模一样,只是用的SPI不一样)
#include "si24r1.h"
#include "systick.h"
#include "stdio.h"
#include "stdlib.h"
#define SI24R1AddrMAX 50 //SI24R1最后一个字节地址最大为50
u8 SI24R1addr = 0xFF; //初始化SI24R1最后一个字节地址
u8 SI24R1_TX_DATA[TX_PAYLO_WIDTH]={0} ; //SI24R1发送缓冲区
u8 SI24R1_RX_DATA[RX_PAYLO_WIDTH]={0} ; //SI24R1接收缓冲区
u8 TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01};//发送地址
u8 RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01};//接收地址
/****************************************************************************
* 名 称:void SI24R1_Init(void)
* 功 能:SI24R1初始化及检查通信
* 入口参数:无
* 出口参数:无
* 说 明:SI24R1spi最大速度不超过10Mbps
****************************************************************************/
void SI24R1_Init(void)
{
SI24R1_GPIO_Init(); //初始化管脚
SI24R1_SPI_Init(); // 初始化SPI2
SI24R1_CSN_High; //片选信号失能
SI24R1_CE_Low; //待机模式
}
/****************************************************************************
* 名 称:void SI24R1_GPIO_Init(void)
* 功 能:配置在SI24R1与stm32间spi通信的引脚及控制SI24R1的引脚
* 入口参数:无
* 出口参数:无
* 说 明:SI24R1spi最大速度不超过10Mbps
****************************************************************************/
void SI24R1_GPIO_Init(void)
{
GPIO_InitType GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_GPIOB | RCC_APB2PERIPH_GPIOD |RCC_APB2PERIPH_AFIO,ENABLE);
//PB13 SCLK;PB14 MISO ;PB15 MOSI
GPIO_InitStructure.GPIO_Pins = GPIO_Pins_13 | GPIO_Pins_14 | GPIO_Pins_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_10MHz; //si24r1 最大读写速度为10M
GPIO_Init(GPIOB,&GPIO_InitStructure);
//CSN 片选管脚
GPIO_InitStructure.GPIO_Pins = GPIO_Pins_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT_PP;
GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_10MHz; //si24r1 最大读写速度为10M
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_ResetBits(GPIOB,GPIO_Pins_12);
//CE 使能管脚
GPIO_InitStructure.GPIO_Pins = GPIO_Pins_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT_PP;
GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_10MHz;
GPIO_Init(GPIOD,&GPIO_InitStructure);
GPIO_ResetBits(GPIOD,GPIO_Pins_8);
}
/****************************************************************************
* 名 称:void SI24R1_SPI_Init(void)
* 功 能:配置在SI24R1与stm32间spi通信的初始化
* 入口参数:无
* 出口参数:无
* 说 明:SI24R1spi最大速度不超过10Mbps
****************************************************************************/
void SI24R1_SPI_Init(void)
{
SPI_InitType SPI_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_SPI2,ENABLE);
//配置SPI1相关参数:全双工通信、MSB/LSB、通信速度、工作模式(mode0~mode3)......
SPI_InitStructure.SPI_TransMode = SPI_TRANSMODE_FULLDUPLEX; //全双工通信
SPI_InitStructure.SPI_Mode = SPI_MODE_MASTER; //主机角色
SPI_InitStructure.SPI_FrameSize =SPI_FRAMESIZE_8BIT; //看时序图,8位数据位
SPI_InitStructure.SPI_CPOL = SPI_CPOL_LOW; //时钟线空闲的时候是什么电平,当前配置为低电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1EDGE; //主机在时钟线哪一个时刻读取MISO引脚的电平,在时钟第一个边沿来采集数据
SPI_InitStructure.SPI_NSSSEL = SPI_NSSSEL_SOFT; //片选需要代码控制
SPI_InitStructure.SPI_MCLKP = SPI_MCLKP_32; //SPI1的通信硬件时钟=72MHz/8=9MHz SI24R1最大为10M
SPI_InitStructure.SPI_FirstBit = SPI_FIRSTBIT_MSB; //最高有效位优先传输
SPI_InitStructure.SPI_CPOLY = 7;
SPI_Init(SPI2,&SPI_InitStructure);
SPI_Enable(SPI2,ENABLE);
}
/****************************************************************************
* 名 称:u8 SPI2_WriteReadByte(u8 Data)
* 功 能:SPI2读写一个字节
* 入口参数:无
* 出口参数:无
* 说 明:无
****************************************************************************/
u8 SPI2_WriteReadByte(u8 Data)
{
u8 cnt = 0;
while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TE) == RESET) //等待发送区为空
{
cnt++;
if( cnt > 100)
return 0;
}
SPI_I2S_TxData(SPI2,Data); //发送一个字节的数据
cnt = 0;
while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RNE) == RESET) //等待接收完一个Byte
{
cnt++;
if( cnt > 100)
return 0;
}
return SPI_I2S_RxData(SPI2); //接收一个字节的数据
}
/****************************************************************************
* 名 称:u8 SI24R1_Write_Reg(u8 reg,u8 val)
* 功 能:对SI24R1写一个字节到寄存器
* 入口参数:无
* 出口参数:无
* 说 明:无
****************************************************************************/
u8 SI24R1_Write_Reg(u8 reg,u8 val)
{
u8 ReceiveData;
SI24R1_CSN_Low;
ReceiveData = SPI2_WriteReadByte(reg);
SPI2_WriteReadByte(val);
SI24R1_CSN_High;
return ReceiveData;
}
/****************************************************************************
* 名 称:u8 SI24R1_Read_Reg(u8 reg,u8 val)
* 功 能:对SI24R1读寄存器的值
* 入口参数:无
* 出口参数:无
* 说 明:无
****************************************************************************/
u8 SI24R1_Read_Reg(u8 reg)
{
u8 RegData;
SI24R1_CSN_Low;
SPI2_WriteReadByte(reg);
RegData = SPI2_WriteReadByte(0xff);
SI24R1_CSN_High;
return RegData;
}
/****************************************************************************
* 名 称:u8 SI24R1_Write_Buffer(u8 reg,u8 *pBuf,u8 len)
* 功 能:向某一个寄存器写入一组数据
* 入口参数 reg 寄存器地址
pBuf 写入的数据地址
len 数据长度
* 出口参数:ReceiveData
* 说 明:无
****************************************************************************/
u8 SI24R1_Write_Buffer(u8 reg,u8 *pBuf,u8 len)
{
u8 ReceiveData;
int i=0;
SI24R1_CSN_Low;
ReceiveData = SPI2_WriteReadByte(reg);
for(i= 0;i < len;i++)
{
SPI2_WriteReadByte(*pBuf);
pBuf++;
}
SI24R1_CSN_High;
return ReceiveData;
}
/****************************************************************************
* 名 称:u8 SI24R1_Read_Buffer(u8 reg,u8 *pBuf,u8 len)
* 功 能:向某一个寄存器读出一组数据
* 入口参数 reg 寄存器地址
pBuf 写入的数据地址
len 数据长度
* 出口参数:ReceiveData
* 说 明:无
****************************************************************************/
u8 SI24R1_Read_Buffer(u8 reg,u8 *pBuf,u8 len)
{
u8 status;
int i;
SI24R1_CSN_Low;
status = SPI2_WriteReadByte(reg);
for(i= 0;i < len;i++)
{
*pBuf = SPI2_WriteReadByte(0xff);
pBuf++;
}
SI24R1_CSN_High;
return status;
}
/****************************************************************************
* 名 称:void SI24R1__Set_Mode(u8 mode)
* 功 能:设置SI24R1发送还是接收模式
* 入口参数 mode 模式设置
* 出口参数:无
* 说 明:无
****************************************************************************/
void SI24R1_Set_Mode(u8 mode)
{
if(mode == IT_TX)
{
SI24R1_CE_Low;
SI24R1_Write_Reg(W_REGISTER+CONFIG,IT_TX);
SI24R1_Write_Reg(W_REGISTER+STATUS,0x7E); //关闭所有中断,防止一进入发送模式就中断
SI24R1_CE_High;
// delay_us(20);
}
else
{
SI24R1_CE_Low;
SI24R1_Write_Reg(W_REGISTER+CONFIG,IT_RX);
SI24R1_Write_Reg(W_REGISTER+STATUS,0x7E); //关闭所有中断,防止一进入接收模式中断
SI24R1_CE_High;
delay_us(200);
}
}
/****************************************************************************
* 名 称:SI24R1_Config(void)
* 功 能:SI24R1基本参数配置,并初始化为发射模式
* 入口参数 :无
* 出口参数:无
* 说 明:无
****************************************************************************/
void SI24R1_Config(void)
{
SI24R1_CE_Low;
//接收模式的配置
SI24R1_Write_Reg(W_REGISTER + SETUP_AW,0x03); //配置通信地址长度,默认值时0x03,即5字节
SI24R1_Write_Buffer(W_REGISTER + TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH);
SI24R1_Write_Buffer(W_REGISTER + RX_ADDR_P0,TX_ADDRESS,TX_ADR_WIDTH); //设置RX节点地址
SI24R1_Write_Reg(W_REGISTER + EN_AA,0x01); //使能通道0自动应答
SI24R1_Write_Reg(W_REGISTER + EN_RXADDR,0x01); //使能通道0的接收地址
SI24R1_Write_Reg(W_REGISTER + SETUP_RETR,0x1A);
SI24R1_Write_Reg(W_REGISTER + RF_CH,40); //设置RF通道为40Hz
SI24R1_Write_Reg(W_REGISTER + RX_PW_P0,TX_PAYLO_WIDTH); //设置接收管道字节数为32字节
SI24R1_Write_Reg(W_REGISTER + RF_SETUP,0x0e); //设置TX发射参数,7db增益,2Mbps,低噪声增益关闭
SI24R1_Set_Mode(IT_RX); //默认为接收模式
//发送模式的配置
// SI24R1_Write_Reg(W_REGISTER + SETUP_AW,0x03); //配置通信地址长度,默认值时0x03,即5字节
// SI24R1_Write_Buffer(W_REGISTER + TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH); //写TX节点地址(发送地址)
// SI24R1_Write_Buffer(W_REGISTER + RX_ADDR_P0,(u8*)TX_ADDRESS,TX_ADR_WIDTH); //设置RX节点地址(为了应答接收设备,接收通道0和发送地址相同)
//
// SI24R1_Write_Reg(W_REGISTER + EN_AA,0x01); //使能通道0自动应答
// SI24R1_Write_Reg(W_REGISTER + EN_RXADDR,0x01); //使能通道0的接收地址
// SI24R1_Write_Reg(W_REGISTER + SETUP_RETR,0x1A); //设置自动重发延时为500us,最大自动重发次数为10
// SI24R1_Write_Reg(W_REGISTER + RF_CH,40); //设置RF通道为40Hz
// SI24R1_Write_Reg(W_REGISTER + RF_SETUP,0x27); //设置TX发射参数,7db增益,2Mbps,低噪声增益关闭
// SI24R1_Set_Mode(IT_TX); //默认为发射模式
SI24R1_CE_High;
delay_us(20);
}
/****************************************************************************
* 名 称:void SI24R1_TxPacket(u8 *txbuf)
* 功 能:SI24R1发送一包数据
* 入口参数 :txbuf 要发送的数据地址
* 出口参数:无
* 说 明:无
****************************************************************************/
void SI24R1_TxPacket(u8 *txbuf)
{
SI24R1_Config();
SI24R1_CE_Low;
SI24R1_Write_Buffer(W_REGISTER + TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH); //写TX节点地址
SI24R1_Write_Buffer(W_REGISTER + RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); //写RX节点地址
SI24R1_Write_Reg(FLUSH_TX ,0xFF);
SI24R1_Write_Buffer(W_TX_PAYLOAD,txbuf,TX_PAYLO_WIDTH); //写数据到TX_BUFF
SI24R1_Write_Reg(W_REGISTER + CONFIG,IT_TX); //设置为发送模式,开启所有中断
SI24R1_Write_Reg(W_REGISTER + STATUS,0x7E); //清除所有中断,防止一进去发送模式就触发中断
SI24R1_CE_High;
delay_us(10);
}
/****************************************************************************
* 名 称:void SI24R1_RxPacket(u8 *txbuf)
* 功 能:SI24R1接收一包数据
* 入口参数 :rxbuf 要接收的数据地址
* 出口参数:无
* 说 明:无
****************************************************************************/
void SI24R1_RxPacket(u8 *rxbuf)
{
SI24R1_CE_Low;
SI24R1_Read_Buffer(R_RX_PAYLOAD,rxbuf,TX_PAYLO_WIDTH); //读取RX的有效数据
SI24R1_Write_Reg(FLUSH_RX ,0xFF); //清除RX_FIFO
SI24R1_CE_High;
}
/****************************************************************************
* 名 称:u8 SPI_Test_Connection(void)
* 功 能:测试SPI是否与MCU正常通信
* 入口参数 :无
* 出口参数:无
* 说 明:无
****************************************************************************/
u8 SPI2_Test_Connection(void)
{
u8 test_txbuf[5] = {0xC0,0xC1,0xC2,0xC3,0xC4};
u8 test_rxbuf[5] = {0};
u8 i;
SI24R1_Write_Buffer(W_REGISTER + TX_ADDR,test_txbuf,5); // 写入5个字节的数据
SI24R1_Read_Buffer(TX_ADDR,test_rxbuf,5); // 读出写入的数据
for(i=0;i< 5; i++)
{
// printf("SI24R1 test_rxbuf[%d]=%x\r\n",i,test_rxbuf[i]);
if(test_rxbuf[i] != test_txbuf[i])
{
break;
}
}
if(i != 5 )
{
return 0; // SPI与MCU通信有误
}
return 1; //正常通信
}
/****************************************************************************
* 名 称:void SI24R1_Check(void)
* 功 能:测试MCU与SI24R1是否连接
* 入口参数 :无
* 出口参数:无
* 说 明:无
****************************************************************************/
void SI24R1_Check(void)
{
while(!SPI2_Test_Connection())
{
printf("\r SI24R1 has no connection with MCU! \r\n");
}
if(SPI2_Test_Connection())
printf("\r SI24R1 has connections with MCU! \r\n");
}
/****************************************************************************
* 名 称:u8 SI24R1_Test_Connection(void)
* 功 能:测试飞控SI24R1和遥控SI24R1是否正常通信
* 入口参数 :无
* 出口参数:无
* 说 明:无
****************************************************************************/
void SI24R1_Test_Connection(void)
{
u8 i=0;
for(i = 0; i < 32;i++)
{
SI24R1_TX_DATA[0] = 1;
}
SI24R1_TxPacket(SI24R1_TX_DATA);
}
谢谢大家指教
|
|