2. HIL测试平台初始化
任务目标
搭建一个最小可用的HIL(硬件在环)测试平台,实现上位机(PC)与STM32目标板之间的双向数据交互。平台包含实时仿真机(以脚本模拟)、STM32目标板(以开发板固件实现)和上位机通信接口,三者通过串口连接,完成命令下发与状态回传的闭环。
平台架构与连接
本案例采用“上位机(PC) — 实时仿真机(PC脚本) — STM32目标板”的简化拓扑。实时仿真机与STM32之间通过UART1连接,上位机与实时仿真机之间通过UART2连接(实际部署时可用同一PC的两个串口或虚拟串口对)。实时仿真机负责转发上位机指令并模拟被控对象响应。
环境依赖
- STM32开发板(Nucleo-F401RE或类似),板载ST-Link虚拟串口
- STM32CubeIDE(含CubeMX)用于生成和编译固件
- Python 3.8+,安装
pyserial库:pip install pyserial - 两个可用串口(Windows下可用虚拟串口软件如VSPD模拟一对互联串口)
STM32目标板固件(CubeMX配置 + 核心代码)
使用CubeMX生成基础工程,配置UART1(115200-8-N-1)和UART2(115200-8-N-1),开启UART1接收中断。在 main.c 中添加以下核心逻辑:
// 全局变量
uint8_t rx1_buf[64];
uint8_t rx1_len = 0;
uint8_t tx2_buf[64];
// UART1接收中断回调(接收来自实时仿真机的命令)
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart == &huart1) {
// 简单协议:收到单字节命令,回传状态
uint8_t cmd = rx1_buf[0];
uint8_t status[2];
status[0] = cmd; // 回显命令
status[1] = cmd + 1; // 模拟状态值(如ADC采样结果)
// 通过UART2发送到实时仿真机
HAL_UART_Transmit(&huart2, status, 2, 100);
// 重新开启接收中断
HAL_UART_Receive_IT(&huart1, rx1_buf, 1);
}
}
// main() 中初始化后启动接收
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
// 启动UART1接收中断
HAL_UART_Receive_IT(&huart1, rx1_buf, 1);
while (1)
{
// 主循环可处理其他任务,此处留空
}
}
实时仿真机脚本(simulator.py)
该脚本运行在PC上,连接STM32的UART1和上位机的UART2,负责双向转发并模拟被控对象延迟。
import serial
import time
import threading
# 串口配置(根据实际设备修改)
STM_PORT = 'COM5' # 连接STM32的串口
HOST_PORT = 'COM6' # 连接上位机的串口
BAUD = 115200
stm_ser = serial.Serial(STM_PORT, BAUD, timeout=0.1)
host_ser = serial.Serial(HOST_PORT, BAUD, timeout=0.1)
def stm_to_host():
"""STM32 → 上位机转发"""
while True:
if stm_ser.in_waiting:
data = stm_ser.read(stm_ser.in_waiting)
host_ser.write(data)
time.sleep(0.001)
def host_to_stm():
"""上位机 → STM32转发(模拟实时仿真机处理延迟)"""
while True:
if host_ser.in_waiting:
data = host_ser.read(host_ser.in_waiting)
time.sleep(0.01) # 模拟10ms处理延迟
stm_ser.write(data)
time.sleep(0.001)
# 启动双向转发线程
threading.Thread(target=stm_to_host, daemon=True).start()
threading.Thread(target=host_to_stm, daemon=True).start()
print("实时仿真机已启动,双向转发中...")
while True:
time.sleep(1)
上位机测试脚本(host.py)
import serial
import time
HOST_PORT = 'COM6' # 与simulator.py的HOST_PORT对应
BAUD = 115200
ser = serial.Serial(HOST_PORT, BAUD, timeout=1)
def send_command(cmd_byte):
"""发送单字节命令并接收2字节响应"""
ser.write(bytes([cmd_byte]))
resp = ser.read(2)
return resp
# 发送测试命令序列
test_commands = [0x01, 0x02, 0x03, 0x10, 0x55]
print("=== HIL平台通信测试 ===")
for cmd in test_commands:
resp = send_command(cmd)
if len(resp) == 2:
echo = resp[0]
status = resp[1]
print(f"发送: 0x{cmd:02X} → 回显: 0x{echo:02X}, 状态: 0x{status:02X}")
if echo == cmd and status == cmd + 1:
print(" ✓ 校验通过")
else:
print(" ✗ 数据不匹配")
else:
print(f"发送: 0x{cmd:02X} → 无响应(超时)")
ser.close()
运行与验证
- 烧录固件:编译STM32工程并烧录到目标板,打开串口调试助手确认UART1和UART2均正常初始化。
- 启动实时仿真机:运行
python simulator.py,看到“实时仿真机已启动”提示。 - 运行上位机测试:另开终端执行
python host.py。 - 通过标准:所有测试命令均显示“✓ 校验通过”,即证明上位机→实时仿真机→STM32→实时仿真机→上位机的完整数据链路已打通,HIL平台初始化成功。
常见问题
- 串口打不开:确认设备管理器中端口号,关闭占用该串口的其他程序。
- 无响应:检查STM32的UART1接收中断是否已启动(
HAL_UART_Receive_IT必须在主循环前调用一次)。 - 数据乱码:核对所有串口参数一致(115200, 8, N, 1),且共地连接。