基于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 */
}
三、效果展示
 

