STM32F1系列单片机通过串口与JY901传感器通信

STM32F1系列单片机通过串口与JY901传感器通信,主要任务是正确解析其输出的数据帧

硬件连接与JY901数据协议

确保JY901模块与STM32F1开发板接线正确是其正常通信的基础。JY901模块的串口通常是TTL电平

JY901模块 STM32F1xx 说明
VCC 3.3V 或 5V 根据模块要求
GND GND 共地
TX 任意USART的RX引脚 (如PA3/USART2_RX) JY901发送,STM32接收
RX 任意USART的TX引脚 (如PA2/USART2_TX) 如需向JY901发送配置指令才连接

JY901数据帧格式是关键,其主动输出模式下的数据帧格式如下:

字节偏移 内容 说明
0 0x55 帧头
1 0x5X 数据类型标识,X代表不同传感器数据
2-9 数据内容 具体数据(小端模式存储)
10 0x5X 此字节有时在示例代码中未被明确提及,通常关注前11字节

常见的数据类型标识包括:0x50(时间)、0x51(加速度)、0x52(角速度)、0x53(角度)、0x54(磁场)等。

软件实现:STM32F1读取JY901数据

利用STM32标准外设库,通过串口读取并解析JY901数据的基本步骤和代码示例。

1. 串口初始化

首先需要初始化一个USART,以下以USART2为例。

#include "stm32f10x.h"
#include <stdio.h>

// 定义接收缓冲区及相关变量
#define RX_BUFFER_SIZE 256
uint8_t ucRxBuffer[RX_BUFFER_SIZE];
uint32_t uiRxCnt = 0; 

// 定义用于存储解析后数据的结构体
// 注意:根据JY901协议,数据通常为小端模式
typedef struct {
    short a[3];
    short T;
} SAcc;
typedef struct {
    short w[3];
    short T;
} SGyro;
typedef struct {
    short Angle[3];
    short T;
} SAngle;
// ... 可根据需要定义其他数据结构,如磁场、角度等

SAcc     stcAcc;
SGyro    stcGyro;
SAngle   stcAngle;

void USART2_Init(uint32_t baudrate) {
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    // 使能时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

    // 配置USART2 Tx (PA.2) 为复用推挽输出
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置USART2 Rx (PA.3) 为浮空输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // USART 参数配置
    USART_InitStructure.USART_BaudRate = baudrate; // 常用9600或115200
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART2, &USART_InitStructure);

    // 使能USART2接收中断
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);

    // 配置NVIC
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // 使能串口
    USART_Cmd(USART2, ENABLE);
}

2. 串口中断服务函数与数据帧解析

在中断服务函数中接收数据,并调用数据处理函数。

// 在stm32f10x_it.c中
void USART2_IRQHandler(void) {
    if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) {
        // 读取接收到的数据
        uint8_t ucData = USART_ReceiveData(USART2);
        // 调用数据处理函数
        CopeSerial2Data(ucData);
        // 可选:将接收到的字节原样发送回串口助手,用于调试
        // USART_SendData(USART2, ucData); 
    }
}

数据处理函数 CopeSerial2Data 是核心,负责识别并解析完整的数据帧。

// 数据处理函数
void CopeSerial2Data(unsigned char ucData) {
    // 静态变量,用于在函数调用间保持值
    static unsigned char ucRxBuffer[11]; // 存放一帧数据
    static unsigned char ucRxCnt = 0;     // 接收计数

    // 将数据存入缓冲区
    ucRxBuffer[ucRxCnt++] = ucData;

    // 检查帧头:第一个字节必须是0x55
    if (ucRxBuffer[0] != 0x55) {
        ucRxCnt = 0;
        return;
    }

    // 检查是否接收够一帧数据(11字节)
    if (ucRxCnt < 11) {
        return; // 数据不够,继续等待
    } else {
        // 根据第二个字节(数据类型标识)进行数据解析
        switch(ucRxBuffer[1]) {
            case 0x51:
                // 解析加速度数据,注意数据在小端模式下通过memcpy拷贝到结构体
                memcpy(&stcAcc, &ucRxBuffer[2], 8); 
                // 数据转换示例(根据模块手册和量程)
                // stcAcc.a[0] = (short)(ucRxBuffer[3]<<8 | ucRxBuffer[2]); // 也可用此方式合并字节
                break;
            case 0x52:
                // 解析角速度数据
                memcpy(&stcGyro, &ucRxBuffer[2], 8);
                break;
            case 0x53:
                // 解析角度数据
                memcpy(&stcAngle, &ucRxBuffer[2], 8);
                break;
            // 可根据需要添加其他数据类型 case 0x54: 等
            default:
                break;
        }
        // 处理完一帧,重置计数,准备接收下一帧
        ucRxCnt = 0;
    }
}

3. 主函数初始化与数据使用

在主函数中初始化串口,然后在循环中处理或发送解析后的数据。

#include "stm32f10x.h"
#include "usart2.h" // 假设串口初始化代码放在这个头文件

int main(void) {
    char str[50]; // 用于格式化输出
    // 系统时钟等初始化
    SystemInit();
    // 初始化串口2,波特率设置为9600或115200
    USART2_Init(9600);

    while(1) {
        // 示例:通过其他串口(如USART1)发送角度数据到上位机
        sprintf(str, "Angle: %.3f %.3f %.3f\r\n", 
                        (float)stcAngle.Angle[0]/32768*180,  // 转换为度,假设量程±180°
                        (float)stcAngle.Angle[1]/32768*180,
                        (float)stcAngle.Angle[2]/32768*180);
        // 假设UART1_SendString函数已实现,用于向串口助手发送数据
        UART1_SendString(str);

        // 延时,控制数据发送频率
        Delay_ms(500);
    }
}

参考代码 Jy901通过串口连接stm32f1x的源代码 www.3dddown.com/cna/71613.html

关键点与调试

  1. 数据解析与转换:从缓冲区提取的原始数据是字节,需按小端模式(低位字节在前)组合成shortint型,再根据模块资料给出的量程和分辨率转换为有物理意义的量。
  2. 校验和:上述示例代码为了简洁,省略了校验和验证。在实际应用中,为增强通信可靠性,建议根据JY901的通信协议加上校验和检查。
  3. 连接与配置
    • 确保JY901模块的VCC和GND连接正确稳定。
    • 确认STM32的串口波特率与JY901模块的输出波特率一致(常见9600或115200)。
    • JY901模块通常支持主动输出模式,可能需要通过上位机配置其串口输出参数和数据类型。
  4. 调试技巧
    • 可以先将JY901的TX引脚连接到USB-TTL,直接接电脑,用串口助手(如sscom)查看其原始数据输出,确认模块工作正常和数据格式。
    • 在STM32代码中,可以先将接收到的每一个字节通过另一个串口原样发送给PC,模拟"串口透传",帮助判断STM32是否正常接收。
posted @ 2025-12-12 10:36  躲雨小伙  阅读(3)  评论(0)    收藏  举报