在嵌入式系统开发中,串口通信是实现设备间数据交互的重要方式之一。STM32 凭借其丰富的外设和强大的性能,成为嵌入式开发的热门选择。本文将详细介绍如何基于 HAL 库在 STM32 上实现 RS232 串口通信,以完成上下位机之间的控制与数据传输。
目录
一、开发环境与硬件准备
(一)开发环境
- 硬件平台:STM32 开发板(以 STM32F103C8T6 为例)、PC 机(上位机)、RS232 转 TTL 模块(如 MAX232 芯片模块)。
- 软件工具:Keil MDK(用于编写和编译 STM32 代码)、STM32CubeMX(用于配置 STM32 外设)、串口调试助手(如 XCOM、SSCOM 等,用于上位机与下位机通信测试)。
(二)硬件连接
RS232 串口通信需要进行电平转换,因为 STM32 使用的是 TTL 电平(3.3V 或 5V),而 PC 机的串口使用的是 RS232 电平(正负电压)。通过 RS232 转 TTL 模块实现电平转换,具体连接如下:
- STM32 的 TX 引脚(PA9)连接到 RS232 转 TTL 模块的 RX 引脚。
- STM32 的 RX 引脚(PA10)连接到 RS232 转 TTL 模块的 TX 引脚。
- RS232 转 TTL 模块的 VCC 连接到 STM32 的 3.3V 电源。
- RS232 转 TTL 模块的 GND 连接到 STM32 的 GND。
- RS232 转 TTL 模块通过 USB 转串口线连接到 PC 机的 USB 接口。
二、STM32CubeMX 配置
(一)新建工程
打开 STM32CubeMX,选择对应的 STM32 芯片型号(如 STM32F103C8T6),创建新工程。
(二)配置串口
- 在 "Pinout & Configuration" 选项卡中,找到 USART1(根据实际使用的串口选择,这里以 USART1 为例)。
- 设置 USART1 为异步通信模式(Asynchronous)。
- 配置波特率(Baud Rate),通常设置为 9600、115200 等常用速率,此处设置为 115200。
- 数据位(Data Bits)选择 8 位。
- 停止位(Stop Bits)选择 1 位。
- 校验位(Parity)选择无校验(None)。
- 硬件流控制(Hardware Flow Control)选择无(None)。
(三)配置时钟
根据开发板的晶振频率配置系统时钟,确保串口通信的时钟准确。例如,若外部晶振为 8MHz,通过时钟树配置使系统时钟达到 72MHz。
(四)生成代码
完成配置后,点击 "Generate Code" 生成 Keil MDK 工程文件。
三、STM32 代码编写(HAL 库)
(一)包含头文件
在主函数所在的文件中,包含必要的头文件:
#include "stm32f1xx_hal.h"
#include "usart.h"
#include "gpio.h"
(二)串口发送函数
void uart_send_string(uint8_t *str) {
HAL_UART_Transmit(&huart1, str, strlen((char *)str), 0xffff);
}
该函数用于向上位机发送字符串,通过 HAL 库的HAL_UART_Transmit函数实现数据传输。
(三)串口接收回调函数
uint8_t receive_buffer[100]; // 接收缓冲区
uint8_t receive_index = 0; // 接收索引
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (huart == &huart1) {
receive_buffer[receive_index++] = receive_buffer[0]; // 存储接收到的数据
if (receive_index >= sizeof(receive_buffer)) {
receive_index = 0; // 缓冲区满,重新开始
}
HAL_UART_Receive_IT(&huart1, receive_buffer, 1); // 重新开启接收中断
}
}
通过接收回调函数处理接收到的数据,使用中断方式接收数据,提高程序效率。在主函数中初始化接收中断:
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
HAL_UART_Receive_IT(&huart1, receive_buffer, 1); // 开启接收中断
while (1) {
// 主循环处理逻辑
if (receive_index > 0) {
// 处理接收到的数据,例如根据指令控制LED等
if (strcmp((char *)receive_buffer, "LED_ON\r\n") == 0) {
// 点亮LED的代码
} else if (strcmp((char *)receive_buffer, "LED_OFF\r\n") == 0) {
// 熄灭LED的代码
}
receive_index = 0; // 处理完数据后清空索引
}
}
}
四、上位机软件设计(以 Python 为例)
上位机可以使用 Python 编写简单的串口通信程序,实现向 STM32 发送控制指令和接收数据。
(一)安装串口库
使用 pip 安装 pyserial 库:
pip install pyserial
(二)上位机代码
import serial
import time
# 配置串口参数
ser = serial.Serial(
port='COM3', # 根据实际串口端口号设置
baudrate=115200,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=1
)
def send_command(command):
"""发送控制指令"""
ser.write((command + '\r\n').encode())
def receive_data():
"""接收数据"""
data = ser.read_all()
if data:
return data.decode()
return None
if __name__ == "__main__":
while True:
command = input("请输入控制指令(LED_ON/LED_OFF):")
send_command(command)
time.sleep(0.1)
response = receive_data()
if response:
print("下位机返回:", response)
五、通信测试
(一)硬件连接检查
确保 STM32 开发板、RS232 转 TTL 模块和 PC 机之间的连接正确,电源正常。
(二)串口调试助手测试
- 打开串口调试助手,设置与 STM32 相同的波特率、数据位、停止位和校验位。
- 在上位机串口调试助手中发送指令,如 "LED_ON",观察 STM32 开发板上的 LED 是否点亮;发送 "LED_OFF",观察 LED 是否熄灭。
- STM32 可以向上位机发送数据,例如在主循环中定时发送 "Hello from STM32!",在上位机串口调试助手中查看接收的数据是否正确。
(三)Python 程序测试
运行编写的 Python 上位机程序,按照提示输入控制指令,测试上下位机之间的通信是否正常,数据传输是否准确无误。
六、注意事项
- 电平转换模块的选择要确保与 STM32 的电平兼容(3.3V 或 5V)。
- 串口参数(波特率、数据位、停止位、校验位)必须上下位机一致,否则无法正常通信。
- 在处理接收数据时,要注意缓冲区的大小和溢出处理,避免数据丢失或程序出错。
- 对于长时间通信或大量数据传输,建议添加数据校验和错误处理机制,提高通信的可靠性。
通过以上步骤,我们成功实现了基于 HAL 库的 STM32 与上位机之间的 RS232 串口通信,完成了上下位机控制。这种通信方式在嵌入式系统中具有广泛的应用场景,如工业控制、物联网设备、数据采集等。掌握 HAL 库的串口通信开发,将为进一步开发复杂的嵌入式系统奠定坚实的基础。