【星云 Orbit • STM32F4】08. 用判断数据头来接收据的串口通用程序框架

【星云 Orbit • STM32F4】08. 用判断数据头来接收据的串口通用程序框架

1. 引言

本教程旨在帮助嵌入式开发小白从零开始,学习如何在STM32F407微控制器上实现一个基于串口的数据接收程序。该程序能够通过判断数据头来接收一串数据,并将其存储到缓冲区中以供后续处理。教程内容涵盖基础知识、配置步骤、HAL库函数详解,并提供配套例程和代码注释。

2. 硬件准备
  • STM32F407开发板
  • 串口调试工具(如串口助手)
3. 软件准备
  • Keil MDK-ARM开发环境
  • STM32F407标准库
4. 知识储备

在开始编程之前,需要了解以下基础知识:

  • STM32F407的串口(USART)外设
  • 基本的串口通信知识(波特率、数据位、停止位、校验位)
  • C语言编程基础
  • 中断服务函数的基本概念
5. 程序设计
5.1 程序功能概述

程序的主要功能包括:

  • 初始化STM32F407的串口外设
  • 通过中断方式接收串口数据
  • 检测数据头(特定字节序列)
  • 存储接收到的数据到缓冲区
  • 提供数据处理接口
5.2 程序模块划分

程序分为以下几个模块:

  • main.c:主程序文件,负责初始化和程序运行逻辑
  • usart.husart.c:串口驱动文件,负责串口的初始化和数据收发
  • data_receiver.hdata_receiver.c:数据接收模块,负责数据头检测和数据存储
5.3 程序流程图
流程图说明:
  1. 系统初始化:程序开始时进行系统初始化,包括时钟配置、GPIO配置等。
  2. 串口初始化:配置串口参数(如波特率、数据位、停止位等),使串口准备好接收数据。
  3. 等待中断触发:程序进入等待状态,等待串口接收到数据后触发中断。
  4. 接收数据:中断触发后,程序从串口接收数据。
  5. 检测数据头:检查接收到的数据是否包含有效的数据头,以确保数据的完整性。
  6. 存储数据:将接收到的有效数据存储到内存或外部存储器中。
  7. 数据处理:对存储的数据进行进一步的处理,如解析、计算等。

这个流程图清晰地展示了从系统初始化到数据处理的完整流程,帮助理解基于STM32F407的串口数据接收程序的工作原理。

6. 代码实现
6.1 串口初始化 (usart.c)
c 复制代码
#include "usart.h"

void USART_Init(uint32_t baudrate) {
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    // 使能GPIO和USART时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

    // 配置GPIO引脚
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置USART
    USART_InitStructure.USART_BaudRate = baudrate;
    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(USART1, &USART_InitStructure);

    // 使能USART
    USART_Cmd(USART1, ENABLE);

    // 配置 NVIC 优先级
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}
6.2 数据接收模块 (data_receiver.c)
c 复制代码
#include "data_receiver.h"

#define DATA_BUFFER_SIZE 100
#define HEADER_SIZE 3
#define HEADER_1 0xEB
#define HEADER_2 0x00
#define HEADER_3 0x55

static uint8_t data_buffer[DATA_BUFFER_SIZE];
static uint16_t buffer_index = 0;
static uint8_t header_received = 0;

void DataReceiver_Init(void) {
    buffer_index = 0;
    header_received = 0;
}

void USART1_IRQHandler(void) {
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
        uint8_t received_data = USART_ReceiveData(USART1);

        if (header_received < HEADER_SIZE) {
            if (received_data == header[header_received]) {
                header_received++;
                if (header_received == HEADER_SIZE) {
                    // 数据头检测完成,开始接收数据
                    buffer_index = 0;
                }
            } else {
                header_received = 0;
            }
        } else {
            if (buffer_index < DATA_BUFFER_SIZE) {
                data_buffer[buffer_index++] = received_data;
            }
        }
    }
}

uint8_t* GetDataBuffer(void) {
    return data_buffer;
}

uint16_t GetBufferDataLength(void) {
    return buffer_index;
}
6.3 主程序 (main.c)
c 复制代码
#include "usart.h"
#include "data_receiver.h"

int main(void) {
    // 系统时钟配置
    SystemClock_Config();

    // 初始化串口
    USART_Init(9600);

    // 初始化数据接收模块
    DataReceiver_Init();

    while (1) {
        // 主循环可以添加其他任务
    }
}
7. 使用示例
7.1 初始化串口

main.c 中调用 USART_Init 函数,配置串口参数:

c 复制代码
USART_Init(9600); // 配置波特率为9600
7.2 初始化数据接收模块

调用 DataReceiver_Init 函数,初始化数据接收模块:

c 复制代码
DataReceiver_Init();
7.3 数据接收与处理

在中断服务函数 USART1_IRQHandler 中,接收到的数据会被存储到 data_buffer 中。主程序可以通过以下函数获取接收到的数据:

c 复制代码
uint8_t* data = GetDataBuffer();
uint16_t data_length = GetBufferDataLength();
8. 串口收发状态图

以下是基于STM32F407的串口数据接收程序的状态图,展示了串口收发的状态转换过程:

串口数据接收程序的状态图

9. 总结

通过本教程,读者可以掌握如何在STM32F407上实现一个基于串口的数据接收程序。程序通过检测数据头来接收数据,并将其存储到缓冲区中以供后续处理。教程内容从零开始,详细讲解了串口配置、数据接收、中断处理等关键步骤,并提供了完整的代码示例和注释,帮助读者快速上手。

相关推荐
国科安芯13 分钟前
空间机电一体化:AS32S601型抗辐射MCU在卫星推进与执行机构控制中的关键技术研究
单片机·嵌入式硬件·物联网·机器人·云计算
国科安芯24 分钟前
AS32S601型抗辐射MCU在分布式太空算力架构中的技术演进与应用前景
人工智能·分布式·单片机·嵌入式硬件·架构·边缘计算
国科安芯32 分钟前
在轨能源中枢:AS32S601型抗辐射MCU在卫星电源管理与配电系统中的控制策略研究
嵌入式硬件·架构·能源·risc-v·sps·电源管理·卫星
纯音乐sjc36 分钟前
ARM Linux 嵌入式中断全流程解析:从 GPIO 到 GIC 架构实战
单片机·嵌入式硬件
雯宝39 分钟前
|____1.4外部中断/看门狗/定时器/PWM/RTC/待机唤醒/ADC/DAC/IIC/SPI/485/CAN
单片机
sramdram16 小时前
基于32位微控制器的FOC汽车水泵方案
单片机·嵌入式硬件·汽车·微控制器·32位微控制器
十月的皮皮18 小时前
stm20260720-从新手 C 到量产 STM32 工程:程序设计推导指南
c语言·开发语言·stm32·stm32cubemx·hal库
开发笔记-阿牛18 小时前
解析一款有意思的产品||CK6159A语音芯片设计的儿童专注力训练机-舒尔特玩具
stm32·单片机·嵌入式硬件·音频
残影飞雪20 小时前
ESP32-C5下载烧录固件失败报错的原因
单片机·嵌入式硬件
搞全栈小苏21 小时前
SIMetrix_simplis8.4安装教程——附安装包
stm32·单片机·嵌入式硬件·电力电子