STM32获取GY-25A倾角传感器串口输出数据
GY-25A模块是新型的倾角传感器模块,具有X和Y两轴模拟角度输出和串口角度输出的功能。这里介绍STM32获取GY-25A串口输出的角度数据。
串口输出格式介绍
GY-25A默认以9600波特率输出TTL电平的串口数据,其一帧数据输出4种数据,共8个字节,如下所示:
其中横滚角对应模拟输出的X轴,俯仰角对应模拟输出的Y轴。
串口接收的数据帧里,前4个字节固定为16进制A4 03 14 08,其中第一个字节A4是GY-25A的访问地址, 第二个字节此次输出对应的指令,这里03是连续输出的指令,第三个指令是输出的寄存器收地址,14即为ROLL_H字节的地址,第四个指令是后面输出的字节数,08表示输出8个寄存器字节数据,也就是从ROLL_H输出到TEMP_L,在数据字节输出后还会输出1个字节,为前面输出的字节的累加和的低8位。如一帧数据为:A4 03 14 08 BB 36 02 01 FF 7E 0D 92 D3 。
GY-25A输出的这部分数据,采用放大100倍和补码方式表示。如16进制数据为02 01, 02是高字节,最高位为0,因此为正数,不做补码处理。02 01对应十进制数513, 将513除以100得到5.13,即当前的角度为5.13度。如16进制数据为BB 36,最高位为1,因此为负数,进行补码处理,得到其代表的负数为-17610,将-17610除以100得到-176.10,即当前的角度为-176.10度。
横滚角翻转特性
芯片的横滚角度变化关系如下面所示:
需要注意,在芯片朝下模块与水平面平行时,芯片X轴微动,会有180度输出和-180度输出的跳变!
以上为横滚角X轴的输出特性。
俯仰角翻转特性
芯片的俯仰角度变化关系如下面所示:
由横滚角和俯仰角的输出特性可以看出,横滚角是360度分辨特性,俯仰角是180度分辨特性,与名称来历相符。
另外两个输出数据即航向角和温度,数据输出格式也是一样,这里不做介绍。也可以通过串口指令,控制GY-25A的工作方式,将连续输出模式改为查询模式,可以查看数据手册进行操作。
STM32串口程序
这里以STM32F401CCU6开发板介绍串口获取GY-25A默认输出数据的方式。主要的逻辑设计为:
- 通过中断接收四个字节,并判断是否为帧头A4 03 14 08,如果不是,重新接收4个字节,重新判断帧头。
- 通过中断接收四个字节,并判断是否为帧头A4 03 14 08,如果是,通过轮询方式接收9个字节,前8个字节为有效数据,最后一个字节为校验字节。收完9个字节后,重新启动4个字节的中断接收。
如果一开始接收的帧头错误,最多滑动3帧后就可以接收到正确的帧头,这一点可以自己分析。
通过STM32CUBEIDE建立HAL库工程做介绍:
首先建立工程并配置时钟,普通时序,采用内部时钟即可。
设置UART串口:
然后生成工程初始代码:
编写代码实现数据接收:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart1;
/* USER CODE BEGIN PV */
uint8_t frame_head[4];
uint8_t frame_data[9];
uint8_t d1[2];
uint8_t d2[2];
uint8_t rd_flag = 0;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
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();
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart1, frame_head, 4);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(rd_flag==1)
{
rd_flag = 0;
HAL_UART_Receive(&huart1, frame_data, 9, 5000);
d1[0]=frame_data[0];
d1[1]=frame_data[1];
d2[0]=frame_data[2];
d2[1]=frame_data[3];
//do something you want
HAL_UART_Receive_IT(&huart1, frame_head, 4);
}
HAL_Delay(1);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 16;
RCC_OscInitStruct.PLL.PLLN = 168;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief USART1 Initialization Function
* @param None
* @retval None
*/
static void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
}
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart==&huart1)
{
if ((frame_head[0]==0xA4)&&(frame_head[1]==0x03)&&(frame_head[2]==0x14)&&(frame_head[3]==0x08))
{
rd_flag = 1;
}
else
{
HAL_UART_Receive_IT(&huart1, frame_head, 4);
}
}
}
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
–End–
版权声明:本文为CSDN博主「PegasusYu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/hwytree/article/details/122622720
STM32获取GY-25A倾角传感器串口输出数据
GY-25A模块是新型的倾角传感器模块,具有X和Y两轴模拟角度输出和串口角度输出的功能。这里介绍STM32获取GY-25A串口输出的角度数据。
串口输出格式介绍
GY-25A默认以9600波特率输出TTL电平的串口数据,其一帧数据输出4种数据,共8个字节,如下所示:
其中横滚角对应模拟输出的X轴,俯仰角对应模拟输出的Y轴。
串口接收的数据帧里,前4个字节固定为16进制A4 03 14 08,其中第一个字节A4是GY-25A的访问地址, 第二个字节此次输出对应的指令,这里03是连续输出的指令,第三个指令是输出的寄存器收地址,14即为ROLL_H字节的地址,第四个指令是后面输出的字节数,08表示输出8个寄存器字节数据,也就是从ROLL_H输出到TEMP_L,在数据字节输出后还会输出1个字节,为前面输出的字节的累加和的低8位。如一帧数据为:A4 03 14 08 BB 36 02 01 FF 7E 0D 92 D3 。
GY-25A输出的这部分数据,采用放大100倍和补码方式表示。如16进制数据为02 01, 02是高字节,最高位为0,因此为正数,不做补码处理。02 01对应十进制数513, 将513除以100得到5.13,即当前的角度为5.13度。如16进制数据为BB 36,最高位为1,因此为负数,进行补码处理,得到其代表的负数为-17610,将-17610除以100得到-176.10,即当前的角度为-176.10度。
横滚角翻转特性
芯片的横滚角度变化关系如下面所示:
需要注意,在芯片朝下模块与水平面平行时,芯片X轴微动,会有180度输出和-180度输出的跳变!
以上为横滚角X轴的输出特性。
俯仰角翻转特性
芯片的俯仰角度变化关系如下面所示:
由横滚角和俯仰角的输出特性可以看出,横滚角是360度分辨特性,俯仰角是180度分辨特性,与名称来历相符。
另外两个输出数据即航向角和温度,数据输出格式也是一样,这里不做介绍。也可以通过串口指令,控制GY-25A的工作方式,将连续输出模式改为查询模式,可以查看数据手册进行操作。
STM32串口程序
这里以STM32F401CCU6开发板介绍串口获取GY-25A默认输出数据的方式。主要的逻辑设计为:
- 通过中断接收四个字节,并判断是否为帧头A4 03 14 08,如果不是,重新接收4个字节,重新判断帧头。
- 通过中断接收四个字节,并判断是否为帧头A4 03 14 08,如果是,通过轮询方式接收9个字节,前8个字节为有效数据,最后一个字节为校验字节。收完9个字节后,重新启动4个字节的中断接收。
如果一开始接收的帧头错误,最多滑动3帧后就可以接收到正确的帧头,这一点可以自己分析。
通过STM32CUBEIDE建立HAL库工程做介绍:
首先建立工程并配置时钟,普通时序,采用内部时钟即可。
设置UART串口:
然后生成工程初始代码:
编写代码实现数据接收:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart1;
/* USER CODE BEGIN PV */
uint8_t frame_head[4];
uint8_t frame_data[9];
uint8_t d1[2];
uint8_t d2[2];
uint8_t rd_flag = 0;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
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();
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart1, frame_head, 4);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(rd_flag==1)
{
rd_flag = 0;
HAL_UART_Receive(&huart1, frame_data, 9, 5000);
d1[0]=frame_data[0];
d1[1]=frame_data[1];
d2[0]=frame_data[2];
d2[1]=frame_data[3];
//do something you want
HAL_UART_Receive_IT(&huart1, frame_head, 4);
}
HAL_Delay(1);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 16;
RCC_OscInitStruct.PLL.PLLN = 168;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief USART1 Initialization Function
* @param None
* @retval None
*/
static void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
}
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart==&huart1)
{
if ((frame_head[0]==0xA4)&&(frame_head[1]==0x03)&&(frame_head[2]==0x14)&&(frame_head[3]==0x08))
{
rd_flag = 1;
}
else
{
HAL_UART_Receive_IT(&huart1, frame_head, 4);
}
}
}
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
–End–
版权声明:本文为CSDN博主「PegasusYu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/hwytree/article/details/122622720
暂无评论