基于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, &current_frame))
    {
      // 数据处理
      Process_JY901_Data(&current_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

七、常见问题解决

  1. 数据乱码 检查波特率是否匹配(使用逻辑分析仪验证) 确认TX/RX引脚交叉连接
  2. 校验失败 验证数据帧长度字段是否正确 检查数据解析顺序是否与协议一致
  3. 动态漂移 实现温度补偿算法 定期执行零偏校准
posted @ 2025-10-21 09:09  csoe9999  阅读(15)  评论(0)    收藏  举报