
这类基于 STM32 的电机状态检测项目在毕设和课程设计里出现频率很高。它核心解决的事情并不是“读一个电流值”那么简单而是把电压、电流、PWM、堵转、过载这些状态量采集到 MCU 里再做滤波、换算、判断和展示最后形成一个完整的“检测 — 判断 — 告警 — 保护”链路。适合的人群很明确正在选嵌入式课题的学生想用 STM32 做电机控制的开发者以及第一次接触 ADC 采样和信号调理电路的入门者。最值得关注的点不是“电机转不转”而是“怎么通过电压和电流变化判断电机当前处于什么状态”以及“为什么有些环境跑起来显示正常一接电机采样值就开始乱跳”。下面我按实际落地的顺序拆一遍从需求拆解、硬件准备、电压电流采样电路到程序结构、状态判断、常见排查和扩展思路全部写在一起。遇到容易踩坑的地方我会直接点出来。1. 先把电机状态检测的需求拆清楚1.1 检测对象不是“电机”本身而是“电机回路”的能量状态很多初学者一听到“电机状态检测”第一反应是是不是要检测电机类型、电机编号、电机健康状况实际在嵌入式侧我们说的电机状态检测更多是指检测电机工作回路中的几个电气量然后通过这些电气量推断电机当前的运行状态。具体到 STM32 平台最常见的一组检测对象是电源电压或者电机供电电压电机工作电流PWM 控制占空比或者控制档位电机的启动、运行、堵转、停机状态通过电流变化间接判断的负载大小和故障状态这样处理后STM32 得到的不是“这台电机是直流电机还是步进电机”这种分类信息而是“当前电机电压是多少、电流是多少、有没有堵转、是不是空载、有没有过流”这些可以直接用于控制的信息。1.2 什么场景下需要自己做电机状态检测直接回答一个问题买一个成品电机驱动板很多驱动板本身就带电流采样引脚为什么还要自己设计一套检测电路主要场景有几个毕业设计或者课程设计需要体现完整的信号调理、ADC 采集、算法处理、显示和告警链路。定制化设备中驱动板和主控分离主控需要自己采集电机状态。需要采集多路状态量比如电压、电流、转速、温度而不是单一电流。需要把检测数据用于闭环控制比如堵转保护、恒流控制、超载保护。低成本场景不能用高端驱动芯片必须用分立器件把检测电路搭出来。在这些场景下STM32 检测电机状态的完整链路就变得很有价值传感器把物理量变成电压信号调理电路把电压信号变成 STM32 ADC 能接受的范围MCU 通过 ADC 采样、滤波、换算、阈值判断最后输出显示和控制信号。1.3 检测结果的输出形式电机状态检测做完之后结果要能被人或者上位机看到。常见输出方式包括OLED 或者 LCD1602 显示电压、电流、状态文字。串口打印方便接上位机调试。状态指示灯比如正常运行亮绿灯、过流亮红灯。蜂鸣器报警。通过 GPIO 或者继电器控制外部负载。这套思路其实就是把检测、处理、显示、告警全部串起来。对于学习嵌入式的人来说它能覆盖 GPIO、ADC、定时器、PWM、串口、外部中断、显示驱动这些常见外设所以很适合作为独立项目。2. 跑通这个项目需要准备哪些硬件和软件2.1 硬件环境低配也能起步做电机状态检测不一定非要高端的 STM32F407 或者 H7 系列。很多现成的资料参考都是基于 STM32F103C8T6 或者 STM32F103ZET6。F103C8T6 最小系统板足够跑通初期逻辑只有一点需要注意如果你的检测板需要同时驱动显示、蜂鸣器、继电器并且还要做屏幕刷新那么引脚规划要提前想好避免后期扯线。我建议的基础硬件清单STM32F103C8T6 最小系统板或者对应的开发板。直流电机工作电压 5V 到 12V 都行带减速器的更稳。电机驱动模块常见 L298N 或者 TB6612。电压采样部分电阻分压网络。电流采样部分采样电阻加运算放大器或者 ACS712 电流传感器模块。ST-Link 调试器或者 USB 转 TTL 串口模块。OLED 显示屏0.96 寸 I2C 接口的比较方便。必要的按键用于切换显示模式或者设置报警阈值。蜂鸣器和 LED用来做状态提示。这个清单里最容易被人忽略的是采样电阻和运放这一块。如果只是学习原理用 ACS712 会省事很多接线少、隔离简单、程序也直观。但如果想真正理解电机电流检测的原理最好还是把“采样电阻 运放放大 ADC 采集”这条路走一遍。2.2 软件环境提前把工程模板搭好STM32 开发环境现在主流是 Keil MDK配合 STM32CubeMX 做初始化代码生成。也可以选择 GCC 工具链加 VS Code但新手直接上手 Keil 加 CubeMX 的组合调试方便一些。需要准备的内容Keil MDK版本建议 5.x。对应型号的器件支持包比如 STM32F1xx 的 Device Family Pack。STM32CubeMX用来生成初始化工程。ST-Link 驱动或者你手头调试器的驱动。串口助手比如 XCOM、PuTTY。这里有一个常见问题很多人下载了 STM32CubeMX也安装了 Keil但生成工程后编译报错最常见的原因是器件支持包没有装或者 Keil 打开的工程版本和实际固件库不一致。我的建议是第一次搭建工程时直接用标准库或者 HAL 库新建一个空工程先能点亮 LED再去做 ADC 采样。不要一上来就把电机驱动、显示、采样全部揉进一个工程里。提示我实际开发时喜欢用 CubeMX 生成外设初始化再在用户代码区写业务逻辑。这样外设时钟、引脚复用、ADC 触发方式不会因为手写遗漏而出问题也方便以后换芯片型号重新生成。3. 电压检测的实现思路与实测参数3.1 电压检测为什么不能直接把 12V 接到 STM32STM32 的 ADC 输入电压范围通常是 0 到 3.3V。如果你直接把 12V 接到 PA0 引脚大概率会烧引脚严重时还会烧主控。所以电压检测的第一步就是把 12V、24V 这种电源电压降到 ADC 可以承受的范围内。常用的方法是电阻分压。比如你要测 12V可以用 10K 和 3.3K 电阻分压得到一个大约 2.48V 的输出。这个信号再经过一个电压跟随器或者直接接 ADC 引脚。加电压跟随器的好处是提高输入阻抗减少电源波动对采样结果的影响但简单的学习项目不加也能跑。分压比例要根据你的被测电压范围和 STM32 的 ADC 参考电压来设计。参考电压 VREF 在 F103 上通常就是 3.3V所以设计原则是最大被测电压对应的分压输出电压要低于 3.3V最好留出 10% 到 20% 的余量。3.2 计算分压电阻假设电机电源电压 V_MOTOR 最大为 12V我们希望 ADC 引脚最大电压 V_ADC_MAX 不超过 3.0V方便留余量。分压电路一般用上电阻 R1 和下电阻 R2V_ADC V_MOTOR * R2 / (R1 R2)要让 12V 对应 3.0V则 R2 / (R1 R2) 3.0 / 12 0.25。取 R1 10KR2 3.3K则比例约 0.24812V 时 ADC 引脚约 2.98V符合余量要求。如果被测电压是 24V可以选 R1 20KR2 3K比例约 0.1324V 时约为 3.13V但还是偏极限。更稳妥的是 R1 22KR2 3.3K比例约 0.1324V 对应 3.12V。实际使用时还要看电阻精度。3.3 ADC 采样和数值换算STM32F103 的 ADC 是 12 位分辨率是 4096。如果参考电压是 3.3V那么 ADC 数值 N 对应的电压是V_ADC N / 4096 * 3.3然后反向计算电机电源电压V_MOTOR V_ADC * (R1 R2) / R2比如 ADC 读到 2000则 V_ADC 1.61V按 10K 和 3.3K 分压V_MOTOR 1.61 * 13.3 / 3.3 6.49V。这里要注意几个细节参考电压并不是所有板子都精确等于 3.3V最好用万用表实测一下板载 3.3V 再代替公式里的 3.3。电阻分压存在误差尤其是普通 5% 精度电阻电压越高偏差越大。想准一点用 1% 精度电阻。如果采样结果波动大可以在程序里做多次采样取平均或者用简单的滑动滤波。3.4 电压结果怎么看我用过的验证例子是这样电机电源统一接 12V 直流空载时采样电压在 11.8V 左右带负载后因为电源内阻和线路压降可能掉到 11.5V堵转时如果电源能力不够可能掉到 8V 以下。这种变化本身就能反映出电机状态。如果屏幕上显示电压明显偏低先检查分压电阻焊没焊对再用万用表量 ADC 引脚电压和 STM32 读到的内部换算值对比。很多时候不是程序问题而是电阻接错或者参考电压不对。4. 电流检测的实现思路重点讲采样电阻与运放4.1 为什么测电流比测电压更麻烦电压检测只需要把大电压变小用几个电阻就能做。电流检测不能直接接电流表读也不能把电流直接送进 ADC。最常见的思路是把电流转换成电压再放大再让 ADC 采集。转换的方式有两种采样电阻法在电流回路中串一个小阻值电阻用电阻两端压差反映电流。霍尔电流传感器比如 ACS712直接输出一个与电流成比例的电压信号。ACS712 用起来简单但价格比采样电阻加运放高。而且如果你想学习信号调理电路采样电阻加运放是更完整的设计。4.2 采样电阻怎么选采样电阻的阻值不能太大否则产生压降影响电机供电。一般选 0.1Ω、0.05Ω 这种小电阻。功率也要选够否则大电流流过时会发热甚至烧掉。采样电阻压降 V_SENSE I_MOTOR * R_SENSE。假设电机最大电流 2A采样电阻 0.1Ω压降就是 0.2V。这个 0.2V 如果直接接 STM32 ADC在小电流时分辨率不足因为 0.5A 对应 0.05VADC 能分辨但误差大。所以需要放大。放大方式可以用最简单的同相放大器也可以用电流检测专用运放比如 INA180、INA240。如果自己搭选轨到轨运放 LMV358 或者 MCP6002 比较合适单电源 3.3V 也能工作。放大倍数设计原则最大电流对应的放大后输出电压不超过 3.0V给 ADC 留余量。上面例子 2A 对应 0.2V 压降如果放大 10 倍对应 2.0V配合 12 位 ADC 分辨率约 0.49mV对应电流分辨率 0.49mA这个精度足够看电机负载和堵转变化。4.3 电流采样计算示例设采样电阻 R_SENSE 0.1Ω最大电流 I_MAX 2A运放放大倍数 G 10则 ADC 引脚最大电压V_ADC_MAX 2 * 0.1 * 10 2.0VADC 读到的电压为 V_ADC则实际电流I V_ADC / (R_SENSE * G) V_ADC / 1也就是实测电流等于 ADC 引脚电压值。这种方式运算简单适合新手调试。如果 G 200.2V 压降放大到 4V超出 3.3V 范围就要减小采样电阻或者降低放大倍数。所以不要盲目追求大放大倍数必须结合 ADC 参考电压和最大电流一起算。4.4 为什么堵转检测要用电流变化而不是只看 PWM直流电机在稳定运转时电流比较平稳。负载增加时电流上升。堵转时因为电机不动反电动势为 0回路电流会快速增大到接近堵转电流。堵转电流通常是额定电流的数倍。STM32 只需要定义两个阈值正常运行时电流在某个区间。电流超过阈值持续时间超过一定时长判定为堵转或者过载。不要刚开始就判断电流超过阈值立刻报警因为电机启动瞬间电流也会很大。我一般会在程序里做“超阈值持续计数”比如连续采样 20 次或者持续 100ms 仍然超过阈值才判定为异常。这样能避免启动浪涌造成的误报。4.5 电流检测的实测注意点如果用 ACS712VCC 用 5V 时输出信号会有一个 2.5V 的直流偏置也就是说 0A 输出约 2.5V正电流输出高于 2.5V负电流输出低于 2.5V。STM32 ADC 直接采集 2.5V 没问题但换算电流时要把 2.5V 减去。如果用采样电阻加运放运放电源要稳定。如果运放供电和 STM32 3.3V 共用容易受到电机启停冲击导致采样抖。解决办法是在运放电源引脚加 0.1uF 和 10uF 去耦电容电机电源地和控制地单点连接。5. STM32 端程序结构ADC 采样、滤波、状态判断5.1 外设初始化顺序程序里需要用到的外设包括GPIO用于 ADC 引脚输入、OLED 或 LCD 显示、按键、指示灯、蜂鸣器。ADC采集电压和电流两路模拟信号。定时器可以用于 PWM 输出控制电机转速也可以用于定时采样。串口打印调试数据。I2C 或 SPI驱动 OLED 或 LCD。CubeMX 里初始化顺序一般是系统时钟、GPIO、ADC、定时器、串口、I2C/SPI。生成代码后在 main 函数里先初始化外设再进入 while 主循环。5.2 一次完整采样的流程我推荐的采样流程如下定时器或者主循环触发 ADC 转换读取电压通道。延时或者启动下一次转换读取电流通道。对原始 ADC 值进行滤波。把滤波后的值换算成实际电压和电流。根据阈值判断电机状态正常、空载、过载、堵转。刷新显示串口打印必要时控制蜂鸣器和指示灯。不要在检测到电流变化之后立刻做复杂处理最好把“采样、换算、状态判断、输出控制”拆成不同函数。这样后续调试更容易定位问题。5.3 关于滤波的简洁实现ADC 采样最怕抖动尤其是电机运行中电流波动大。如果直接用单次采样值做阈值判断很容易误报。可以做一个简单的滑动平均数组保存最近 N 次采样值每次求和取平均。N 取 8 或者 16 都行数值越大越平滑但响应越慢。堵转检测需要一定响应速度所以 N 不宜太大。如果希望更细致可以区分用途显示电压电流用较重的滤波比如 N16。堵转保护用较轻的滤波比如 N4再配合持续超阈值计数。这样可以兼顾显示平稳和保护及时性。不要用一套滤波参数处理所有需求。5.4 状态判断逻辑假设电流阈值分三档电流小于 I_IDLE判定为停机或者空载。电流正常范围判定为运行中。电流大于 I_OVERLOAD且持续 T1判定为过载或堵转。这个逻辑用一个函数就能实现类似uint8_t check_motor_state(float voltage, float current) { if (current I_IDLE) return STATE_STOP; if (current I_OVERLOAD) return STATE_OVERLOAD; return STATE_RUNNING; }当然实际工程里不能只看一个电流点。可以把当前状态保存在一个变量里每次循环根据新的采样值更新并用一个计数器记录连续异常次数。只有异常计数器超过阈值才真正切换状态。否则电机启动瞬间的尖峰电流会把状态误判成堵转。6. 上位机、显示和报警如何把检测结果用起来6.1 显示设计OLED 是直观选择0.96 寸 I2C OLED 显示内容项目第一行显示电机电压比如 V: 11.82V。第二行显示电机电流比如 I: 0.86A。第三行显示 PWM 占空比或者当前状态。第四行显示运行状态比如 NORMAL、OVERLOAD。显示刷新频率不用太高5 到 10Hz 就够。人眼对电压电流的实时变化没有那么敏感刷新太快反而占用 CPU 和 I2C 总线。6.2 串口输出调试阶段最有用调试时我一般用串口打印一行数据V11.82V, I0.86A, PWM70%, STATERUNNING这样把取样结果和状态判断结果一起输出就能快速发现算法问题。比如电压一直显示 0说明分压电路或者 ADC 引脚有问题电流一直显示 2.5V 对应的值可能是 ACS712 偏置未减去。串口波特率建议 115200调试信息用中文或英文都行但要注意串口助手的编码有些串口助手对中文编码支持不好可以先用英文。6.3 报警输出蜂鸣器和 LED电机过流或堵转时除了显示状态还需要外部告警。可以用一个 LED 常亮表示过流蜂鸣器间歇鸣叫提示。用 GPIO 控制外部继电器时要加三极管或者光耦驱动不要直接用 STM32 引脚驱动继电器线圈因为线圈电流可能超过 GPIO 驱动能力。蜂鸣器如果是有源蜂鸣器直接给高电平就会响程序里用延时或者定时器控制响 200ms、停 200ms 即可。如果是无源蜂鸣器需要给 PWM 信号驱动频率通常在 2KHz 到 4KHz实际参数以模块为准。6.4 按键调整阈值为了让项目更完整可以留两个按键一个用于切换显示页面一个用于修改过流阈值。这样可以避免每次要改阈值就重新烧录程序。这种交互方式也很适合在答辩或者展示时演示。7. 从单路检测扩展到多路检测、控制和闭环7.1 多路电机检测如果一个 STM32 需要检测两路或者三路电机ADC 通道数量要提前算好。STM32F103C8T6 有 10 个 ADC 引脚如果每路电机需要电压和电流两个采样点支持三路电机就需要 6 路还剩下一些引脚做按键、显示、PWM。这个数量基本够用但要注意 ADC 引脚不能与其他功能冲突。多路检测的核心问题是采样顺序和通道切换。使用 ADC 扫描模式时可以配置多通道顺序采样但要注意每个通道的采样时间和转换时间。如果两个通道相互干扰检查是否是采样时间太短。7.2 从“检测状态”到“控制电机”检测到异常之后下一步自然是控制。常见控制逻辑包括堵转保护检测到电流超阈值立即把 PWM 降为 0停止电机。软启动启动前先把 PWM 从 0 慢慢增加到目标值减小启动冲击电流。恒流限制通过电流闭环调整 PWM让电流保持在一个区间内。过温保护如果还接了温度传感器温度过高时降低占空比或者停机。这个阶段就进入了简单的闭环控制。虽然有刷直流电机的控制不像 BLDC 那样复杂但“采样、比较、调整 PWM”这套思路是通用的以后做 PID 调速、平衡车、无刷电机控制也能复用。7.3 如何做一个可供答辩展示的完整项目如果是毕业设计或者课程设计除了让电路能跑还需要考虑演示流程开机后屏幕显示初始电压和电流。按下启动键电机运行PWM 从 0 逐步增加。按下负载切换键或者手动给电机增加阻力观察电流上升。关闭电机观察电流回落到 0状态变为停机。人为堵转电机触发过流保护蜂鸣器响PWM 关闭。这个流程能展示 MCU、ADC、PWM、显示、报警、状态判断的完整链路比单纯显示一个电流数字更有说服力。8. 常见问题排查按这个顺序查8.1 电压检测显示为 0检查顺序用万用表量分压电阻输入点确认有电机电源电压。量 ADC 引脚电压确认是否在 0 到 3.3V 之间。检查程序里 ADC 通道号是否对应实际引脚。检查 ADC 初始化是否成功参考电压设置是否正确。如果 ADC 引脚被复用成其他功能也会导致采样不到正确值。很多时候显示 0 不是数学公式错而是引脚配置或者硬件没接线。8.2 电流显示像随机数一样跳动可能原因采样时间太短信号还没稳定。运放电源没有去耦电机电流冲击影响内部参考。采样点正好在 PWM 开关瞬间造成尖峰。地线回路不合适采样地和电机地共用造成噪声。滤波不够。排查时可以先用固定电压输入模拟电流信号确认运放和 ADC 链路正常再接电机做实际测试。这样能区分是信号链路问题还是电机噪声问题。8.3 堵转保护没有触发先检查电流阈值设置再检查堵转持续时间。有人会直接设过流阈值为 1A但电机启动瞬间电流可能到 2A如果程序里持续判断马上就会误报或者触发了保护但状态很快恢复。要确认现场是不是真的堵转并且要给连续异常计数留出时间。另外如果采样的是平均电流堵转时平均值确实会上升但上升幅度取决于电源能力和采样电阻。电源能力太弱时堵转时电压掉得很低电流可能并不会太大这时只靠电流阈值判断不够还要结合电压下降一起判断。8.4 STM32 开发环境编译报错大多数是工程模板问题没有安装对应型号的器件包。打开工程时选错了芯片型号。固件库版本不匹配。编译环境缺少必要的宏定义。用了高版本 Keil 打开低版本工程出现兼容提示。建议固定一套开发环境Keil 5 某个版本配 F1 系列器件包配相同版本的 STM32CubeMX 生成的 HAL 或标准库工程。不要频繁升级编译器版本否则容易出现莫名其妙的编译差异。9. 资源与性能边界别把“能跑”当成“能批量化”9.1 低配 MCU 能做什么STM32F103C8T6 这类芯片资源有限Flash 64KBRAM 20KB。主频最高 72MHz。ADC 12 位单次转换时间在 1us 级别。可用的定时器足够做 PWM 输出和输入捕获。做单路或者双路电机状态检测完全够用但如果同时处理多路高分辨率 ADC、显示刷新、串口打印、复杂算法就要留意 CPU 占用率。尤其是不要在主循环里用大量软件延时刷新 OLED否则采样频率会被压得很低。9.2 批量任务的临界在哪里如果只做一个演示项目程序怎么写都行。但如果要连续监测多台电机或者要做大量数据的采集和记录就要考虑ADC 采样率是否够。数据缓存放在哪里RAM 是否紧张。串口打印是否会影响采样时序。状态判断和显示刷新是否互相阻塞。简单的办法是让“采样、计算”在定时器中断里完成把结果显示放到主循环。这样即使刷新显示慢一点也不会影响核心采样。9.3 什么时候应该升级主控如果你遇到以下情况建议从 F103 升级到 F407 或者 G4 系列需要更高分辨率或者多路同步采样。需要做无刷电机 FOC 控制。需要同时处理显示、通信、控制、外部 Flash 记录等复杂任务。需要更快的主频和更多 RAM。G4 系列本身就偏向电机控制场景片上有比较丰富的模拟外设和高级定时器。不过那是另一个项目的话题前期用 F103 打基础完全没问题。10. 几个落地建议特别写给做毕业设计的同学10.1 先跑单条链路再做完整系统不要一次性把所有的模块全部焊到一起。我建议的顺序是先点亮一块屏幕。再让 ADC 采集一个稳定电压比如用一个电位器分压。再把分压网络接入 12V测试电压检测。再接入采样电阻和运放测试电流检测。最后接电机观察运行、负载、堵转三种情况。每步都验证成功再做下一步。这样即使出问题也能快速定位到具体模块。10.2 不要忽视电源设计和地线电机一启动电流会突然增大如果控制电路电源和电机共用同一路ADC 采样值经常会波动。解决办法是控制电源用独立的 5V 或者 3.3V电机电源单独 12V。两边地线在电源入口处单点连接避免大电流地环路干扰。这个细节在很多项目里都会遇到。检测电路本身没错程序也没错但采样乱跳最终查下来往往是地线布局问题。10.3 记录数据用串口和 Excel 分析调试阶段不要只盯着 OLED 看最好把串口数据保存下来用 Excel 或者简单的脚本画一画电压电流曲线。观察电机启动阶段电流尖峰有多大空载稳定后电流是多少堵转时电流增长到多少这些数据可以帮你设置更合理的阈值。我这里说的“Excel”只是一种简单方式实际用串口助手保存文本转 CSV 就能分析。重点是你要有一个能对比“状态变化”与“电流变化”的过程而不是只看瞬间读数。10.4 给文档和代码留好注释如果是毕设项目最终打分往往不只看实物演示还要看设计说明、代码结构、测试数据和结果分析。建议在代码里按模块写注释说明每个函数的输入输出含义把电压换算、电流换算、阈值判断的逻辑写清楚再配合测试数据表格说明系统正常工作。这会让整个项目显得完整且可信。结束语这篇内容更像是一次基于 STM32 的电机状态检测实操拆解。电压检测解决的是“电源侧高电压怎么安全送给 MCU 读”电流检测解决的是“怎么把电流变化转换成 MCU 能理解的数字”而状态判断则把这两个数值变成可执行的动作。这套链路学会了再去扩展多路检测、转速采集、PID 调速或者无刷电机控制都会顺手很多。真正落地时我最建议你先从最小样例开始一块 F103 核心板一块 OLED一个电位器调电压先把 ADC 采样跑稳定再接入电机。低配设备也能完成核心验证但要注意地线、电源和阈值设置这些细节。先把单路跑稳再谈批量和闭环控制这是做嵌入式检测项目最不容易踩坑的顺序。