基于STM32F1x系列与JY901模块串口通信
一、硬件
| JY901引脚 | STM32F103引脚 | 功能说明 |
|---|---|---|
| VCC | 3.3V | 电源供电 |
| GND | GND | 地线 |
| TX | PA10 (USART1_RX) | 接收数据 |
| RX | PA9 (USART1_TX) | 发送数据 |
二、STM32串口配置代码(HAL库)
// usart.c
#include "stm32f1xx_hal.h"
UART_HandleTypeDef huart1;
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200; // 默认波特率
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();
}
}
// 重定向printf函数
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, HAL_MAX_DELAY);
return ch;
}
三、数据接收与解析
1. 数据结构定义
typedef struct {
uint8_t header[2]; // 起始符 0x55 0xAA
uint8_t addr; // 地址位
uint8_t ctrl; // 控制码
uint16_t length; // 数据长度
uint8_t data[64]; // 数据域
uint8_t checksum; // 校验和
} JY901_Frame;
typedef struct {
float accel[3]; // 加速度 (g)
float gyro[3]; // 角速度 (°/s)
float angle[3]; // 角度 (°)
float mag[3]; // 磁场 (mG)
float pressure; // 气压 (hPa)
float altitude; // 高度 (m)
} JY901_Data;
2. DMA接收配置
#define RX_BUFFER_SIZE 256
uint8_t rx_buffer[RX_BUFFER_SIZE];
JY901_Frame current_frame;
void MX_DMA_Init(void)
{
__HAL_RCC_DMA1_CLK_ENABLE();
DMA_HandleTypeDef hdma_usart1_rx;
hdma_usart1_rx.Instance = DMA1_Channel5;
hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart1_rx.Init.Mode = DMA_CIRCULAR;
hdma_usart1_rx.Init.Priority = DMA_PRIORITY_HIGH;
if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(&huart1, hdmarx, hdma_usart1_rx);
HAL_UART_Receive_DMA(&huart1, rx_buffer, RX_BUFFER_SIZE);
}
四、数据解析核心代码
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart1);
if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
// 计算接收数据长度
uint16_t len = RX_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(huart1.hdmarx);
// 解析数据帧
if(Parse_Frame(rx_buffer, len, ¤t_frame))
{
// 数据处理
Process_JY901_Data(¤t_frame, &sensor_data);
}
}
}
// 数据帧解析函数
bool Parse_Frame(uint8_t *buffer, uint16_t len, JY901_Frame *frame)
{
if(len < 10) return false; // 最小帧长度
// 检查起始符
if(buffer[0] != 0x55 || buffer[1] != 0xAA) return false;
frame->addr = buffer[2];
frame->ctrl = buffer[3];
frame->length = (buffer[4] << 8) | buffer[5];
// 检查数据长度合法性
if(frame->length > RX_BUFFER_SIZE - 8) return false;
// 复制数据域
memcpy(frame->data, buffer+6, frame->length);
// 校验和验证
uint8_t checksum = 0;
for(int i=2; i<6+frame->length; i++) checksum += buffer[i];
if(checksum != buffer[6+frame->length]) return false;
return true;
}
五、数据处理与输出
void Process_JY901_Data(JY901_Frame *frame, JY901_Data *data)
{
static float accel_scale = 16.0f/32768.0f; // ±2g量程
static float gyro_scale = 2000.0f/32768.0f; // ±2000°/s量程
// 解析加速度
data->accel[0] = (frame->data[0] | (frame->data[1]<<8)) * accel_scale;
data->accel[1] = (frame->data[2] | (frame->data[3]<<8)) * accel_scale;
data->accel[2] = (frame->data[4] | (frame->data[5]<<8)) * accel_scale;
// 解析角速度
data->gyro[0] = (frame->data[6] | (frame->data[7]<<8)) * gyro_scale;
data->gyro[1] = (frame->data[8] | (frame->data[9]<<8)) * gyro_scale;
data->gyro[2] = (frame->data[10]| (frame->data[11]<<8)) * gyro_scale;
// 解析角度(示例:Roll/Pitch/Yaw)
data->angle[0] = (frame->data[12] | (frame->data[13]<<8)) / 100.0f; // Roll
data->angle[1] = (frame->data[14] | (frame->data[15]<<8)) / 100.0f; // Pitch
data->angle[2] = (frame->data[16] | (frame->data[17]<<8)) / 100.0f; // Yaw
}
六、主程序流程
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_USART1_UART_Init();
MX_DMA_Init();
printf("JY901 UART Test Start...\r\n");
while(1)
{
// 主循环处理其他任务
HAL_Delay(10);
}
}
参考代码 Jy901通过串口连接stm32f1x的源代码 www.youwenfan.com/contentcnj/71613.html
七、常见问题解决
- 数据乱码 检查波特率是否匹配(使用逻辑分析仪验证) 确认TX/RX引脚交叉连接
- 校验失败 验证数据帧长度字段是否正确 检查数据解析顺序是否与协议一致
- 动态漂移 实现温度补偿算法 定期执行零偏校准
浙公网安备 33010602011771号