同步步兵代码,暂时关闭底盘跟随

This commit is contained in:
2025-11-02 21:21:11 +08:00
parent 456cc96c81
commit 3821589bed
693 changed files with 238044 additions and 2735 deletions

View File

@@ -0,0 +1,580 @@
#include "stm32f4xx.h" // Device header
#include "stm32f4xx_conf.h"
#include "Warming.h"
#include "Delay.h"
/*
*SPI模式选择:
*
*CPOL(时钟极性):
* 0/Low-空闲状态时,SCK=0
* 1/High-空闲状态时,SCK=1
*CPHA(时钟相位):
* 0/1Edge-SCK第一个边沿移入数据,第二个边沿移出数据
* 1/2Edge-SCK第一个边沿移出数据,第二个边沿移入数据
*
*模式0:CPOL=0,CPHA=0
*模式1:CPOL=0,CPHA=1
*模式2:CPOL=1,CPHA=0
*模式3:CPOL=1,CPHA=1
*/
//加速度计寄存器
#define BMI088_ACC_CHIP_ID 0x00//加速度计Who Am I寄存器
#define BMI088_ACC_PWR_CTRL 0x7D//加速度计电源控制寄存器
#define BMI088_ACC_PWR_CONF 0x7C//加速度计电源配置寄存器
#define BMI088_ACC_CONF 0x40//加速度计配置寄存器
#define BMI088_ACC_RANGE 0x41//加速度计范围设置寄存器
#define BMI088_INT1_IO_CONF 0x53//加速度计配置INT1输入输出引脚寄存器
#define BMI088_INT1_INT2_MAP_DATA 0x58//加速度计映射数据就绪中断到INT1/INT2寄存器
#define BMI088_ACC_SOFTRESET 0x7E//加速度计软件重启寄存器
#define BMI088_ACC_AccelDataStart 0x12//加速度计数据寄存器首地址
#define BMI088_ACC_TEMP_MSB 0x22//加速度计温度寄存器高八位
#define BMI088_ACC_TEMP_LSB 0x23//加速度计温度寄存器低三位
//陀螺仪寄存器
#define BMI088_GYRO_CHIP_ID 0x00//陀螺仪Who Am I寄存器
#define BMI088_GYRO_RANGE 0x0F//陀螺仪范围设置寄存器
#define BMI088_GYRO_BANDWIDTH 0x10//陀螺仪带宽寄存器
#define BMI088_GYRO_LPM1 0x11//陀螺仪主电源模式选择寄存器
#define BMI088_GYRO_INT_CTRL 0x15//陀螺仪中断控制寄存器
#define BMI088_INT3_INT4_IO_CONF 0x16//陀螺仪配置中断输入输出引脚寄存器
#define BMI088_INT3_INT4_IO_MAP 0x18//陀螺仪映射数据就绪中断到INT3/INT4寄存器
#define BMI088_GYRO_SOFTRESET 0x14//陀螺仪软件重启寄存器
#define BMI088_GYRO_GyroDataStart 0x02//陀螺仪数据寄存器首地址
#define BMI088_ACC_Address 0x1E//加速度计地址
#define BMI088_GYRO_Address 0x0F//陀螺仪地址
#define BMI088_CS_Accel(x) GPIO_WriteBit(GPIOA,GPIO_Pin_4,(BitAction)(x))//写加速度计的片选引脚
#define BMI088_CS_Gyro(x) GPIO_WriteBit(GPIOB,GPIO_Pin_0,(BitAction)(x))//写陀螺仪的片选引脚
#define BMI088_Accel_Start() BMI088_CS_Accel(0)//BMI088加速度计硬件SPI数据交换开始(拉低BMI088_CS_Accel完成片选)
#define BMI088_Accel_Stop() BMI088_CS_Accel(1)//BMI088加速度计硬件SPI数据交换结束(拉高BMI088_CS_Accel结束片选)
#define BMI088_Gyro_Start() BMI088_CS_Gyro(0)//BMI088陀螺仪硬件SPI数据交换开始(拉低BMI088_CS_Gyro完成片选)
#define BMI088_Gyro_Stop() BMI088_CS_Gyro(1)//BMI088陀螺仪硬件SPI数据交换结束(拉高BMI088_CS_Gyro结束片选)
uint8_t BMI088_SPI_DMASend[8],BMI088_SPI_DMAReceive[8];//BMI088的SPI发送DMA存储器数组,BMI088的SPI接收DMA存储器数组
uint8_t BMI088_FirstDMA_Flag=2,BMI088_DMAAccGyroSelect;//BMI088的DMA首次启动标志位(0-已经首次启动,1-准备首次启动,2-等待首次启动),BMI088的DMA处于加速度计数据接收还是陀螺仪数据接收的状态选择(1-加速度计数据接收,2-陀螺仪数据接收)
uint8_t BMI088_DataStartFlag;//BMI088开始接收数据标志位
int16_t BMI088_RawAccelData[3],BMI088_RawGyroData[3],BMI088_RawTemperatureData;//BMI088的三轴加速度原始数据,三轴角速度原始数据和温度原始数据
float BMI088_Accel[3],BMI088_Gyro[3],BMI088_Temperature;//BMI088的三轴加速度数据,三轴角速度数据和温度
/*
*函数简介:BMI088专用微秒级延时
*参数说明:延时时长,单位us
*返回类型:无
*备注:参数范围:0~4294967295
*/
void BMI088_Delay_us(uint32_t us)
{
uint32_t temp;
SysTick->LOAD=us*21; //时间加载我们要延时n倍的us, 1us是一个fac_ua周期所以总共要延时的周期值为二者相乘最后送到Load中。
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //开启使能位 开始倒数
do temp=SysTick->CTRL;
while((temp&0x01) && !(temp&(1<<16))); //用来判断 systick 定时器是否还处于开启状态然后在等待时间到达也就是数到0的时候,此时第十六位设置为1
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器使能位
SysTick->VAL=0x00; //清空计数器
}
/*
*函数简介:BMI088加速度计写寄存器
*参数说明:8bits寄存器地址
*参数说明:8bits寄存器写入数据
*返回类型:无
*备注:在第一个数据发送时,第二个数据已经在发送缓冲区等待以实现连续数据流
*备注:BMI088的寄存器地址的最高位bit需要为0(即&0x7F),以实现写寄存器
*/
void BMI088_SPI_AccelWriteRegister(uint8_t RegAddress,uint8_t Data)
{
BMI088_Accel_Start();//开始
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)!=SET);//发送缓冲区为空
SPI_I2S_SendData(SPI1,RegAddress & 0x7F);//将地址(写数据)放入发送缓冲区
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)!=SET);//发送缓冲区为空
SPI_I2S_SendData(SPI1,Data);//SPI发送数据(放入发送缓冲区,实现连续数据流)
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)!=SET);//接收缓冲区非空,即第一个数据(地址数据)移位完成
SPI_I2S_ReceiveData(SPI1);//此数据来自发送地址,故读取当前接收缓冲区以清除接收数据和标志位
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)!=SET);//接收缓冲区非空,即第二个数据(接收数据)移位完成
SPI_I2S_ReceiveData(SPI1);//SPI接收数据,清除接收数据和标志位
BMI088_Accel_Stop();//结束
}
/*
*函数简介:BMI088加速度计读寄存器
*参数说明:8bits寄存器地址
*返回类型:8bits寄存器读出数据
*备注:在第一个数据发送时,第二个数据已经在发送缓冲区等待以实现连续数据流
*备注:BMI088的寄存器地址的最高位bit需要为1(即|0x80),以实现读寄存器
*备注:加速度计读取寄存器时(包括连续读取和非连续读取),第一个读出数据是乱码,从第二个开始才是有效数据
*/
uint8_t BMI088_SPI_AccelReadRegister(uint8_t RegAddress)
{
BMI088_Accel_Start();//开始
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)!=SET);//发送缓冲区为空
SPI_I2S_SendData(SPI1,RegAddress | 0x80);//将地址(读数据)放入发送缓冲区
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)!=SET);//发送缓冲区为空
SPI_I2S_SendData(SPI1,0x00);//SPI发送数据(放入发送缓冲区,实现连续数据流)
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)!=SET);//接收缓冲区非空,即第一个数据(地址数据)移位完成
SPI_I2S_ReceiveData(SPI1);//此数据来自发送地址,故读取当前接收缓冲区以清除接收数据和标志位
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)!=SET);//发送缓冲区为空
SPI_I2S_SendData(SPI1,0x00);//SPI发送数据(放入发送缓冲区,实现连续数据流)
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)!=SET);//接收缓冲区非空,即第二个数据(地址数据)移位完成
SPI_I2S_ReceiveData(SPI1);//此回传数据为乱码,故读取当前接收缓冲区以清除接收数据和标志位
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)!=SET);//接收缓冲区非空,即第三个数据(接收数据)移位完成
BMI088_Accel_Stop();//结束
return SPI_I2S_ReceiveData(SPI1);//SPI接收数据
}
/*
*函数简介:BMI088陀螺仪写寄存器
*参数说明:8bits寄存器地址
*参数说明:8bits寄存器写入数据
*返回类型:无
*备注:在第一个数据发送时,第二个数据已经在发送缓冲区等待以实现连续数据流
*备注:BMI088的寄存器地址的最高位bit需要为0(即&0x7F),以实现写寄存器
*/
void BMI088_SPI_GyroWriteRegister(uint8_t RegAddress,uint8_t Data)
{
BMI088_Gyro_Start();//开始
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)!=SET);//发送缓冲区为空
SPI_I2S_SendData(SPI1,RegAddress & 0x7F);//将地址(写数据)放入发送缓冲区
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)!=SET);//发送缓冲区为空
SPI_I2S_SendData(SPI1,Data);//SPI发送数据(放入发送缓冲区,实现连续数据流)
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)!=SET);//接收缓冲区非空,即第一个数据(地址数据)移位完成
SPI_I2S_ReceiveData(SPI1);//此数据来自发送地址,故读取当前接收缓冲区以清除接收数据和标志位
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)!=SET);//接收缓冲区非空,即第二个数据(接收数据)移位完成
SPI_I2S_ReceiveData(SPI1);//SPI接收数据,清除接收数据和标志位
BMI088_Gyro_Stop();//结束
}
/*
*函数简介:BMI088陀螺仪读寄存器
*参数说明:8bits寄存器地址
*返回类型:8bits寄存器读出数据
*备注:在第一个数据发送时,第二个数据已经在发送缓冲区等待以实现连续数据流
*备注:BMI088的寄存器地址的最高位bit需要为1(即|0x80),以实现读寄存器
*/
uint8_t BMI088_SPI_GyroReadRegister(uint8_t RegAddress)
{
BMI088_Gyro_Start();//开始
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)!=SET);//发送缓冲区为空
SPI_I2S_SendData(SPI1,RegAddress | 0x80);//将地址(读数据)放入发送缓冲区
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)!=SET);//发送缓冲区为空
SPI_I2S_SendData(SPI1,0x00);//SPI发送数据(放入发送缓冲区,实现连续数据流)
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)!=SET);//接收缓冲区非空,即第一个数据(地址数据)移位完成
SPI_I2S_ReceiveData(SPI1);//此数据来自发送地址,故读取当前接收缓冲区以清除接收数据和标志位
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)!=SET);//接收缓冲区非空,即第二个数据(接收数据)移位完成
BMI088_Gyro_Stop();//结束
return SPI_I2S_ReceiveData(SPI1);//SPI接收数据
}
/*
*函数简介:BMI088初始化
*参数说明:无
*返回类型:无
*备注:使用SPI1,SPI模式3(CPOL=1,CPHA=1),波特率5.25MHz
*备注:规定SPI1_CLK为PB3,SPI1_MISO为PB4,SPI1_MOSI为PA7,CS1_Accel为PA4(加速度计片选引脚),CS1_Gyro为PB0(陀螺仪片选引脚)
*备注:规定INT1_Accel为PC4,INT1_Gyro为PC5,分别连接芯片的INT1和INT3,配置为数据就绪中断(下降沿)
*备注:采用SPI收发DMA节约CPU资源(SPI1发送DMA为DMA2数据流3通道3,SPI1接收DMA为DMA2数据流2通道3)
*备注:在初始化中对寄存器进行了配置,最关键配置为加速度量程±3g,角速度量程±2000°/s
*备注:配置寄存器时会对加速度计和陀螺仪进行软重启,加速度计耗时1ms,陀螺仪耗时30ms,同时软重启之后第一次读写有bug,数据会错误
*备注:加速度计软重启之后需要重新上电,需要配置BMI088_ACC_PWR_CTRL和BMI088_ACC_PWR_CONF两个寄存器,每次配置需要等待一段时间,测试得到250us足矣,共耗时500us,保险起见采用300us,共耗时600us
*备注:保险起见在每一次配置寄存器之后加入300us的延时,共计3.6ms
*备注:初始化时会检查加速度计和陀螺仪的ID,ID错误会进行报警,并且程序会卡死不断的进行检测,具体报警现象见Warming.h
*/
void BMI088_Init(void)
{
/*===============配置时钟===============*/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);//开启时钟
/*===============配置GPIO===============*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//默认上拉
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);//配置CS1_Accel(加速度计片选引脚)
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
GPIO_Init(GPIOB,&GPIO_InitStructure);//配置CS1_Gyro(陀螺仪片选引脚)
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;//复用推挽
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3 | GPIO_Pin_4;
GPIO_Init(GPIOB,&GPIO_InitStructure);//配置SPI1_CLK和SPI1_MISO
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;
GPIO_Init(GPIOA,&GPIO_InitStructure);//配置SPI1_MOSI
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;//上拉输入
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4 | GPIO_Pin_5;
GPIO_Init(GPIOC,&GPIO_InitStructure);//配置INT1_Accel和INT1_Gyro(加速度计和陀螺仪的中断线)
GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_SPI1);//开启PA7的SPI1复用模式
GPIO_PinAFConfig(GPIOB,GPIO_PinSource3,GPIO_AF_SPI1);//开启PB3的SPI1复用模式
GPIO_PinAFConfig(GPIOB,GPIO_PinSource4,GPIO_AF_SPI1);//开启PB4的SPI1复用模式
/*===============配置SPI和SPI收发DMA===============*/
SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Mode=SPI_Mode_Master;//主机模式
SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;//双线全双工
SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b;//8位数据帧
SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB;//高位先行
SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_8;//波特率预分频系数8,SCK频率为PCLK/分频系数,即Freq_SCK=42MHz/8=5.25MHz
SPI_InitStructure.SPI_CPOL=SPI_CPOL_High;//CPOL=1
SPI_InitStructure.SPI_CPHA=SPI_CPHA_2Edge;//第二个边沿开始采样,即CPHA=1
SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;//软件NSS模式
SPI_InitStructure.SPI_CRCPolynomial=10;//CRC检测,不懂
SPI_Init(SPI1,&SPI_InitStructure);
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_Channel=DMA_Channel_3;//选择DMA通道3
DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;//普通模式(非自动重装)
DMA_InitStructure.DMA_DIR=DMA_DIR_MemoryToPeripheral;//转运方向为存储器到外设
DMA_InitStructure.DMA_BufferSize=8;//数据传输量为8字节
DMA_InitStructure.DMA_Priority=DMA_Priority_VeryHigh;//最高优先级
DMA_InitStructure.DMA_PeripheralBaseAddr=(uint32_t)&(SPI1->DR);//外设地址(SPI1的DR数据接收寄存器)
DMA_InitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;//外设突发单次传输
DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;//外设数据长度为1字节(8bits)
DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设地址不自增
DMA_InitStructure.DMA_Memory0BaseAddr=(uint32_t)BMI088_SPI_DMASend;//存储器地址(BMI088的SPI发送DMA存储器数组)
DMA_InitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single;//存储器突发单次传输
DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;//存储器数据长度为1字节(8bits)
DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;//存储器地址自增
DMA_InitStructure.DMA_FIFOMode=DMA_FIFOMode_Disable;//不使用FIFO模式
DMA_InitStructure.DMA_FIFOThreshold=DMA_FIFOStatus_1QuarterFull;//设置FIFO阈值为1/4(不使用FIFO模式时,此位无意义)
DMA_Init(DMA2_Stream3,&DMA_InitStructure);//初始化数据流3(SPI1发送DMA)
DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralToMemory;//转运方向为外设到存储器
DMA_InitStructure.DMA_Memory0BaseAddr=(uint32_t)BMI088_SPI_DMAReceive;//存储器地址(BMI088的SPI接收DMA存储器数组)
DMA_Init(DMA2_Stream2,&DMA_InitStructure);//初始化数据流2(SPI1接收DMA)
SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Tx,ENABLE);//使能SPI1的发送DMA搬运
SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Rx,ENABLE);//使能SPI1的接收DMA搬运
BMI088_CS_Accel(1);//复位CS1_Accel(加速度计片选引脚)
BMI088_CS_Gyro(1);//复位CS1_Gyro(陀螺仪片选引脚)
/*===============配置外部中断和SPI1接收DMA传输完成中断===============*/
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,EXTI_PinSource4);//配置PC4与中断线的映射关系
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,EXTI_PinSource5);//配置PC5与中断线的映射关系
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line=EXTI_Line4;//配置中断线4
EXTI_InitStructure.EXTI_LineCmd=ENABLE;//使能中断线
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//配置为外部中断模式
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;//选择下降沿触发
EXTI_Init(&EXTI_InitStructure);//初始化EXTI
EXTI_InitStructure.EXTI_Line=EXTI_Line5;//配置中断线5
EXTI_Init(&EXTI_InitStructure);//初始化EXTI
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择NVIC分组为2
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=EXTI4_IRQn;//配置NVIC通道4
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能NVIC通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//响应优先级
NVIC_Init(&NVIC_InitStructure);//初始化NVIC
NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQn;//配置NVIC通道9_5
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//响应优先级
NVIC_Init(&NVIC_InitStructure);//初始化NVIC
DMA_ITConfig(DMA2_Stream2,DMA_IT_TC,ENABLE);//打通SPI1到NVIC的接收传输完成中断通道
NVIC_InitStructure.NVIC_IRQChannel=DMA2_Stream2_IRQn;//选择SPI1接收DMA传输完成中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//响应优先级为1
NVIC_Init(&NVIC_InitStructure);//初始化SPI1接收DMA传输完成中断的NVIC
/*===============使能===============*/
DMA_Cmd(DMA2_Stream3,DISABLE);//失能DMA2的数据流3(SPI1发送DMA)
DMA_Cmd(DMA2_Stream2,DISABLE);//失能DMA2的数据流2(SPI1接收DMA)
SPI_Cmd(SPI1,ENABLE);//使能SPI1
/*===============检测加速度计和陀螺仪ID并配置寄存器===============*/
while(1)
{
if(BMI088_SPI_AccelReadRegister(BMI088_ACC_CHIP_ID)==BMI088_ACC_Address && BMI088_SPI_GyroReadRegister(BMI088_GYRO_CHIP_ID)==BMI088_GYRO_Address)//设备连接正常,加速度计和陀螺仪Who Am I正确
{
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//关闭NVIC通道
NVIC_Init(&NVIC_InitStructure);//初始化NVIC
BMI088_SPI_AccelWriteRegister(BMI088_ACC_SOFTRESET,0xB6);BMI088_Delay_us(1000);//加速度计软重启,耗时1ms
BMI088_SPI_GyroWriteRegister(BMI088_GYRO_SOFTRESET,0xB6);BMI088_Delay_us(30000);//陀螺仪软重启,耗时30ms
BMI088_SPI_AccelReadRegister(BMI088_ACC_CHIP_ID);//再次读取ID,促使从机BMI088的SPI重新开始工作(软重启之后第一次读写有bug)
BMI088_SPI_GyroReadRegister(BMI088_GYRO_CHIP_ID);
BMI088_SPI_AccelWriteRegister(BMI088_ACC_PWR_CTRL,0x04);BMI088_Delay_us(300);//打开加速度计
BMI088_SPI_AccelWriteRegister(BMI088_ACC_PWR_CONF,0x00);BMI088_Delay_us(300);//加速度计正常工作(不挂起)
BMI088_SPI_AccelWriteRegister(BMI088_ACC_CONF,0xAB);BMI088_Delay_us(300);//配置加速度计正常低通滤波带宽,800Hz输出
BMI088_SPI_AccelWriteRegister(BMI088_ACC_RANGE,0x00);BMI088_Delay_us(300);//配置加速度计量程±3g
BMI088_SPI_AccelWriteRegister(BMI088_INT1_IO_CONF,0x08);BMI088_Delay_us(300);//配置加速度计INT1推挽输出,低电平有效(下降沿)
BMI088_SPI_AccelWriteRegister(BMI088_INT1_INT2_MAP_DATA,0x04);BMI088_Delay_us(300);//配置INT1中断映射为数据就绪中断
BMI088_SPI_GyroWriteRegister(BMI088_GYRO_RANGE,0x00);BMI088_Delay_us(300);//配置陀螺仪量程±2000°/s
BMI088_SPI_GyroWriteRegister(BMI088_GYRO_BANDWIDTH,0x82);BMI088_Delay_us(300);//配置陀螺仪滤波器带宽116Hz,1000Hz输出(写此寄存器,写入数据最高位需要为1)
BMI088_SPI_GyroWriteRegister(BMI088_GYRO_LPM1,0x00);BMI088_Delay_us(300);//配置陀螺仪主电源模式为正常模式
BMI088_SPI_GyroWriteRegister(BMI088_GYRO_INT_CTRL,0x80);BMI088_Delay_us(300);//使能陀螺仪数据就绪中断
BMI088_SPI_GyroWriteRegister(BMI088_INT3_INT4_IO_CONF,0x00);BMI088_Delay_us(300);//配置陀螺仪INT3推挽输出,低电平有效(下降沿)
BMI088_SPI_GyroWriteRegister(BMI088_INT3_INT4_IO_MAP,0x01);BMI088_Delay_us(300);//配置INT3中断映射为数据就绪中断
BMI088_FirstDMA_Flag=1;//准备首次启动DMA
break;
}
else//设备异常
{
NVIC_InitStructure.NVIC_IRQChannelCmd=DISABLE;//关闭NVIC通道
NVIC_Init(&NVIC_InitStructure);//初始化NVIC
Warming_BMI088LinkError();//BMI088连接异常报警
Delay_ms(25);
}
}
while(BMI088_DataStartFlag==0);//等待数据开始接收
}
/*
*函数简介:BMI088处理加速度计数据
*参数说明:无
*返回类型:无
*备注:本函数用于SPI接收DMA传输完成之后,数据来源为BMI088的SPI接收DMA存储器数组BMI088_SPI_DMAReceive
*备注:加速度a(m2/s)=a_raw(g)*9.8=(a_raw/32768*Range)*9.8
* =(a_raw/32768*3)*9.8
* =a_raw*0.0008974358974
*/
void BMI088_ProcessAccelData(void)
{
BMI088_RawAccelData[0]=(int16_t)((uint16_t)BMI088_SPI_DMAReceive[3]<<8|BMI088_SPI_DMAReceive[2]);//拼接为原始数据
BMI088_RawAccelData[1]=(int16_t)((uint16_t)BMI088_SPI_DMAReceive[5]<<8|BMI088_SPI_DMAReceive[4]);
BMI088_RawAccelData[2]=(int16_t)((uint16_t)BMI088_SPI_DMAReceive[7]<<8|BMI088_SPI_DMAReceive[6]);
BMI088_Accel[0]=BMI088_RawAccelData[0]*0.0008974358974f;
BMI088_Accel[1]=BMI088_RawAccelData[1]*0.0008974358974f;
BMI088_Accel[2]=BMI088_RawAccelData[2]*0.0008974358974f;
// BMI088_Accel[0]=BMI088_RawAccelData[0]/32768.0f*9.8f*3.0f;
// BMI088_Accel[1]=BMI088_RawAccelData[1]/32768.0f*9.8f*3.0f;
// BMI088_Accel[2]=BMI088_RawAccelData[2]/32768.0f*9.8f*3.0f;
}
/*
*函数简介:BMI088处理温度数据
*参数说明:无
*返回类型:无
*备注:本函数用于SPI接收DMA传输完成之后,数据来源为BMI088的SPI接收DMA存储器数组BMI088_SPI_DMAReceive
*备注:温度t(℃)=t_raw*0.125+23
*备注:温度数据是11bits数据
*/
void BMI088_ProcessTemperatureData(void)
{
uint16_t unsignedTemperatureData=((uint16_t)BMI088_SPI_DMAReceive[2]<<3) | (BMI088_SPI_DMAReceive[3]>>5);//拼接为原始数据
if(unsignedTemperatureData>1023)BMI088_RawTemperatureData=unsignedTemperatureData-2048;//对11bits数据进行正负数处理
else BMI088_RawTemperatureData=unsignedTemperatureData;
BMI088_Temperature=BMI088_RawTemperatureData*0.125f+23.0f;
}
/*
*函数简介:BMI088处理陀螺仪数据
*参数说明:无
*返回类型:无
*备注:本函数用于SPI接收DMA传输完成之后,数据来源为BMI088的SPI接收DMA存储器数组BMI088_SPI_DMAReceive
*备注:角速度w(rad/s)=w_raw(°/s)/180*Π=(w_raw/32768*Range)/180*Π
* =(w_raw/32768*2000)/180*Π
* =w_raw*0.00106526443603169529841533860381
*/
void BMI088_ProcessGyroData(void)
{
BMI088_RawGyroData[0]=(int16_t)((uint16_t)BMI088_SPI_DMAReceive[2]<<8|BMI088_SPI_DMAReceive[1]);//拼接为原始数据
BMI088_RawGyroData[1]=(int16_t)((uint16_t)BMI088_SPI_DMAReceive[4]<<8|BMI088_SPI_DMAReceive[3]);
BMI088_RawGyroData[2]=(int16_t)((uint16_t)BMI088_SPI_DMAReceive[6]<<8|BMI088_SPI_DMAReceive[5]);
BMI088_Gyro[0]=BMI088_RawGyroData[0]*0.00106526443603169529841533860381f;
BMI088_Gyro[1]=BMI088_RawGyroData[1]*0.00106526443603169529841533860381f;
BMI088_Gyro[2]=BMI088_RawGyroData[2]*0.00106526443603169529841533860381f;
// BMI088_Gyro[0]=BMI088_RawGyroData[0]/32768.0f*2000.0f/180.0f*3.141592653589793238462643383279f;
// BMI088_Gyro[1]=BMI088_RawGyroData[1]/32768.0f*2000.0f/180.0f*3.141592653589793238462643383279f;
// BMI088_Gyro[2]=BMI088_RawGyroData[2]/32768.0f*2000.0f/180.0f*3.141592653589793238462643383279f;
}
/*
*函数简介:BMI088检测并关闭DMA
*参数说明:无
*返回类型:无
*备注:用在外部中断中用来等待SPI传输结束后配合BMI088_OpenDMA函数重新启动DMA
*/
void BMI088_CheckAndCloseDMA(void)
{
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_BSY)==SET);//等待总线空闲
while(DMA_GetFlagStatus(DMA2_Stream3,DMA_FLAG_TCIF3)==RESET);//判断发送完成
DMA_ClearFlag(DMA2_Stream3,DMA_FLAG_TCIF3);//清除发送完成标志位
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_BSY)==SET);//等待总线空闲
DMA_Cmd(DMA2_Stream3,DISABLE);//失能DMA2的数据流2
DMA_Cmd(DMA2_Stream2,DISABLE);//失能DMA2的数据流3
}
/*
*函数简介:BMI088开启DMA
*参数说明:DMA传输数据个数
*返回类型:无
*备注:SPI收发DMA开启后会立刻开始发送接收,请在使用函数前配置BMI088的SPI发送DMA存储器数组BMI088_SPI_DMASend
*/
void BMI088_OpenDMA(uint8_t DMA_BufferSize)
{
while(DMA_GetCmdStatus(DMA2_Stream2)!=DISABLE);//检测DMA2的数据流2为可配置状态
DMA_SetCurrDataCounter(DMA2_Stream2,DMA_BufferSize);//恢复传输计数器的值
DMA_Cmd(DMA2_Stream2,ENABLE);//使能DMA2的数据流2
while(DMA_GetCmdStatus(DMA2_Stream3)!=DISABLE);//检测DMA2的数据流3为可配置状态
DMA_SetCurrDataCounter(DMA2_Stream3,DMA_BufferSize);//恢复传输计数器的值
DMA_Cmd(DMA2_Stream3,ENABLE);//使能DMA2的数据流3
}
/*
*函数简介:BMI088加速度计外部中断中断函数
*参数说明:无
*返回类型:无
*备注:在中断函数中启动DMA收发以实现减少CPU负担
*/
void EXTI4_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line4)==SET)//检测BMI088加速度计外部中断触发(即检测EXTI通道4中断触发)
{
EXTI_ClearITPendingBit(EXTI_Line4);//清除标志位
if(BMI088_FirstDMA_Flag==0)//非第一次启动DMA
{
BMI088_CheckAndCloseDMA();//关闭DMA准备配置
BMI088_Accel_Start();//片选加速度计
BMI088_DMAAccGyroSelect=1;//DMA为加速度计数据接收
BMI088_SPI_DMASend[0]=BMI088_ACC_AccelDataStart | 0x80;//配置SPI的发送数据的地址(读数据)
BMI088_OpenDMA(8);//开启DMA转运8个数据
}
else if(BMI088_FirstDMA_Flag==1)//第一次启动DMA
{
BMI088_FirstDMA_Flag=0;
BMI088_Accel_Start();//片选加速度计
BMI088_DMAAccGyroSelect=1;//DMA为加速度计数据接收
BMI088_SPI_DMASend[0]=BMI088_ACC_AccelDataStart | 0x80;//配置SPI的发送数据的地址(读数据)
DMA_Cmd(DMA2_Stream2,ENABLE);//使能DMA2的数据流2
DMA_Cmd(DMA2_Stream3,ENABLE);//使能DMA2的数据流3
}
}
}
/*
*函数简介:BMI088陀螺仪外部中断中断函数
*参数说明:无
*返回类型:无
*备注:在中断函数中启动DMA收发以实现减少CPU负担
*备注:第一次DMA转运8个数据,从第二次DMA开始转运7个数据
*/
void EXTI9_5_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line5)==SET)//检测BMI088陀螺仪外部中断触发(即检测EXTI通道5中断触发)
{
EXTI_ClearITPendingBit(EXTI_Line5);//清除标志位
if(BMI088_FirstDMA_Flag==0)//非第一次启动DMA
{
BMI088_CheckAndCloseDMA();//关闭DMA准备配置
BMI088_Gyro_Start();//片选陀螺仪
BMI088_DMAAccGyroSelect=2;//DMA为陀螺仪数据接收
BMI088_SPI_DMASend[0]=BMI088_GYRO_GyroDataStart | 0x80;//配置SPI的发送数据的地址(读数据)
BMI088_OpenDMA(7);//开启DMA转运7个数据
}
else if(BMI088_FirstDMA_Flag==1)//第一次启动DMA
{
BMI088_FirstDMA_Flag=0;
BMI088_Gyro_Start();//片选陀螺仪
BMI088_DMAAccGyroSelect=2;//DMA为陀螺仪数据接收
BMI088_SPI_DMASend[0]=BMI088_GYRO_GyroDataStart | 0x80;//配置SPI的发送数据的地址(读数据)
DMA_Cmd(DMA2_Stream2,ENABLE);//使能DMA2的数据流2
DMA_Cmd(DMA2_Stream3,ENABLE);//使能DMA2的数据流3
}
}
}
/*
*函数简介:SPI1接收DMA传输完成中断中断函数
*参数说明:无
*返回类型:无
*备注:在此函数中会处理接收数据获取BMI088的三轴加速度数据,三轴角速度数据和温度
*备注:在此函数中如果接收的是加速度计数据会再开启一个DMA去接收温度数据
*/
void DMA2_Stream2_IRQHandler(void)
{
if(DMA_GetITStatus(DMA2_Stream2,DMA_IT_TCIF2)==SET)//检测SPI1接收DMA传输完成中断触发
{
static uint8_t BMI088_ReceiveTEMPFlag=0;//BMI088的DMA接收温度数据标志位(0-未在接收温度数据,1-正在接收温度数据)
BMI088_DataStartFlag=1;//数据开始接收
DMA_ClearITPendingBit(DMA2_Stream2,DMA_IT_TCIF2);//清除标志位
if(BMI088_ReceiveTEMPFlag==1)//正在接收温度数据
{
BMI088_Accel_Stop();//结束加速度计片选
BMI088_ProcessTemperatureData();//处理温度数据
BMI088_ReceiveTEMPFlag=0;
}
else//接收加速度或角速度数据
{
if(BMI088_DMAAccGyroSelect==1)//接收加速度计数据
{
BMI088_Accel_Stop();//结束加速度计片选
BMI088_ProcessAccelData();//处理加速度数据
BMI088_ReceiveTEMPFlag=1;//开始接收温度数据
BMI088_CheckAndCloseDMA();//关闭DMA准备配置
BMI088_Accel_Start();//片选加速度计
BMI088_SPI_DMASend[0]=BMI088_ACC_TEMP_MSB | 0x80;//配置SPI的发送数据的地址(读数据)
BMI088_OpenDMA(4);//开启DMA转运4个数据
}
else if(BMI088_DMAAccGyroSelect==2)//接收陀螺仪数据
{
BMI088_Gyro_Stop();//结束陀螺仪片选
BMI088_ProcessGyroData();//处理陀螺仪数据
}
}
}
}

View File

@@ -0,0 +1,9 @@
#ifndef __BMI088_H
#define __BMI088_H
extern float BMI088_Accel[],BMI088_Gyro[],BMI088_Temperature;//BMI088的三轴加速度数据,三轴角速度数据和温度
extern int16_t BMI088_RawAccelData[],BMI088_RawGyroData[],BMI088_RawTemperatureData;//BMI088的三轴加速度原始数据,三轴角速度原始数据和温度原始数据
void BMI088_Init(void);//BMI088初始化
#endif

View File

@@ -0,0 +1,107 @@
#include "stm32f4xx.h" // Device header
#include "stm32f4xx_conf.h"
#include "Buzzer.h"
#include "Delay.h"
int16_t Buzzer_ToneFreq[37]=
{
0,
32107,30305,28604,26999,25483,24053,22703,21429,20226,19091,18019,17008,
16053,15152,14302,13499,12742,12026,11352,10714,10113,9545,9010,8504,
8027,7576,7151,6750,6371,6013,5676,5357,5056,4773,4505,4252,
};//蜂鸣器音调频率表
/*
*函数简介:蜂鸣器初始化
*参数说明:无
*返回类型:无
*备注:无源蜂鸣器
*备注:默认TIM4-CH3(PD14)
*/
void Buzzer_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);//开启时钟
TIM_InternalClockConfig(TIM4);//选择时基单元TIM4
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//复用推挽
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//默认上拉
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_14;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOD,&GPIO_InitStructure);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource14,GPIO_AF_TIM4);//开启PD14的TIM4复用模式
TIM_TimeBaseInitTypeDef TIM_InitStructure;
TIM_InitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//配置时钟分频为1分频
TIM_InitStructure.TIM_CounterMode=TIM_CounterMode_Up;//配置计数器模式为向上计数
TIM_InitStructure.TIM_Period=10-1;//ARR,PWM为十分位
TIM_InitStructure.TIM_Prescaler=19091-1;//PSC,默认频率低音6(440Hz)
TIM_InitStructure.TIM_RepetitionCounter=0;//配置重复计数单元的置为0
TIM_TimeBaseInit(TIM4,&TIM_InitStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//配置输出比较模式
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//配置输出比较的极性
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//输出使能
TIM_OCInitStructure.TIM_Pulse=0;//配置输出比较寄存器CCR的值,默认占空比0%
TIM_OC3Init(TIM4,&TIM_OCInitStructure);//配置PD14输出PWM
TIM_Cmd(TIM4,ENABLE);//启动定时器
}
/*
*函数简介:蜂鸣器发声
*参数说明:枚举音调
*参数说明:持续时间,单位ms
*返回类型:无
*备注:无
*/
void Buzzer_Time(Buzzer_Tone Tone,uint16_t ms)
{
if(Tone!=P)//非停止调
{
TIM_PrescalerConfig(TIM4,Buzzer_ToneFreq[Tone],TIM_PSCReloadMode_Update);//配置频率
TIM_SetCompare3(TIM4,5);//占空比50%
}
else//停止调(即空拍)
TIM_SetCompare3(TIM4,0);//占空比0%,即关闭PWM
Delay_ms(ms);
TIM_SetCompare3(TIM4,0);//占空比0%,即关闭PWM
}
/*
*函数简介:蜂鸣器打开
*参数说明:枚举音调
*返回类型:无
*备注:无
*/
void Buzzer_ON(Buzzer_Tone Tone)
{
TIM_Cmd(TIM4,ENABLE);//打开定时器
if(Tone!=P)//非停止调
{
TIM_PrescalerConfig(TIM4,Buzzer_ToneFreq[Tone],TIM_PSCReloadMode_Update);//配置频率
TIM_SetCompare3(TIM4,5);//占空比50%
}
else//停止调(即空拍)
TIM_SetCompare3(TIM4,0);//占空比0%,即关闭PWM
}
/*
*函数简介:蜂鸣器关闭
*参数说明:无
*返回类型:无
*备注:无
*/
void Buzzer_OFF(void)
{
TIM_SetCompare3(TIM4,0);//占空比0%,即关闭PWM
TIM_Cmd(TIM4,DISABLE);//关闭定时器
}

View File

@@ -0,0 +1,17 @@
#ifndef __BUZZER_H
#define __BUZZER_H
typedef enum
{
P=0,//空拍
L1,L1_,L2,L2_,L3,L4,L4_,L5,L5_,L6,L6_,L7,//低音
M1,M1_,M2,M2_,M3,M4,M4_,M5,M5_,M6,M6_,M7,//中音
H1,H1_,H2,H2_,H3,H4,H4_,H5,H5_,H6,H6_,H7,//高音
}Buzzer_Tone;//蜂鸣器音调枚举
void Buzzer_Init(void);//蜂鸣器初始化
void Buzzer_Time(Buzzer_Tone Tone,uint16_t ms);//蜂鸣器发声
void Buzzer_ON(Buzzer_Tone Tone);//蜂鸣器打开
void Buzzer_OFF(void);//蜂鸣器关闭
#endif

View File

@@ -0,0 +1,268 @@
#include "stm32f4xx.h" // Device header
#include "stm32f4xx_conf.h"
#include "MyI2C.h"
#include "Warming.h"
#include "Delay.h"
#define IST8310_Address 0x0E//IST8310的地址
#define IST8310_Who_Am_I 0x00//Who Am I寄存器
#define IST8310_CNTL1 0x0A//控制设置1寄存器
#define IST8310_CNTL2 0x0B//控制设置2寄存器
#define IST8310_AVGCNTL 0x41//采样平均寄存器
#define IST8310_PDCNTL 0x42//脉冲持续时间寄存器
#define IST8310_DataStart 0x03//数据寄存器首地址
#define IST8310_TEMPL 0x1C//温度寄存器-温度低八位
#define IST8310_TEMPH 0x1D//温度寄存器-温度高八位
MyI2C_InitTypedef MyI2C_InitStruction;//I2C配置结构体
uint8_t IST8310_DataStartFlag;//IST8310开始接收数据标志位
int16_t IST8310_RawData[4];//IST8310原始数据,1~3为xyz轴磁场原始数据,4为温度原始数据
float IST8310_MagneticField[3];//IST8310磁场数据,分别为xyz轴磁场数据(单位uT)
float IST8310_Temperature;//IST8310温度数据(单位℃)
/*
*函数简介:IST8310的RSTN延时
*参数说明:无
*返回类型:无
*备注:默认配置RSTN延时500us,重启一次延时1ms
*/
void IST8310_Delay_us(void)
{
uint32_t temp;
SysTick->LOAD=500*21; //时间加载我们要延时500倍的us, 1us是一个fac_ua周期所以总共要延时的周期值为二者相乘最后送到Load中。
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //开启使能位 开始倒数
do temp=SysTick->CTRL;
while((temp&0x01) && !(temp&(1<<16))); //用来判断 systick 定时器是否还处于开启状态然后在等待时间到达也就是数到0的时候,此时第十六位设置为1
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器使能位
SysTick->VAL=0x00; //清空计数器
}
/*
*函数简介:IST8310配置RSTN电平
*参数说明:高低电平,0-低电平 1-高电平
*返回类型:无
*备注:规定RSTN为PG6
*备注:RSTN为低电平时重启IST8310
*备注:每次修改RSTN,需要等待一段时间产生作用(测试得到0.5ms足矣)
*/
void IST8310_RSTN(uint8_t x)
{
GPIO_WriteBit(GPIOG,GPIO_Pin_6,(BitAction)(x));
IST8310_Delay_us();//延时0.5ms
}
/*
*函数简介:IST8310重启
*参数说明:无
*返回类型:无
*备注:重启大概耗时1ms
*/
void IST8310_Reset(void)
{
IST8310_RSTN(0);
IST8310_RSTN(1);
}
/*
*函数简介:IST8310初始化
*参数说明:无
*返回类型:无
*备注:规定SCL为PA8,SDA为PC9,DRDY为PG3(下降沿)
*备注:初始化中配置了寄存器并进行了重启,大概耗时1ms
*备注:在初始化中对寄存器进行了配置
*备注:初始化时会检查IST8310的ID,ID错误会进行报警,并且程序会卡死不断的进行检测,具体报警现象见Warming.h
*/
void IST8310_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG,ENABLE);//开启时钟
MyI2C_InitStruction.MyI2C_SCL_RCC=RCC_AHB1Periph_GPIOA;//配置SCL为PA8
MyI2C_InitStruction.MyI2C_SCL_GPIOx=GPIOA;
MyI2C_InitStruction.MyI2C_SCL_Pin=GPIO_Pin_8;
MyI2C_InitStruction.MyI2C_SDA_RCC=RCC_AHB1Periph_GPIOC;//配置SDA为PC9
MyI2C_InitStruction.MyI2C_SDA_GPIOx=GPIOC;
MyI2C_InitStruction.MyI2C_SDA_Pin=GPIO_Pin_9;
MyI2C_Init(&MyI2C_InitStruction);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉输入
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3;//配置DRDY(PG3)
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOG,&GPIO_InitStructure);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOG,EXTI_PinSource3);//配置PG3与中断线的映射关系
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line=EXTI_Line3;//配置中断线3
EXTI_InitStructure.EXTI_LineCmd=ENABLE;//使能中断线
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//配置为外部中断模式
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;//选择下降沿触发
EXTI_Init(&EXTI_InitStructure);//初始化EXTI
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择NVIC分组为2
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=EXTI3_IRQn;//配置NVIC通道3
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能NVIC通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//响应优先级
NVIC_Init(&NVIC_InitStructure);//初始化NVIC
while(1)
{
if(MyI2C_CheckDevice(&MyI2C_InitStruction,IST8310_Address)==1 && MyI2C_CheckWhoAmI(&MyI2C_InitStruction,IST8310_Address,IST8310_Who_Am_I)==0x10)//设备连接正常,Who Am I正确
{
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//开启NVIC通道
NVIC_Init(&NVIC_InitStructure);//初始化NVIC
MyI2C_WriteRegister(&MyI2C_InitStruction,IST8310_Address,IST8310_CNTL1,0x03);//配置为连续输出模式,输出频率200Hz
MyI2C_WriteRegister(&MyI2C_InitStruction,IST8310_Address,IST8310_CNTL2,0x08);//配置为DRDY下降沿中断,不重启
MyI2C_WriteRegister(&MyI2C_InitStruction,IST8310_Address,IST8310_AVGCNTL,0x12);//配置为四次采样平均
MyI2C_WriteRegister(&MyI2C_InitStruction,IST8310_Address,IST8310_PDCNTL,0xC0);//配置为正常脉冲持续时间
IST8310_Reset();//IST8310重启
break;
}
else//设备异常
{
NVIC_InitStructure.NVIC_IRQChannelCmd=DISABLE;//关闭NVIC通道
NVIC_Init(&NVIC_InitStructure);//初始化NVIC
Warming_IST8310LinkError();//IST8310连接异常报警
Delay_ms(25);
}
}
while(IST8310_DataStartFlag==0);//等待数据开始接收
}
/*
*函数简介:IST8310数据读取
*参数说明:无
*返回类型:无
*备注:读取三轴磁场(单位uT)和温度(单位℃)
*备注:温度转换比例没找到,暂且以0.001为比例转换
*/
void IST8310_GetData(void)
{
uint8_t IST8310_MagneticFieldReceive[6],TempL,TempH;//三轴磁场返回数据,温度返回数据(低八位),温度返回数据(高八位)
MyI2C_ContinuousReadRegister(&MyI2C_InitStruction,IST8310_Address,IST8310_DataStart,IST8310_MagneticFieldReceive,6);//读取三轴磁场返回数据
TempL=MyI2C_ReadRegister(&MyI2C_InitStruction,IST8310_Address,IST8310_TEMPL);//读取温度返回数据(低八位)
TempH=MyI2C_ReadRegister(&MyI2C_InitStruction,IST8310_Address,IST8310_TEMPH);//读取温度返回数据(高八位)
IST8310_RawData[0]=(int16_t)(((uint16_t)(IST8310_MagneticFieldReceive[1])<<8)|IST8310_MagneticFieldReceive[0]);
IST8310_RawData[1]=(int16_t)(((uint16_t)(IST8310_MagneticFieldReceive[3])<<8)|IST8310_MagneticFieldReceive[2]);
IST8310_RawData[2]=(int16_t)(((uint16_t)(IST8310_MagneticFieldReceive[5])<<8)|IST8310_MagneticFieldReceive[4]);//获取三轴磁场原始数据
IST8310_RawData[3]=(int16_t)(((uint16_t)(TempH)<<8)|TempL);//获取温度原始数据
IST8310_MagneticField[0]=IST8310_RawData[0]*0.3f;
IST8310_MagneticField[1]=IST8310_RawData[1]*0.3f;
IST8310_MagneticField[2]=IST8310_RawData[2]*0.3f;//获取三轴磁场数据
IST8310_Temperature=IST8310_RawData[3]*0.001f;//获取温度
}
/*
*函数简介:IST8310外部中断中断函数
*参数说明:无
*返回类型:无
*备注:在中断函数中读取数据
*/
void EXTI3_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line3)==SET)//检测IST8310外部中断触发(即检测EXTI通道3中断触发)
{
EXTI_ClearITPendingBit(EXTI_Line3);//清除标志位
IST8310_GetData();//读取数据
IST8310_DataStartFlag=1;//数据开始接收
}
}
/*硬件I2C的遗骸*/
////void IST8310_I2CInit(void)
////{
////
////
//// GPIO_InitTypeDef GPIO_InitStructure;
//// GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
//// GPIO_InitStructure.GPIO_OType=GPIO_OType_OD;
//// GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;
//// GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
//// GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
//// GPIO_Init(GPIOA,&GPIO_InitStructure);
//// GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
//// GPIO_Init(GPIOC,&GPIO_InitStructure);
//// GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
//// GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
//// GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;
//// GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
//// GPIO_Init(GPIOG,&GPIO_InitStructure);
////
//// GPIO_PinAFConfig(GPIOA,GPIO_PinSource8,GPIO_AF_I2C3);
//// GPIO_PinAFConfig(GPIOC,GPIO_PinSource9,GPIO_AF_I2C3);
////
//// I2C_InitTypeDef I2C_InitStructure;
//// I2C_InitStructure.I2C_Mode=I2C_Mode_I2C;
//// I2C_InitStructure.I2C_ClockSpeed=10000;
//// I2C_InitStructure.I2C_DutyCycle=I2C_DutyCycle_2;
//// I2C_InitStructure.I2C_Ack=I2C_Ack_Disable;
//// I2C_InitStructure.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit;
//// I2C_InitStructure.I2C_OwnAddress1=0x01;
//// I2C_Init(I2C3,&I2C_InitStructure);
////
//// I2C3->CR1 |= I2C_CR1_SWRST;
//// while(I2C_GetFlagStatus(I2C3,I2C_FLAG_BUSY)==SET);
//// I2C3->CR1 &= ~I2C_CR1_SWRST;
////
//// I2C_Cmd(I2C3,ENABLE);
////
//// GPIO_ResetBits(GPIOG,GPIO_Pin_6);
//// Delay_ms(50);
//// GPIO_SetBits(GPIOG,GPIO_Pin_6);
//// Delay_ms(50);
//// LED_BInit();
////}
////void IST8310_I2CWriteData(uint8_t Address,uint8_t Data)
////{
//// uint8_t B=0;
//// while(I2C_GetFlagStatus(I2C3,I2C_FLAG_BUSY)==SET);
////
//// I2C_GenerateSTART(I2C3,ENABLE);
//// while(I2C_CheckEvent(I2C3,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);
////
//// while(I2C_GetFlagStatus(I2C3,I2C_FLAG_BUSY)!=SET);
//// while(I2C_GetFlagStatus(I2C3,I2C_FLAG_MSL)!=SET);
//// //I2C_SendData(I2C3,0x0E<<1);
//// int i=0;
//// do
//// {
//// I2C_Send7bitAddress(I2C3,i<<1,I2C_Direction_Receiver);
//// i++;
//// if(i==0x8F)break;
//// }
//// while(I2C_GetFlagStatus(I2C3,I2C_FLAG_ADDR)!=SET);
//// if(i<0x8F)LED_BON();
//// //while(I2C_CheckEvent(I2C3,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)!=SUCCESS);
//// I2C_SendData(I2C3,0x00);
//// //while(I2C_CheckEvent(I2C3,I2C_EVENT_MASTER_BYTE_TRANSMITTING)!=SUCCESS);
////
////// I2C_SendData(I2C3,Data);
//// //while(I2C_CheckEvent(I2C3,I2C_EVENT_MASTER_BYTE_TRANSMITTED)!=SUCCESS);
//// I2C_GenerateSTART(I2C3,ENABLE);
//// //while(I2C_CheckEvent(I2C3,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);
////
//// //I2C_SendData(I2C3,(0x0E<<1)|0x01);
//// I2C_Send7bitAddress(I2C3,0x0E,I2C_Direction_Receiver);
//// //while(I2C_GetFlagStatus(I2C3,I2C_FLAG_AF)==SET);
//// //while(I2C_GetFlagStatus(I2C3,I2C_FLAG_ADDR)!=SET);
//// //while(I2C_CheckEvent(I2C3,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)!=SUCCESS);
//// B=I2C_ReceiveData(I2C3);
//// //while(I2C_CheckEvent(I2C3,I2C_EVENT_MASTER_BYTE_TRANSMITTING)!=SUCCESS);
////
//// I2C_GenerateSTOP(I2C3,ENABLE);
////}

View File

@@ -0,0 +1,12 @@
#ifndef __IST8310_H
#define __IST8310_H
extern int16_t IST8310_RawData[];//IST8310原始数据,1~3为xyz轴磁场原始数据,4为温度原始数据
extern float IST8310_MagneticField[];//IST8310磁场数据,分别为xyz轴磁场数据(单位uT)
extern float IST8310_Temperature;//IST8310温度数据(单位℃)
void IST8310_Init(void);//IST8310初始化
void IST8310_Reset(void);//IST8310重启
void IST8310_GetData(void);//IST8310数据读取
#endif

View File

@@ -0,0 +1,255 @@
#include "stm32f4xx.h" // Device header
#include "stm32f4xx_conf.h"
/*
*函数简介:三色单色LED初始化
*参数说明:无
*返回类型:无
*备注:蓝色-PH10,绿色-PH11,红色-PH12
*/
void LED_Init(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH,ENABLE);//开启时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//默认上拉
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOH,&GPIO_InitStructure);
GPIO_ResetBits(GPIOH,GPIO_Pin_10);
GPIO_ResetBits(GPIOH,GPIO_Pin_11);
GPIO_ResetBits(GPIOH,GPIO_Pin_12);//默认三灯均熄灭
}
/*
*函数简介:蓝色单色LED初始化
*参数说明:无
*返回类型:无
*备注:引脚PH10
*/
void LED_BInit(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH,ENABLE);//开启时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//默认上拉
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOH,&GPIO_InitStructure);
GPIO_ResetBits(GPIOH,GPIO_Pin_10);//默认熄灭
}
/*
*函数简介:蓝灯点亮
*参数说明:无
*返回类型:无
*备注:无
*/
void LED_BON(void)
{
GPIO_SetBits(GPIOH,GPIO_Pin_10);
}
/*
*函数简介:蓝灯熄灭
*参数说明:无
*返回类型:无
*备注:无
*/
void LED_BOFF(void)
{
GPIO_ResetBits(GPIOH,GPIO_Pin_10);
}
/*
*函数简介:蓝灯亮灭反转
*参数说明:无
*返回类型:无
*备注:无
*/
void LED_BTurn(void)
{
if(GPIO_ReadInputDataBit(GPIOH,GPIO_Pin_10)==0)//当前蓝灯灭
GPIO_SetBits(GPIOH,GPIO_Pin_10);
else//当前蓝灯亮
GPIO_ResetBits(GPIOH,GPIO_Pin_10);
}
/*
*函数简介:绿色单色LED初始化
*参数说明:无
*返回类型:无
*备注:引脚PH11
*/
void LED_GInit(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH,ENABLE);//开启时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//默认上拉
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOH,&GPIO_InitStructure);
GPIO_ResetBits(GPIOH,GPIO_Pin_11);//默认熄灭
}
/*
*函数简介:绿灯点亮
*参数说明:无
*返回类型:无
*备注:无
*/
void LED_GON(void)
{
GPIO_SetBits(GPIOH,GPIO_Pin_11);
}
/*
*函数简介:绿灯熄灭
*参数说明:无
*返回类型:无
*备注:无
*/
void LED_GOFF(void)
{
GPIO_ResetBits(GPIOH,GPIO_Pin_11);
}
/*
*函数简介:绿灯亮灭反转
*参数说明:无
*返回类型:无
*备注:无
*/
void LED_GTurn(void)
{
if(GPIO_ReadInputDataBit(GPIOH,GPIO_Pin_11)==0)//当前绿灯灭
GPIO_SetBits(GPIOH,GPIO_Pin_11);
else//当前绿灯亮
GPIO_ResetBits(GPIOH,GPIO_Pin_11);
}
/*
*函数简介:红色单色LED初始化
*参数说明:无
*返回类型:无
*备注:无
*/
void LED_RInit(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH,ENABLE);//开启时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//默认上拉
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOH,&GPIO_InitStructure);
GPIO_ResetBits(GPIOH,GPIO_Pin_12);//默认熄灭
}
/*
*函数简介:红灯点亮
*参数说明:无
*返回类型:无
*备注:无
*/
void LED_RON(void)
{
GPIO_SetBits(GPIOH,GPIO_Pin_12);
}
/*
*函数简介:红灯熄灭
*参数说明:无
*返回类型:无
*备注:无
*/
void LED_ROFF(void)
{
GPIO_ResetBits(GPIOH,GPIO_Pin_12);
}
/*
*函数简介:红灯亮灭反转
*参数说明:无
*返回类型:无
*备注:无
*/
void LED_RTurn(void)
{
if(GPIO_ReadInputDataBit(GPIOH,GPIO_Pin_12)==0)//当前红灯灭
GPIO_SetBits(GPIOH,GPIO_Pin_12);
else//当前红灯亮
GPIO_ResetBits(GPIOH,GPIO_Pin_12);
}
/*
*函数简介:RGB混色LED初始化
*参数说明:无
*返回类型:无
*备注:蓝色-PH10,绿色-PH11,红色-PH12
*/
void LED_MaxInit(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH,ENABLE);//开启时钟
TIM_InternalClockConfig(TIM5);//选择时基单元TIM5
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//复用推挽
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//默认上拉
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOH,&GPIO_InitStructure);//配置TIM5的CH1-3
GPIO_PinAFConfig(GPIOH,GPIO_PinSource10,GPIO_AF_TIM5);
GPIO_PinAFConfig(GPIOH,GPIO_PinSource11,GPIO_AF_TIM5);
GPIO_PinAFConfig(GPIOH,GPIO_PinSource12,GPIO_AF_TIM5);//开启PH10-12的TIM5复用模式
TIM_TimeBaseInitTypeDef TIM_InitStructure;
TIM_InitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//配置时钟分频为1分频
TIM_InitStructure.TIM_CounterMode=TIM_CounterMode_Up;//配置计数器模式为向上计数
TIM_InitStructure.TIM_Period=1000-1;//ARR,PWM为千分位
TIM_InitStructure.TIM_Prescaler=84-1;//PSC,默认1000Hz
TIM_InitStructure.TIM_RepetitionCounter=0;//配置重复计数单元的置为0
TIM_TimeBaseInit(TIM5,&TIM_InitStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//配置输出比较模式
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//配置输出比较的极性
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//输出使能
TIM_OCInitStructure.TIM_Pulse=0;//配置输出比较寄存器CCR的值
TIM_OC1Init(TIM5,&TIM_OCInitStructure);
TIM_OC2Init(TIM5,&TIM_OCInitStructure);
TIM_OC3Init(TIM5,&TIM_OCInitStructure);
TIM_Cmd(TIM5,ENABLE);//启动定时器
}
/*
*函数简介:设置混色LED的RGB
*参数说明:三个8位整型,表示RGB的三个值
*返回类型:无
*备注:无
*/
void LED_SetColor(uint8_t R,uint8_t G,uint8_t B)
{
TIM_SetCompare1(TIM5,B*1000/255);
TIM_SetCompare2(TIM5,G*1000/255);
TIM_SetCompare3(TIM5,R*1000/255);
}

View File

@@ -0,0 +1,20 @@
#ifndef __LED_H
#define __LED_H
void LED_Init(void);//三色单色LED初始化
void LED_BInit(void);//蓝色单色LED初始化
void LED_BON(void);//蓝灯点亮
void LED_BOFF(void);//蓝灯熄灭
void LED_BTurn(void);//蓝灯亮灭反转
void LED_GInit(void);//绿色单色LED初始化
void LED_GON(void);//绿灯点亮
void LED_GOFF(void);//绿灯熄灭
void LED_GTurn(void);//绿灯亮灭反转
void LED_RInit(void);//红色单色LED初始化
void LED_RON(void);//红灯点亮
void LED_ROFF(void);//红灯熄灭
void LED_RTurn(void);//红灯亮灭反转
void LED_MaxInit(void);//RGB混色LED初始化
void LED_SetColor(uint8_t R,uint8_t G,uint8_t B);//设置混色LED的RGB
#endif

View File

@@ -0,0 +1,111 @@
#include "stm32f4xx.h" // Device header
#include "stm32f4xx_conf.h"
/*
*函数简介:激光初始化
*参数说明:无
*返回类型:无
*备注:规定引脚为PC8,高电平点亮
*/
void Laser_Init(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);//开启时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//默认上拉
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOC,&GPIO_InitStructure);
GPIO_ResetBits(GPIOC,GPIO_Pin_8);//默认关闭
}
/*
*函数简介:激光普通模式打开激光
*参数说明:无
*返回类型:无
*备注:规定引脚为PC8,高电平点亮
*/
void Laser_ON(void)
{
GPIO_SetBits(GPIOC,GPIO_Pin_8);
}
/*
*函数简介:激光普通模式关闭激光
*参数说明:无
*返回类型:无
*备注:规定引脚为PC8,低电平关闭
*/
void Laser_OFF(void)
{
GPIO_ResetBits(GPIOC,GPIO_Pin_8);
}
/*
*函数简介:激光PWM模式初始化
*参数说明:无
*返回类型:无
*备注:规定引脚为PC8(TIM3_CH3),占空比越高越亮
*/
void Laser_PWMInit(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);//开启时钟
TIM_InternalClockConfig(TIM3);//选择时基单元TIM3
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//复用推挽
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//默认上拉
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOC,&GPIO_InitStructure);
GPIO_PinAFConfig(GPIOC,GPIO_PinSource8,GPIO_AF_TIM3);//开启PC8的TIM3复用模式
TIM_TimeBaseInitTypeDef TIM_InitStructure;
TIM_InitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//配置时钟分频为1分频
TIM_InitStructure.TIM_CounterMode=TIM_CounterMode_Up;//配置计数器模式为向上计数
TIM_InitStructure.TIM_Period=1000-1;//ARR,PWM为千分位1ms
TIM_InitStructure.TIM_Prescaler=84-1;//PSC
TIM_InitStructure.TIM_RepetitionCounter=0;//配置重复计数单元的置为0
TIM_TimeBaseInit(TIM3,&TIM_InitStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//配置输出比较模式
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//配置输出比较的极性
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//输出使能
TIM_OCInitStructure.TIM_Pulse=0;//配置输出比较寄存器CCR的值,默认占空比0
TIM_OC3Init(TIM3,&TIM_OCInitStructure);//配置CH3(PC8)输出PWM
TIM_Cmd(TIM3,DISABLE);//默认关闭定时器
}
/*
*函数简介:激光PWM模式以一定亮度打开激光
*参数说明:亮度百分比,范围0~100,支持一位小数
*返回类型:无
*备注:规定引脚为PC8(TIM3_CH3),占空比越高越亮
*/
void Laser_PWMON(float Brightness)
{
TIM_SetCompare3(TIM3,Brightness*10.0f);//设置占空比
TIM_Cmd(TIM3,ENABLE);//启动定时器
}
/*
*函数简介:激光PWM模式关闭激光
*参数说明:无
*返回类型:无
*备注:规定引脚为PC8(TIM3_CH3)
*/
void Laser_PWMOFF(void)
{
TIM_SetCompare3(TIM3,0);//设置占空比为0
TIM_Cmd(TIM3,DISABLE);//关闭定时器
}

View File

@@ -0,0 +1,11 @@
#ifndef __LASER_H
#define __LASER_H
void Laser_Init(void);//激光初始化
void Laser_ON(void);//激光普通模式打开激光
void Laser_OFF(void);//激光普通模式关闭激光
void Laser_PWMInit(void);//激光PWM模式初始化
void Laser_PWMON(float Brightness);//激光PWM模式以一定亮度打开激光
void Laser_PWMOFF(void);//激光PWM模式关闭激光
#endif

View File

@@ -0,0 +1,264 @@
#include "stm32f4xx.h" // Device header
#include "stm32f4xx_conf.h"
#include "Remote.h"
#include "UART.h"
#include "Warming.h"
#include "RefereeSystem.h"
uint8_t Remote_RxData0[18];//遥控器DMA数据存储器0
uint8_t Remote_RxData1[18];//遥控器DMA数据存储器1
Remote_Data Remote_RxData;//遥控器接收数据
Remote_Data Remote_LastRxData;//遥控器上一次接收数据
uint8_t Remote_Status;//遥控器连接状态,默认未连接(0)
uint8_t Remote_StartFlag=1;//遥控器启动标志位,0-未在启动阶段,1-准备启动,2-第一次接收到数据
/*
*函数简介:遥控器初始化
*参数说明:无
*返回类型:无
*备注:默认接收引脚为PC11(USART3-Rx)
*备注:采用串口DMA双缓冲接收
*备注:配置定时中断为TIM7 25ms,用来检测遥控器连接情况
*备注:加入独立看门狗,用来在数据接收错误时复位(只在上电的一刻可能数据错误)
*备注:独立看门狗时钟为LSI(32kHz),预分频数默认为8,故IWDG时钟4kHz,重装载值为0x0FFF(4095)
*备注:喂狗时间(溢出时间)T_OUT=Reload/(LSI/Prescaler)=4095/(32k/8)=1.02375s
*/
void Remote_Init(void)
{
/*===============配置时钟===============*/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7,ENABLE);//开启时钟
/*===============配置GPIO===============*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//复用推挽
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//默认上拉
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOC,&GPIO_InitStructure);//初始化USART3-Rx(PC11)
GPIO_PinAFConfig(GPIOC,GPIO_PinSource11,GPIO_AF_USART3);//开启PC11的USART3复用模式
/*===============配置USART和串口接收DMA===============*/
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate=100000;//配置波特率100k
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//配置无硬件流控制
USART_InitStructure.USART_Mode=USART_Mode_Rx;//配置为接收模式
USART_InitStructure.USART_Parity=USART_Parity_Even;//配置为偶校验
USART_InitStructure.USART_StopBits=USART_StopBits_1;//配置停止位为1
USART_InitStructure.USART_WordLength=USART_WordLength_8b;//配置字长8bit
USART_Init(USART3,&USART_InitStructure);//初始化USART3
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_Channel=DMA_Channel_4;//选择DMA通道4
DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;//普通模式(非自动重装)
DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralToMemory;//转运方向为外设到存储器
DMA_InitStructure.DMA_BufferSize=18;//数据传输量为18字节
DMA_InitStructure.DMA_Priority=DMA_Priority_VeryHigh;//最高优先级
DMA_InitStructure.DMA_PeripheralBaseAddr=(uint32_t)&(USART3->DR);//外设地址(USART的DR数据接收寄存器)
DMA_InitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;//外设突发单次传输
DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;//外设数据长度为1字节(8bits)
DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设地址不自增
DMA_InitStructure.DMA_Memory0BaseAddr=(uint32_t)Remote_RxData0;//存储器地址(遥控器DMA数据存储器0)
DMA_InitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single;//存储器突发单次传输
DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;//存储器数据长度为1字节(8bits)
DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;//存储器地址自增
DMA_InitStructure.DMA_FIFOMode=DMA_FIFOMode_Disable;//不使用FIFO模式
DMA_InitStructure.DMA_FIFOThreshold=DMA_FIFOStatus_1QuarterFull;//设置FIFO阈值为1/4(不使用FIFO模式时,此位无意义)
DMA_Init(DMA1_Stream1,&DMA_InitStructure);//初始化数据流1
DMA_DoubleBufferModeConfig(DMA1_Stream1,(uint32_t)Remote_RxData1,DMA_Memory_0);//设置双缓冲搬运从遥控器DMA数据存储器0开始
DMA_DoubleBufferModeCmd(DMA1_Stream1,ENABLE);//使能DMA双缓冲功能
/*===============配置定时器===============*/
TIM_InternalClockConfig(TIM7);//选择时基单元的时钟(TIM7)
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//配置时基单元(配置参数)
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//配置时钟分频为1分频
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//配置计数器模式为向上计数
TIM_TimeBaseInitStructure.TIM_Period=21000-1;//配置自动重装值ARR
TIM_TimeBaseInitStructure.TIM_Prescaler=1000-1;//配置分频值PSC,默认定时25ms
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//配置重复计数单元的置为0
TIM_TimeBaseInit(TIM7,&TIM_TimeBaseInitStructure);//初始化TIM7
TIM_ClearFlag(TIM7,TIM_FLAG_Update);//清除配置时基单元产生的中断标志位
/*===============配置接收中断和定时器中断===============*/
USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);//打通USART3到NVIC的串口接收中断通道
TIM_ITConfig(TIM7,TIM_IT_Update,ENABLE);//使能TIM7更新中断
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择NVIC分组2(2位抢占优先级,2位响应优先级)
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=USART3_IRQn;//选择USART3中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//响应优先级为1
NVIC_Init(&NVIC_InitStructure);//初始化USART3的NVIC
NVIC_InitStructure.NVIC_IRQChannel=TIM7_IRQn;//选择中断通道为TIM2
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//TIM2的抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;//TIM2的响应优先级
NVIC_Init(&NVIC_InitStructure);//初始化NVIC
/*===============使能===============*/
DMA_Cmd(DMA1_Stream1,ENABLE);//使能DMA1的数据流1
USART_DMACmd(USART3,USART_DMAReq_Rx,ENABLE);//使能串口USART3的DMA搬运
USART_Cmd(USART3,ENABLE);//启动USART3
TIM_Cmd(TIM7,ENABLE);//启动定时器
/*===============配置IWDG===============*/
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
IWDG_SetPrescaler(IWDG_Prescaler_8);//8分频
IWDG_SetReload(0x0FFF);//设置重装载值
IWDG_Enable();
}
/*
*函数简介:遥控器开启
*参数说明:无
*返回类型:无
*备注:默认开启串口USART3
*/
void Remote_ON(void)
{
USART_Cmd(USART3,ENABLE);//启动USART3
}
/*
*函数简介:遥控器关闭
*参数说明:无
*返回类型:无
*备注:默认关闭串口USART3
*/
void Remote_OFF(void)
{
USART_Cmd(USART3,DISABLE);//失能USART3
Remote_Status=0;//遥控器连接状态变为未连接
}
/*
*函数简介:遥控器DMA转运复位
*参数说明:无
*返回类型:无
*备注:无
*/
void Remote_TransferReset(void)
{
while(DMA_GetFlagStatus(DMA1_Stream1,DMA_FLAG_TCIF1)==RESET);//判断接收完成
DMA_ClearFlag(DMA1_Stream1,DMA_FLAG_TCIF1);//清除接收完成标志位
DMA_Cmd(DMA1_Stream1,DISABLE);//失能DMA1的数据流1
while(DMA_GetCmdStatus(DMA1_Stream1)!=DISABLE);//检测DMA1的数据流1为可配置状态
DMA_SetCurrDataCounter(DMA1_Stream1,18);//恢复传输计数器的值
DMA_Cmd(DMA1_Stream1,ENABLE);//使能DMA1的数据流1
}
/*
*函数简介:遥控器数据处理
*参数说明:无
*返回类型:无
*备注:遥控器接收数据共18Bytes(144bits)
*/
void Remote_DataProcess(void)
{
uint8_t *Data;//选择存储器
uint16_t Remote_R_RL_True;
if(DMA_GetCurrentMemoryTarget(DMA1_Stream1)==0)Data=Remote_RxData1;//若当前转运位于存储器0,则存储器1数据完整,采用存储器1进行数据处理
else Data=Remote_RxData0;//若当前转运位于存储器1,则存储器0数据完整,采用存储器0进行数据处理
Remote_RxData.Remote_Mouse_KeyLastR=Remote_RxData.Remote_Mouse_KeyR;//获取上一次五个键的状态
Remote_RxData.Remote_KeyLast_Q=Remote_RxData.Remote_Key_Q;
Remote_RxData.Remote_KeyLast_E=Remote_RxData.Remote_Key_E;
Remote_RxData.Remote_KeyLast_Shift=Remote_RxData.Remote_Key_Shift;
Remote_RxData.Remote_KeyLast_Ctrl=Remote_RxData.Remote_Key_Ctrl;
//Remote_RxData.Remote_R_RL=(((uint16_t)Data[1]<<8) | Data[0]) & 0x07FF;//B[0:10],11bits
Remote_R_RL_True=(((uint16_t)Data[1]<<8) | Data[0]) & 0x07FF;//B[0:10],11bits
if(Remote_R_RL_True>1025)
Remote_RxData.Remote_R_RL=Remote_R_RL_True-1;
else if(Remote_R_RL_True<1023)
Remote_RxData.Remote_R_RL=Remote_R_RL_True+1;
else
Remote_RxData.Remote_R_RL=1024;
Remote_RxData.Remote_R_UD=(((uint16_t)Data[2]<<5) | (Data[1]>>3)) & 0x07FF;//B[11:21],11bits
Remote_RxData.Remote_L_RL=(((uint16_t)Data[4]<<10) | (((uint16_t)Data[3]<<2) | (Data[2]>>6))) & 0x07FF;//B[22:32],11bits
Remote_RxData.Remote_L_UD=(((uint16_t)Data[5]<<7) | (Data[4]>>1)) & 0x07FF;//B[33:43],11bits
Remote_RxData.Remote_RS=(Data[5]>>4) & 0x03;//B[44:45],2bits
Remote_RxData.Remote_LS=(Data[5]>>6) & 0x03;//B[46:47],2bits
Remote_RxData.Remote_Mouse_RL=(int16_t)(((uint16_t)Data[7]<<8) | Data[6]);//B[48:63],16bits
Remote_RxData.Remote_Mouse_DU=(int16_t)(((uint16_t)Data[9]<<8) | Data[8]);//B[64:79],16bits
Remote_RxData.Remote_Mouse_Wheel=(int16_t)(((uint16_t)Data[11]<<8) | Data[10]);//B[80:95],16bits
Remote_RxData.Remote_Mouse_KeyL=Data[12];//B[96:103],8bits
Remote_RxData.Remote_Mouse_KeyR=Data[13];//B[104:111],8bits
Remote_RxData.Remote_Key_W=Data[14] & 0x01;//B[112:112],1bits
Remote_RxData.Remote_Key_S=(Data[14]>>1) & 0x01;//B[113:113],1bits
Remote_RxData.Remote_Key_A=(Data[14]>>2) & 0x01;//B[114:114],1bits
Remote_RxData.Remote_Key_D=(Data[14]>>3) & 0x01;//B[115:115],1bits
Remote_RxData.Remote_Key_Shift=(Data[14]>>4) & 0x01;//B[116:116],1bits
Remote_RxData.Remote_Key_Ctrl=(Data[14]>>5) & 0x01;//B[117:117],1bits
Remote_RxData.Remote_Key_Q=(Data[14]>>6) & 0x01;//B[118:118],1bits
Remote_RxData.Remote_Key_E=(Data[14]>>7) & 0x01;//B[119:119],1bits
Remote_RxData.Remote_ThumbWheel=(int16_t)((uint16_t)Data[17]<<8) | Data[16];//B[120:135],16bits
if(Remote_RxData.Remote_KeyLast_Q==0 && Remote_RxData.Remote_Key_Q==1)Remote_RxData.Remote_KeyPush_Q=!Remote_RxData.Remote_KeyPush_Q;//检测是否按下
if(Remote_RxData.Remote_KeyLast_E==0 && Remote_RxData.Remote_Key_E==1)Remote_RxData.Remote_KeyPush_E=!Remote_RxData.Remote_KeyPush_E;
if(Remote_RxData.Remote_KeyLast_Shift==0 && Remote_RxData.Remote_Key_Shift==1)Remote_RxData.Remote_KeyPush_Shift=!Remote_RxData.Remote_KeyPush_Shift;
if(Remote_RxData.Remote_KeyLast_Ctrl==0 && Remote_RxData.Remote_Key_Ctrl==1)Remote_RxData.Remote_KeyPush_Ctrl=!Remote_RxData.Remote_KeyPush_Ctrl;
if(Remote_RxData.Remote_Mouse_KeyLastR==0 && Remote_RxData.Remote_Mouse_KeyR==1)Remote_RxData.Remote_Mouse_KeyPushR=1;
else Remote_RxData.Remote_Mouse_KeyPushR=0;
}
/*
*函数简介:遥控器接收中断
*参数说明:无
*返回类型:无
*备注:USART的接收中断
*/
void USART3_IRQHandler(void)
{
TIM_SetCounter(TIM7,0);
TIM_Cmd(TIM7,DISABLE);//关闭定时器并重置计数值
if(DMA_GetCurrDataCounter(DMA1_Stream1)==18)//转运一次完成,并交换了存储器
{
Remote_TransferReset();//复位DMA1的数据流1
Remote_DataProcess();//数据处理
if(Remote_StartFlag==1)//第一次接收数据
{
while(Remote_RxData.Remote_R_RL!=1024 || Remote_RxData.Remote_R_UD!=1024 || Remote_RxData.Remote_L_RL!=1024 || Remote_RxData.Remote_L_UD!=1024)//数据错误
Warming_RemoteDataERROR();//数据错误报错,等待看门狗复位
Remote_StartFlag=2;
Warming_LEDClean();
}
Remote_Status=1;//遥控器已连接
}
TIM_Cmd(TIM7,ENABLE);//开启定时
USART_ClearITPendingBit(USART3,USART_IT_RXNE);//清除接收中断标志位
}
/*
*函数简介:TIM7定时器更新中断函数
*参数说明:无
*返回类型:无
*备注:进入中断即遥控器未连接
*/
void TIM7_IRQHandler(void)
{
if(TIM_GetITStatus(TIM7,TIM_IT_Update)==SET)//检测TIM2更新
{
TIM_ClearITPendingBit(TIM7,TIM_IT_Update);//清除标志位
Warming_RemoteNoCheck();//遥控器未连接报警
RefereeSystem_Status=0;//裁判系统(图传链路)连接状态变为未连接
Remote_Status=0;//遥控器连接状态变为未连接
Remote_StartFlag=1;//遥控器处于准备启动阶段
}
}

View File

@@ -0,0 +1,51 @@
#ifndef __REMOTE_H
#define __REMOTE_H
typedef struct
{
uint16_t Remote_R_RL;//通道0-右摇杆左右(右为大),范围364(最左端)~1684(最右端),默认值1024(中间)
uint16_t Remote_R_UD;//通道1-右摇杆上下(上为大),范围364(最下端)~1684(最上端),默认值1024(中间)
uint16_t Remote_L_RL;//通道2-左摇杆左右(右为大),范围364(最左端)~1684(最右端),默认值1024(中间)
uint16_t Remote_L_UD;//通道3-左摇杆上下(上为大),范围364(最下端)~1684(最上端),默认值1024(中间)
uint8_t Remote_LS;//S1-左侧拨动开关,范围1~3,上为1,下为2,中间为3
uint8_t Remote_RS;//S2-右侧拨动开关,范围1~3,上为1,下为2,中间为3
int16_t Remote_Mouse_RL;//鼠标X轴-鼠标左右速度,范围-32768~32767,向右为正,向左为负,静止值为0
int16_t Remote_Mouse_DU;//鼠标Y轴-鼠标前后速度,范围-32768~32767,向后为正,向前为负,静止值为0
int16_t Remote_Mouse_Wheel;//鼠标Z轴-鼠标滚轮速度,范围-32768~32767,向前为正,向后为负,静止值为0
uint8_t Remote_Mouse_KeyL;//鼠标左键,按下为1,未按下为0
uint8_t Remote_Mouse_KeyR;//鼠标右键,按下为1,未按下为0
uint8_t Remote_Key_W;//键盘W键,按下为1,未按下为0
uint8_t Remote_Key_S;//键盘S键,按下为1,未按下为0
uint8_t Remote_Key_A;//键盘A键,按下为1,未按下为0
uint8_t Remote_Key_D;//键盘D键,按下为1,未按下为0
uint8_t Remote_Key_Q;//键盘Q键,按下为1,未按下为0
uint8_t Remote_Key_E;//键盘E键,按下为1,未按下为0
uint8_t Remote_Key_Shift;//键盘Shift键,按下为1,未按下为0
uint8_t Remote_Key_Ctrl;//键盘Ctrl键,按下为1,未按下为0
uint8_t Remote_Mouse_KeyLastR;//上一次鼠标右键
uint8_t Remote_KeyLast_Q;//上一次键盘Q键
uint8_t Remote_KeyLast_E;//上一次键盘E键
uint8_t Remote_KeyLast_Shift;//上一次键盘Shift键
uint8_t Remote_KeyLast_Ctrl;//上一次键盘Ctrl键
uint8_t Remote_Mouse_KeyPushR;//按下鼠标右键,按下瞬间为1,其他为0
uint8_t Remote_KeyPush_Q;//按下键盘Q键,按下时0,1切换
uint8_t Remote_KeyPush_E;//按下键盘E键,按下时0,1切换
uint8_t Remote_KeyPush_Shift;//按下键盘Shift键,按下时0,1切换
uint8_t Remote_KeyPush_Ctrl;//按下键盘Ctrl键,按下时0,1切换
int16_t Remote_ThumbWheel;//保留字段-遥控器拨轮,范围-3278(最上端)~1684(最下端),默认值1024
}Remote_Data;//遥控器接收结构体
extern Remote_Data Remote_RxData;//遥控器接收数据
extern uint8_t Remote_Status;//遥控器连接状态,默认未连接(0)
extern uint8_t Remote_StartFlag;//遥控器启动标志位,0-未在启动阶段,1-准备启动,2-第一次接收到数据
void Remote_Init(void);//遥控器初始化
void Remote_ON(void);//遥控器开启
void Remote_OFF(void);//遥控器关闭
#endif