【嵌入式开发学习】第7天:STM32 串口通信(开发板与电脑双向交互)

STM32串口双向通信实战

核心目标:掌握 UART 串口通信原理,用 HAL 库实现 “开发板→电脑” 数据发送(模拟传感器数据上报)、“电脑→开发板” 指令接收(控制 LED),结合定时器实现定时发送,巩固非阻塞逻辑 —— 串口是嵌入式调试、数据传输的 “必备技能”,后续传感器数据上传、上位机控制都依赖它。

一、串口通信原理:嵌入式的 “双向数据线”(30 分钟)

串口(UART/USART)是 STM32 与外部设备(电脑、传感器、蓝牙模块)通信的常用接口,核心是 “异步通信”(无需时钟线,仅用 Tx 发送线、Rx 接收线),简单可靠。

1. 核心概念(新手必懂)
  • UART(通用异步收发传输器):STM32 的基础串口外设,支持双向通信;
  • 波特率:通信速率(常用 9600、115200bps,即每秒传输 9600/115200 位),双方必须一致;
  • 数据格式:默认 “8 位数据位 + 1 位停止位 + 无校验位”(嵌入式最常用,CubeIDE 默认配置);
  • 引脚对应(STM32F103C8T6):USART1 的 Tx=PA9,Rx=PA10(需在 CubeIDE 中配置为串口功能)。
2. 嵌入式场景用途
  • 调试:开发板通过串口向电脑发送调试信息(如传感器数据、程序运行状态);
  • 数据传输:接收电脑指令(如 “点亮 LED”“开始采集”),或向电脑上传传感器数据;
  • 外设交互:与蓝牙、WiFi 模块通信(如通过蓝牙将温度数据发送到手机)。
3. HAL 库串口核心函数(重点记)
  • 阻塞发送:HAL_UART_Transmit(&huart1, 数据缓冲区, 数据长度, 超时时间);(发送时 CPU 等待,适合简单场景);
  • 中断接收:HAL_UART_Receive_IT(&huart1, 接收缓冲区, 接收长度);(接收时不阻塞 CPU,通过中断回调处理数据,推荐用);
  • 中断回调:HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);(接收完成后自动调用,处理接收到的指令)。

二、实操 1:开发板→电脑,发送温度数据(40 分钟)

目标:开发板模拟温度传感器采集,通过 USART1 向电脑串口助手发送 “原始数据 + 校准后温度”,每秒发送一次(用定时器定时,巩固非阻塞)。

步骤 1:CubeIDE 配置串口 + 定时器
  1. 新建工程 “UART_Send_Data”,选择 STM32F103C8T6;
  2. 配置串口(USART1):
    • 左侧 “Connectivity→USART1”:Mode 选 “Asynchronous”(异步模式);
    • 参数默认:波特率 9600bps、8 位数据位、1 位停止位、无校验位;
    • 配置引脚:PA9 设为 “USART1_TX”,PA10 设为 “USART1_RX”;
  3. 配置定时器(TIM3,定时 1s,复用第六天的配置):
    • 预分频器 7199、自动重载值 9999(1s 中断一次),使能 TIM3 中断;
  4. 生成初始化代码。
步骤 2:编写发送逻辑(全局变量 + 定时器中断 + 串口发送)
  1. 打开main.c,定义全局变量(温度数据 + 发送缓冲区):

    c

    /* USER CODE BEGIN 2 */
    uint32_t timer_count = 0;  // 定时器计数(1s一次)
    int temp_raw = 250;        // 模拟温度原始数据
    float temp_real = 0.0;     // 校准后温度
    uint8_t send_buf[50];      // 发送缓冲区(存储要发送的字符串)
    /* USER CODE END 2 */
    
  2. 启动定时器和串口(main函数中):

    c

    /* USER CODE BEGIN 2 */
    HAL_TIM_Base_Start_IT(&htim3);  // 启动TIM3定时中断
    /* USER CODE END 2 */
    
  3. 定时器中断回调函数(1s 更新温度并发送):

    c

    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
      if (htim->Instance == TIM3) {
        // 1. 更新温度数据(模拟采集,每次+1,范围250-270)
        temp_raw = (temp_raw >= 270) ? 250 : temp_raw + 1;
        temp_real = (temp_raw / 10.0) + 2;  // 校准公式
        
        // 2. 格式化发送数据(将数值转为字符串存入缓冲区)
        sprintf((char*)send_buf, "原始数据:%d,校准温度:%.1f℃\r\n", temp_raw, temp_real);
        
        // 3. 串口发送数据(USART1,缓冲区,数据长度,超时100ms)
        HAL_UART_Transmit(&huart1, send_buf, strlen((char*)send_buf), 100);
      }
    }
    
步骤 3:电脑端配置串口助手
  1. 用 USB-TTL 模块连接开发板与电脑(开发板 PA9→TTL Tx,PA10→TTL Rx,GND→GND);
  2. 打开串口助手(如 SecureCRT、SSCOM),配置:
    • 波特率 9600、数据位 8、停止位 1、无校验位、无流控;
    • 选择对应的 COM 口(设备管理器中查看),打开串口。
步骤 4:下载测试

程序下载后,串口助手会每秒收到一条数据:原始数据:250,校准温度:27.0℃,且原始数据逐次递增(模拟传感器实时采集)。


三、实操 2:电脑→开发板,指令控制 LED(50 分钟)

目标:电脑通过串口发送指令(“ON”→点亮 LED,“OFF”→熄灭 LED),开发板接收指令后执行操作,同时定时向电脑反馈 LED 状态(结合实操 1 的定时发送)。

步骤 1:重新配置工程(添加 LED 引脚)
  1. 新建工程 “UART_Control_LED”,配置 USART1(同实操 1)、TIM3(1s 定时);
  2. 配置 LED 引脚:PC13 设为 GPIO_Output(初始熄灭);
  3. 生成初始化代码。
步骤 2:编写接收逻辑(中断接收 + 指令解析)
  1. 定义全局变量(接收缓冲区 + LED 状态):

    c

    /* USER CODE BEGIN 2 */
    uint32_t timer_count = 0;
    uint8_t recv_buf[10];      // 接收缓冲区(存储电脑发送的指令)
    uint8_t led_state = 0;     // LED状态(0=熄灭,1=点亮)
    uint8_t send_buf[50];      // 发送缓冲区
    /* USER CODE END 2 */
    
  2. 启动定时器、串口发送和中断接收(main函数中):

    c

    /* USER CODE BEGIN 2 */
    HAL_TIM_Base_Start_IT(&htim3);  // 启动定时
    // 启动串口中断接收(接收3个字节,对应“ON\r”“OFF\r”,\r是回车符)
    HAL_UART_Receive_IT(&huart1, recv_buf, 3);
    /* USER CODE END 2 */
    
  3. 串口接收完成回调函数(解析指令):

    c

    /* 串口接收完成回调函数:接收3个字节后自动调用 */
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
      if (huart->Instance == USART1) {
        // 解析指令(忽略大小写,电脑发送“ON”“OFF”或“on”“off”都有效)
        if (strcmp((char*)recv_buf, "ON\r") == 0 || strcmp((char*)recv_buf, "on\r") == 0) {
          HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);  // 点亮LED
          led_state = 1;
        } else if (strcmp((char*)recv_buf, "OFF\r") == 0 || strcmp((char*)recv_buf, "off\r") == 0) {
          HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);    // 熄灭LED
          led_state = 0;
        } else {
          // 指令错误,发送提示
          sprintf((char*)send_buf, "指令错误!请发送ON或OFF\r\n");
          HAL_UART_Transmit(&huart1, send_buf, strlen((char*)send_buf), 100);
        }
        
        // 重新开启中断接收(HAL库中断接收一次后会关闭,需手动重启)
        HAL_UART_Receive_IT(&huart1, recv_buf, 3);
      }
    }
    
  4. 定时器中断回调(1s 反馈 LED 状态):

    c

    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
      if (htim->Instance == TIM3) {
        // 发送LED状态
        sprintf((char*)send_buf, "LED状态:%s(发送ON点亮,OFF熄灭)\r\n", led_state ? "点亮" : "熄灭");
        HAL_UART_Transmit(&huart1, send_buf, strlen((char*)send_buf), 100);
      }
    }
    
步骤 3:测试双向通信
  1. 串口助手配置同实操 1,打开串口;
  2. 发送指令 “ON”(回车),开发板 LED 点亮,串口助手收到反馈:LED状态:点亮(发送ON点亮,OFF熄灭)
  3. 发送指令 “OFF”(回车),LED 熄灭,反馈:LED状态:熄灭(发送ON点亮,OFF熄灭)
  4. 发送其他指令(如 “ABC”),开发板反馈:指令错误!请发送ON或OFF

四、第七天必掌握的 3 个关键知识点(10 分钟自测)

  1. 串口通信核心参数:波特率(双方必须一致)、数据格式(8N1:8 位数据 + 1 位停止 + 无校验);
  2. HAL 库串口函数:HAL_UART_Transmit(阻塞发送)、HAL_UART_Receive_IT(中断接收)、HAL_UART_RxCpltCallback(接收回调);
  3. 中断接收注意:HAL 库中断接收一次后会关闭,需在回调函数中重新调用HAL_UART_Receive_IT开启下一次接收。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值