中级会员
 
- 积分
- 235
- 金钱
- 235
- 注册时间
- 2026-1-29
- 在线时间
- 21 小时
|
发表于 2026-4-24 22:53:36
|
显示全部楼层
本帖最后由 664929323 于 2026-4-27 15:05 编辑
以下是 STM32F1 与 HMI串口屏(如迪文屏、淘晶驰屏等)的串口通信完整示例代码及说明。包含 STM32发送数据 和 接收HMI指令并响应 的核心逻辑。
一、硬件接线(UART 直连)
STM32F1 (PA9/PB6) HMI串口屏
TX (输出) → RX
RX (输入) → TX
GND → GND
VCC (可选) → VCC 确保共地!否则通信异常。
二、STM32F1 工程配置(基于标准库)
1. USART 初始化(波特率 115200,8N1)
#include "stm32f10x.h"
void UART_Init(void) {
// 开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
// 配置 PA9 -> TX, PA10 -> RX
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; // 推挽复用输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置 USART1
USART_InitTypeDef USART_InitStruct;
USART_InitStruct.USART_BaudRate = 115200;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART1, &USART_InitStruct);
// 使能中断(用于接收)
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
NVIC_EnableIRQ(USART1_IRQn);
USART_Cmd(USART1, ENABLE); // 使能串口
}
三、发送数据函数(带回车换行)
void UART_SendString(char *str) {
while (*str != '\0') {
USART_SendData(USART1, *str++);
// 等待发送完成
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}
}
// 发送整数(转字符串)
void UART_SendInt(uint16_t num) {
char buf[10];
sprintf(buf, "%d", num);
UART_SendString(buf);
}
四、接收中断 + 指令解析(核心!)
#define RX_BUFFER_SIZE 64
char rxBuffer[RX_BUFFER_SIZE];
uint8_t rxIndex = 0;
uint8_t commandReady = 0;
void USART1_IRQHandler(void) {
uint8_t data = USART_ReceiveData(USART1);
if (data == '\n') { // 假设HMI每条指令以换行结束
rxBuffer[rxIndex] = '\0'; // 字符串结尾
commandReady = 1; // 标记指令就绪
rxIndex = 0; // 重置索引
} else if (data == '\r') {
// 忽略回车符(可选)
} else {
if (rxIndex < RX_BUFFER_SIZE - 1) {
rxBuffer[rxIndex++] = data;
} else {
rxIndex = 0; // 缓冲区溢出,清空重来
}
}
}
// 在主循环处理指令
void Process_Command(void) {
if (commandReady) {
// 例:收到 "LED ON" 打开LED
if (strncmp(rxBuffer, "LED ON", 6) == 0) {
GPIO_SetBits(GPIOB, GPIO_Pin_5); // LED亮
UART_SendString("OK\r\n"); // 回复HMI
}
// 例:收到 "LED OFF" 关闭LED
else if (strncmp(rxBuffer, "LED OFF", 7) == 0) {
GPIO_ResetBits(GPIOB, GPIO_Pin_5); // LED灭
UART_SendString("OK\r\n");
}
// 例:收到 "GET TEMP" 返回温度值
else if (strncmp(rxBuffer, "GET TEMP", 8) == 0) {
uint16_t temp = Read_Temperature(); // 你的传感器读取函数
UART_SendString("TEMP=");
UART_SendInt(temp);
UART_SendString("\r\n");
}
commandReady = 0; // 清除标志
}
}
五、主函数模板
int main(void) {
SystemInit(); // 系统时钟初始化(确保已配置)
UART_Init(); // 串口初始化
// 初始化LED(PB5)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef gpio;
gpio.GPIO_Pin = GPIO_Pin_5;
gpio.GPIO_Mode = GPIO_Mode_Out_PP;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &gpio);
while (1) {
// 主动上报数据(例如每秒发送一次温度)
UART_SendString("STATUS=OK\r\n");
Delay(1000); // 自定义延时函数
// 处理HMI发来的指令
Process_Command();
}
}
六、HMI串口屏端配置建议(迪文/淘晶驰通用)
波特率:115200(与STM32一致)
数据格式:8位数据位,无校验,1位停止位(8N1)
发送指令示例:
点亮LED → 发送 LED ON\r\n
获取温度 → 发送 GET TEMP\r\n
接收显示:设置HMI接收缓冲区,解析 STATUS=OK 或 TEMP=25 等数据更新界面。
七、调试技巧
用USB转串口工具监听:将STM32的TX接到电脑串口助手,验证发送内容。
HMI日志功能:启用HMI的串口调试模式,查看收发原始数据。
添加心跳包:定期发送 HEARTBEAT\r\n,确认链路通畅。
八、常见问题解决
现象 原因 解决方案
HMI无反应 接线错误/未共地 检查TX/RX/GND
乱码 波特率不匹配 双方统一为115200
指令无效 缺少结束符 确保发送 \r\n
程序卡死 接收缓冲区溢出 增加 RX_BUFFER_SIZE
提示:不同HMI厂商可能有私有协议(如迪文DGUS),若需图形界面交互,请参考对应HMI的《串口指令集》文档扩展本例程。
按此框架修改即可快速实现STM32与HMI串口屏的双向通信!
|
|