项目介绍
本次参加2026贸泽电子M-Design创意设计大赛(第二季)活动选择任务为方向三:工业控制,所做项目以 STM32H533 为核心控制器,驱动 42 步进电机实现流水线运动控制;通过触摸串口屏下发指令,灵活控制电机启停与运行速度;搭载三路 PNP 位置传感器实现精准到位检测,电机可根据传感器信号自动左右往返运行,系统响应迅速、控制稳定,满足简易流水线自动化作业需求。
硬件介绍
本项目硬件主要由主控单元、流水线执行机构与人机交互设备三部分组成。主控采用STM32H533 最小系统,作为整个控制系统的核心,具备丰富的外设资源与出色的运算能力,主要完成串口指令解析、步进电机驱动控制、传感器信号采集、逻辑运算等核心工作,为整套设备稳定运行提供基础保障。
流水线执行机构为设备运动主体,核心动力部件为42 步进电机,可实现精准启停、转速调节与往复运动,满足流水线位移控制需求。系统搭配三路PNP 型位置传感器,分别布置在行程关键点位,实时检测设备运行位置,输出电平信号反馈至主控,实现限位保护与到位判定,保障电机安全稳定地左右往返运行。
人机交互选用淘晶驰串口屏,通过串口与主控进行数据通信。操作人员可通过屏幕触摸操作下发启停、调速等控制指令,同时屏幕可同步展示设备运行状态,操作简单直观,实现了人机便捷交互。
方案框图和项目设计思路
本项目以 STM32H533 为控制核心,通过串口接收淘晶驰触摸屏的启停、调速指令,驱动 42 步进电机运转。利用三路 PNP 位置传感器检测位置信号,主控实时采集并判断,实现电机自动左右往返与到位停止。整体设计兼顾手动操控与自动运行,结构简洁、响应快速,满足简易流水线自动化控制需求。

方案框图
原理图和PCB介绍
因为这个简易的流水线位置传感器的输出信号是24V所以会有一个信号转接板,用来将24V输入转换为单片机可以检测的3.3V左右以下是他的原理图和PCB

原理图

PCB
软件流程图和关键代码介绍
软件流程图

软件流程图
代码详解
串口协议解析
void Connec_Process(void)
{
uint8_t rx_buf[64];
uint16_t rx_len;
uint16_t i = 0;
/* 获取接收缓冲区数据长度 */
rx_len = Bsp_Uart5_Get_Rx_Len();
/* 没有数据直接返回 */
if (rx_len == 0)
{
return;
}
/* 读取所有接收数据到临时缓冲区(会清空硬件缓冲区) */
Bsp_Uart5_Read_Rx_Data(rx_buf, rx_len);
/* 逐字节解析数据 */
while (i < rx_len)
{
uint8_t rx_data = rx_buf[i];
/* 根据当前状态处理 */
switch (parse_state)
{
case PARSE_STATE_IDLE:
{
/* 等待包头状态 */
if (rx_data == PKT_HEADER_80)
{
/* 收到0x80包头,切换到等待数据状态 */
parse_state = PARSE_STATE_80;
last_pkt_header = PKT_HEADER_80;
uprintf("PKT:80\r\n");
}
else if (rx_data == PKT_HEADER_81)
{
/* 收到0x81包头,切换到等待数据状态 */
parse_state = PARSE_STATE_81;
last_pkt_header = PKT_HEADER_81;
uprintf("PKT:81\r\n");
}
else
{
/* 非包头数据,忽略 */
uprintf("IGN:0x%02x\r\n", rx_data);
}
}
break;
case PARSE_STATE_80:
{
/* 收到0x80包头后的数据字节 */
/* 判断控制值:0x00=低电平,0x01=高电平 */
if (rx_data == 0x00)
{
Bsp_Output_Set(BSP_OUTPUT_END, false);
uprintf("END=LOW\r\n");
}
else if (rx_data == 0x01)
{
Bsp_Output_Set(BSP_OUTPUT_END, true);
uprintf("END=HIGH\r\n");
}
else
{
uprintf("80 ERR:inv=0x%02x\r\n", rx_data);
}
/* 一个完整包已处理完毕,回到等待包头状态 */
parse_state = PARSE_STATE_IDLE;
}
break;
case PARSE_STATE_81:
{
/* 收到0x81包头后的数据字节 */
/* 判断速度值是否在有效范围内(1~100) */
if (rx_data >= 1 && rx_data <= 100)
{
speed_value = rx_data;
uprintf("SPEED=%d\r\n", speed_value);
/* 更新PWM频率,占空比固定50% */
PWM_Update_Frequency(speed_value);
}
else
{
uprintf("81 ERR:val=%d ovf\r\n", rx_data);
}
/* 一个完整包已处理完毕,回到等待包头状态 */
parse_state = PARSE_STATE_IDLE;
}
break;
default:
/* 未定义状态,强制回到IDLE */
parse_state = PARSE_STATE_IDLE;
break;
}
i++;
}
}
根据串口屏的反馈调节电机速度
void PWM_Update_Frequency(uint8_t speed)
{
uint32_t frequency;
uint32_t period;
TIM_OC_InitTypeDef sConfigOC = {0};
/* 限制速度值范围 */
if (speed < 1) speed = 1;
if (speed > 100) speed = 100;
/* 计算目标频率: 1kHz ~ 100kHz (线性映射) */
/* speed=1 -> frequency=1000Hz */
/* speed=50 -> frequency=50000Hz */
/* speed=100 -> frequency=100000Hz */
frequency = 1000UL * speed;
/* 计算Period: TIM3_clock / (2 * frequency) - 1 */
/* 假设TIM3时钟为250MHz */
/* 除以2是因为PWM模式1周期的一半为有效电平(50%占空比) */
period = 250000000UL / (2 * frequency) - 1;
/* 更新Period */
htim3.Init.Period = period;
HAL_TIM_PWM_Init(&htim3);
/* 配置50%占空比: Pulse = (Period + 1) / 2 */
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = (period + 1) / 2;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2);
/* 重新启动PWM */
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);
/* 调试输出:显示速度值、频率、Period、占空比 */
// uprintf("[PWM] speed=%d, freq=%dHz, period=%d, duty=50%%\r\n", speed, frequency, period);
uprintf("n0.val=%x",frequency);
}
功能展示图及说明

总体展示图

控制图
说明:
按下STOP键就会开启电机并变换为start,右面的滑块可以滑动,滑动结束会发送设置速度的指令
心得体会
本次项目让我熟悉了 STM32 外设应用与步进电机驱动开发,掌握了传感器信号采集和串口通信的实操技巧。调试过程中,我逐步解决了电机调速、限位触发等问题,深刻体会到软硬件配合的重要性。同时也认识到程序逻辑与硬件布局需兼顾合理性,后续会继续积累实战经验。