基于CUBEMX和STM32C8T6的同轴麦轮小车制作(二)——HAL库接受jy61p陀螺仪数据,并解决数据溢出卡死问题
本文利用STM32C8T6中的串口1于JY61P实时通信,并用串口2将其角度打印出来,期间遇到了串口数据溢出卡死的问题,在编写ORE错误回调函数后得到有效解决,其分为CUBEMX基本配置、函数编写、效果展示3个部分。
一、CUBEMX基本配置
1.配置串口1、2,此处要注意串口1的波特率要和JY61P的一致(默认是9600,具体可以在上位机中调节),开启串口1的接收中断。
2.配置时钟,Debug
二、程序编写
(1)在main头文件中定义及声明函数:
struct SAcc
{
short a[3];
short T;
};
struct SGyro
{
short w[3];
short T;
};
struct SAngle
{
short Angle[3];
short T;
};
void CopeSerial2Data(unsigned char ucData);
void sendcmd(uint8_t data[3]);
(2)在main中定义:
#include <string.h>
#include <stdio.h>
uint8_t rx_buff1;
struct SAcc ACC;
struct SAngle Angle;
struct SGyro Gyro;
char YAWCMD[3] = {0XFF,0XAA,0X52};
char ACCCMD[3] = {0XFF,0XAA,0X67};
char SLEEPCMD[3] = {0XFF,0XAA,0X60};
char UARTMODECMD[3] = {0XFF,0XAA,0X61};
char IICMODECMD[3] = {0XFF,0XAA,0X62};
float angle_x;
float angle_y;
float angle_z;
float acc_x;
float acc_y;
float acc_z;
float gyro_x;
float gyro_y;
float gyro_z;
(3)串口回调函数:
void HAL_UART_RxCpltCallback()
{
CopeSerial2Data(rx_buff1);
HAL_UART_Receive_IT(&huart1,&rx_buff1,1);
}
(4)数据处理函数:
void CopeSerial2Data(unsigned char ucData)
{
static unsigned char ucRxBuffer[250];
static unsigned char ucRxCnt = 0;
ucRxBuffer[ucRxCnt++]=ucData; //将收到的数据存入缓冲区中
if (ucRxBuffer[0]!=0x55) //数据头不对,则重新开始寻找0x55数据头
{
ucRxCnt=0;
return;
}
if (ucRxCnt<11) {return;}//数据不满11个,则返回
else
{
switch(ucRxBuffer[1])//判断数据是哪种数据,然后将其拷贝到对应的结构体中,有些数据包需要通过上位机打开对应的输出后,才能接收到这个数据包的数据
{
//memcpy为编译器自带的内存拷贝函数,需引用"string.h",将接收缓冲区的字符拷贝到数据结构体里面,从而实现数据的解析。
case 0x51: memcpy(&ACC,&ucRxBuffer[2],8);break;
case 0x52: memcpy(&Gyro,&ucRxBuffer[2],8);break;
case 0x53: memcpy(&Angle,&ucRxBuffer[2],8);break;
}
ucRxCnt=0;//清空缓存区
}
}
(5)串口1发送数据:
void sendcmd(uint8_t data[3])
{
static uint8_t tx_buff;
for(int i=0;i<3;i++)
{
tx_buff = data[i];
HAL_UART_Transmit(&huart1,&tx_buff,1,0Xff);
}
}
(6)重定义printf:
int fputc(int ch,FILE *f)
{
uint8_t temp[1]={ch};
HAL_UART_Transmit(&huart2,temp,1,0xff);
}
(7)ORE错误回调函数:
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
if(huart->ErrorCode&HAL_UART_ERROR_ORE)
{
__HAL_UART_CLEAR_OREFLAG(huart);
HAL_UART_Receive_IT(&huart1,&rx_buff1,1);
}
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_UART_ErrorCallback can be implemented in the user file.
*/
}
(8)数据处理
void get_data()
{
acc_x = (float)ACC.a[0]/32768*16;
acc_y = (float)ACC.a[1]/32768*16;
acc_z = (float)ACC.a[2]/32768*16;
gyro_x = (float)Gyro.w[0]/32768*2000;
gyro_y = (float)Gyro.w[1]/32768*2000;
gyro_z = (float)Gyro.w[2]/32768*2000;
angle_x = (float)Angle.Angle[0]/32768*180;
angle_y = (float)Angle.Angle[1]/32768*180;
angle_z = (float)Angle.Angle[2]/32768*180;
}
(9)主函数:
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart1,&rx_buff1,1);
HAL_Delay(1000);
HAL_Delay(1000);
sendcmd(ACCCMD1);
sendcmd(YAWCMD1);
int count = 0;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
count++;
HAL_Delay(20);
get_data();
if(count == 50)
{
printf("angle_x = %f\n",angle_x);
printf("angle_y = %f\n",angle_y);
printf("angle_z = %f\n",angle_z);
count = 0;
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
三、效果展示