news 2026/9/16 4:43:41

基于STM32的智能晾衣架源码:状态机驱动的嵌入式课设指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于STM32的智能晾衣架源码:状态机驱动的嵌入式课设指南

简介:一套基于STM32单片机的智能晾衣架源码,面向高校课程设计与期末大作业场景,适合有一定C语言基础、正在学习STM32外设应用的入门至中级开发者。项目包含完整的工程文件,代码注释详尽,从硬件初始化、传感器数据采集到电机控制与晾衣逻辑均清晰可读,新手也能快速理解并二次修改部署。资源包共51个文件,以c源文件、h头文件为核心,另有uvproj工程文件、hex烧录文件、lst及obj编译中间文件、m51映射文件等,方便直接打开工程或烧录运行,压缩包仅133KB,轻量易用。目前已有261人学习下载,作为高分课设范例,能帮助读者快速搭建智能晾衣架系统原型,学习STM32的GPIO、定时器、ADC、PWM等常见外设的综合使用方法,是期末答辩与项目实战的实用参考。

1. 天气突变时,晾衣架的反应速度就是课设的分水岭

一个实际下雨场景里,雨滴传感器从第一滴雨落到模拟输出变化,可能只需要几十毫秒,但如果你让单片机在主循环里用延时函数等待电机转完,整套系统可能卡在收衣过程中,雨已经打湿半边衣服。基于STM32单片机的智能晾衣架源码,核心不是“有没有雨滴传感器”,而是把传感器、电机、限位开关、模式切换整理成一套可靠的状态机。高分课设和普通仿真的差别,通常就落在中断处理、按键消抖、传感器去抖、电机逻辑互斥这些容易被忽略的细节上。

这篇博文会按硬件选型、源码结构、CubeMX工程搭建、关键功能实现、答辩验证五部分展开。面向正在做STM32单片机课设的学生,也适合想用智能晾衣架项目入门嵌入式状态机设计的开发者。内容里出现的代码和参数都能直接复现,只要你有一块STM32F103C8T6最小系统板,外加常见传感器模块和电机驱动,就能在两天内跑通。

2. 智能晾衣架的STM32硬件设计:传感器选型与外设分配

一个带“高分课设”标签的智能晾衣架系统,首先要让评审老师看到硬件选型有明确依据,而不是把淘宝模块堆在一起。常见方案里,雨滴传感器用LM393比较器输出的数字量或模拟量,光线用光敏电阻模块,温度和湿度用DHT11,电机用5V步进电机或带减速箱的直流电机。需要说明的是,我一般不建议用DHT11做晾衣场景的主力传感器,因为它响应偏慢且精度一般,但它便宜、串口调试方便,用于课设答辩完全够用。如果你手头有SHT30,精度和通信方式都会更好。

2.1 雨滴、光照、温湿度传感器的选型与接线差异

雨滴传感器的核心是PCB上交叉排列的裸露铜箔,通过水滴改变电极间阻抗,再由LM393比较器输出数字信号。检测灵敏度和防水处理是两个重点,传感器板本身不防水,长期暴露在室外会氧化,所以实际部署时需要在板子表面喷一层三防漆,或者在结构上设计一个防雨罩。接线方面,数字量DO输出可以直接接STM32普通GPIO,模拟量AO接ADC通道。为了让源码更稳定,建议数字量采用“雨天为低电平”的接线逻辑:干燥时DO输出高,水滴落下时输出低。

光照模块一般也是LM393输出,接收光强变化。晾衣架里它的作用是“白天且光线充足时允许自动晾出”,避免夜间误动作。温湿度用DHT11单总线即可,但注意DHT11的1秒采样间隔,不能放在高频中断里。如果你用的是ESP8266做远程控制,DHT11数据还能顺便上传,但课设源码建议先把本地逻辑做完整。

2.2 STM32单片机外设资源分配与引脚映射表

以最常见的STM32F103C8T6为例,它有两个I2C、三个USART、两个SPI,加上足够多的定时器,做晾衣架绰绰有余。引脚映射表是课设文档中必须出现的部分,它体现你对GPIO复用功能清楚。下面是我在F103C8T6上常用的分配方式:

功能模块信号STM32引脚配置模式
雨滴传感器DOPA0输入上拉
雨滴传感器AOPA1ADC1_IN1
光敏传感器DOPA2输入上拉
DHT11温湿度DATAPA3开漏输出/输入
OLED(I2C)SCLPB6复用开漏
OLED(I2C)SDAPB7复用开漏
按键模式切换KEY1PB12输入上拉
手动收回按键KEY2PB13输入上拉
电机正转IN1PB14推挽输出
电机反转IN2PB15推挽输出
限位开关(晾出到位)SW1PA4输入上拉
限位开关(收回到位)SW2PA5输入上拉
蜂鸣器BEEPPB0推挽输出
状态LEDLEDPC13推挽输出

这里要特别说明,PA0、PA1、PA2、PA3这几个引脚在F103上也是RTC、ADC、串口等功能的复用引脚,如果同时使用串口1,需要避免TX/RX引脚冲突。常用做法是把串口1的TX和RX放到PA9和PA10,这个表格里为了给传感器节省空间,串口日志就走PA9/PA10,完全不影响ADC。

2.3 电源设计与必加的去耦电容

电源是整个智能晾衣架课设最容易翻车的地方。STM32F103C8T6运行电流在几十毫安,但直流电机启动瞬间电流可能到500mA甚至更高,如果使用同一个5V USB供电,电机一转,单片机就会复位。常见做法是用AMS1117-3.3将5V降到3.3V供给MCU,电机驱动模块直接吃5V,并且单独从USB口分一路给电机驱动。在电机驱动电源两端并联100uF电解电容和0.1uF陶瓷电容,去耦位置要尽量靠近驱动芯片。另外一个容易忽略的点是,步进电机驱动板(比如ULN2003)的使能信号不需要外部上拉,但直流电机驱动芯片L298N的逻辑电源需要和电机电源共地,否则输入引脚无法形成回路。

提示:凡是涉及电机的课设,复位按钮不能省。电机制动时会产生反向电动势,如果主板没有复位按钮,测试时反复插拔USB会非常痛苦。

3. 智能晾衣架源码结构与CubeMX初始化工程搭建

源代码的好坏不是看有多少行,而是看模块边界是否清晰。一个能拿高分的STM32智能晾衣架源码,通常包括main.cbsp_sensor.cbsp_motor.cbsp_oled.cbsp_key.capp_tasks.cstate_machine.c。评审老师翻代码时,最先看的是头文件中的函数命名和宏定义。下面就是一套可直接套用的目录结构。

3.1 高分课设源码目录结构:模块化比注释更重要

smart_drying_rack/ ├── Core/ │ ├── Inc/ │ │ ├── main.h │ │ └── state_machine.h │ ├── Src/ │ │ ├── main.c │ │ ├── state_machine.c │ │ └── app_tasks.c ├── Drivers/ │ ├── BSP/ │ │ ├── bsp_sensor.c │ │ ├── bsp_sensor.h │ │ ├── bsp_motor.c │ │ ├── bsp_motor.h │ │ ├── bsp_oled.c │ │ └── bsp_oled.h │ └── ... └── User/ └── debug_uart.c

每个模块只做一件事:bsp_sensor.c负责读传感器原始值,state_machine.c负责状态迁移,app_tasks.c负责把传感器值喂给状态机。这样的好处是后期换传感器时,只改bsp层,不动状态机。

3.2 用STM32CubeMX初始化智能晾衣架的时钟与GPIO

现在即使是课设,也不建议手写寄存器初始化。STM32CubeMX生成代码后,再在Keil5里添加业务代码是效率最高的方式。CubeMX里需要配置的内容如下:

  1. 系统时钟:RCC选择HSE外部晶振,HCLK设为72MHz,APB1总线设为36MHz,APB2为72MHz。
  2. 调试接口:SYS选Serial Wire,否则烧录一次后仿真器可能无法连接。
  3. GPIO:按上文引脚表将PA0、PA2、PA4、PA5、PB12、PB13配置为输入上拉,PA1配置为模拟输入,PB14、PB15、PB0配置为推挽输出。
  4. ADC1:使能IN1,采样周期设为55.5周期,扫描模式关闭。
  5. I2C1:用于OLED,标准模式,速率100kHz。
  6. 定时器TIM2:用于传感器状态机轮询,配置为1ms中断。

生成工程后,在main.cwhile(1)外面,记得关闭所有未使用外设的时钟。CubeMX默认会把所有时钟都打开,这对低电压场景不友好,高分的说法是“低功耗优化”。

3.3 Keil5编译烧录的最小验证命令

在Keil5中首次编译前,必须检查三个地方:Target里选择STM32F103C8,Output页勾选Create HEX File,Magic Wand里把Debugger改为ST-Link或J-Link。用ST-Link烧录时,常用命令是:

ST-LINK_CLI.exe -c SWD UR -P build/dev.hex -Rst

参数说明:-c表示连接,SWD指定连接方式,UR表示热复位,-P指定hex文件路径,-Rst指定烧录后复位运行。如果你更习惯用图形界面,直接在Keil5里按F8编译,再按F5下载。烧录后先别急着接传感器,打开串口助手看复位日志是否打印,这一步能排除焊接和电源问题。

4. 关键功能模块实现:状态机、传感器滤波与电机保护

智能晾衣架的“智能”二字,全部体现在状态机里。很多课设源码喜欢用if(rain == 1) motor_reverse(),这种写法在只有一个触发条件时能跑,但一旦加入“手动模式”、“收回到位”、“电机堵转”,代码就变成一团乱麻。用显式状态机,是代码质量提升最明显的一步。

4.1 用状态机组织晾衣架的核心逻辑

晾衣架可以拆成四个稳定状态:已缩回、晾出中、已晾出、缩回中。再加上两个辅助状态:故障停止、手动暂停。状态迁移条件如下:

  • 已缩回 + 自动模式 + 无雨且光照充足 -> 晾出中
  • 晾出中 + 限位开关SW1触发 -> 已晾出
  • 已晾出 + 自动模式 + 有雨 -> 缩回中
  • 缩回中 + 限位开关SW2触发 -> 已缩回
  • 任意状态下切换到手动模式 -> 手动暂停

state_machine.c中,用枚举定义状态,用函数指针或switch执行迁移,下面是一种可读性高的写法:

typedef enum { STATE_RETRACTED, STATE_EXTENDING, STATE_EXTENDED, STATE_RETRACTING, STATE_FAULT, STATE_MANUAL } ClothesRackState; ClothesRackState g_state = STATE_RETRACTED; void state_machine_run(input_t *input) { switch (g_state) { case STATE_RETRACTED: if (input->auto_mode && !input->rain && input->light) { motor_extend_start(); g_state = STATE_EXTENDING; } break; case STATE_EXTENDING: if (input->limit_extend) { motor_stop(); g_state = STATE_EXTENDED; } else if (input->rain) { motor_retract_start(); g_state = STATE_RETRACTING; } break; case STATE_EXTENDED: if (input->auto_mode && input->rain) { motor_retract_start(); g_state = STATE_RETRACTING; } break; case STATE_RETRACTING: if (input->limit_retract) { motor_stop(); g_state = STATE_RETRACTED; } break; default: motor_stop(); g_state = STATE_FAULT; break; } }

这段代码的逻辑说明:input_t结构体保存着本次轮询周期内所有传感器的有效状态;limit_extendlimit_retract分别来自两个限位开关。STATE_EXTENDING状态下如果突然下雨,需要立刻反向收回,这是晾衣架和普通门禁电机最大的不同。在这里,限位开关是最后一层保护,不能省略。

4.2 雨滴与光线传感器的输入滤波和采样参数

STM32的GPIO输入引脚悬空时极易受到电机干扰,雨滴传感器输出出现毛刺是常态。如果直接读取,一次抖动就会让状态机误切换。常见做法是在ADC和GPIO读函数里加滤波。我一般用软件防抖:连续读到10次同一电平才确认有效。ADC值则需要做中值滤波,取5次采样排序后取中间值,能够滤掉水滴溅射的尖峰。

#define RAIN_SAMPLE_TIMES 10 #define ADC_SAMPLE_NUM 5 uint8_t rain_digital_filtered(void) { uint8_t stable_cnt = 0; for (uint8_t i = 0; i < RAIN_SAMPLE_TIMES; i++) { if (HAL_GPIO_ReadPin(RAIN_DO_PORT, RAIN_DO_PIN) == GPIO_PIN_RESET) { stable_cnt++; } else { stable_cnt = 0; } HAL_Delay(1); } return (stable_cnt >= RAIN_SAMPLE_TIMES); }

这里读取10次是为了滤除雨滴传感器上的水膜抖动,但如果每次都阻塞10毫秒,状态机就会卡顿。正确做法是把采样放进定时器中断里,每毫秒采样一次,再在200毫秒后做累计判断。ADC部分类似,不要在主循环里做while等待。

4.3 电机正反转与限位保护必须做的互斥逻辑

直流电机驱动模块如果同时收到正转和反转指令,轻则电机嗡嗡响,重则烧毁驱动。源码里必须加一个motor_dir变量,在motor_extend_startmotor_retract_start内部检查当前方向:

void motor_retract_start(void) { if (motor_dir == MOTOR_RETRACT) return; motor_dir = MOTOR_RETRACT; HAL_GPIO_WritePin(MOTOR_IN1_PORT, MOTOR_IN1_PIN, GPIO_PIN_RESET); HAL_GPIO_WritePin(MOTOR_IN2_PORT, MOTOR_IN2_PIN, GPIO_PIN_SET); }

电机的限位开关接到中断引脚更好,但为了源码更直观,也可以放在10ms轮询里。要注意的是,电机在到达限位后瞬间停止,会有惯性,电机轴可能滑过限位位置,所以源码中限位触发后还要再给一个50ms的停止保护期,避免紧接着再次启动。

5. 智能晾衣架源码的进阶验证:串口模拟传感器与答辩展示

课设源码写完,最怕评委现场问“如果传感器坏了怎么办”。这个时候,利用STM32的串口做一个调试命令入口,比临时改代码重新烧录要专业得多。在debug_uart.c里实现一个简单的指令协议,rain_on模拟下雨,rain_off模拟雨停,light_on模拟光照充足。命令通过USART1接收,在主循环中解析并覆盖input_t结构体的值。

void debug_parse(char *cmd) { if (strcmp(cmd, "rain_on") == 0) { input_override.rain = 1; } else if (strcmp(cmd, "rain_off") == 0) { input_override.rain = 0; } }

解析完成后,把override_enable位置1,状态机在读取真实传感器前,先检查input_override,被覆盖后,状态机就会按模拟数据动作。这个能力在答辩现场就是“模块化测试”的最好证据:不需要对着晾衣架倒水,只需要串口敲一条命令,就能看到电机动作。这也是我在调课时最常用到的验证方法,比反复拆接线省时间。

另一个加分点是异常恢复测试,故意拨动限位开关让它停在半路,然后发送rain_offlight_on,观察状态机是否能从卡住的状态恢复。如果能在源码里加入“限位开关10秒无响应就自动停止并鸣叫蜂鸣器”的逻辑,那就成了整个课设的亮点,答辩论据也足够完整。智能晾衣架源码的高分关键从来不是代码行数,而是用最少的资源把不该发生的动作全部挡在了状态机之外。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 4:43:31

JSP本质是Servlet?一文搞懂JavaWeb动态页面核心技术

先说个写JavaWeb很容易遇到的事&#xff1a;学完Servlet之后&#xff0c;你可能信心满满地想用纯Servlet写一个页面&#xff0c;结果写了一半人就麻了。输出一行HTML需要写一句out.println("<html>")&#xff0c;输出一个表格要循环拼字符串&#xff0c;前端改…

作者头像 李华
网站建设 2026/9/16 4:40:06

新手入门必看:宁波网站推广优化公司怎么样才靠谱

新手入门必看:宁波网站推广优化公司怎么样才靠谱 网站做好了没人访问,这种憋屈感谁懂?很多老板花大几万做的官网,上线三个月,后台一看,日均IP不到10,连自己人都找不到。这时候找“宁波网站推广优化公司”就成了救命稻草,但市面上水太深,新手入门第一步就是别被忽悠。…

作者头像 李华
网站建设 2026/9/16 4:39:47

AI编码代理pi的Windows桌面端封装实践:轻量替代VS Code

最近我把 pi 这个 AI 编码代理从 VS Code 里“请”了出来&#xff0c;给它单独配了个 Windows 桌面端。折腾完之后最大的感受是&#xff1a;同样是那个聊天界面&#xff0c;少了编辑器这层壳&#xff0c;启动速度快了不止一倍&#xff0c;窗口也不再被项目目录绑着走。以前想跟…

作者头像 李华
网站建设 2026/9/16 4:38:37

装修ERP实测:三个月跑五家,成本数据跑通的关键与避坑指南

装修ERP系统实测推荐&#xff1a;三个月跑了五家&#xff0c;说点第三方的大实话做装修这行的人&#xff0c;多少都动过上ERP的念头。图纸签了、工地开工了&#xff0c;材料却不知道谁去买的、增项费用谁批的、尾款收没收回来&#xff0c;全靠微信群和Excel硬扛。等到公司年产值…

作者头像 李华
网站建设 2026/9/16 4:36:50

从Socket层手写MCP Server:零依赖实现工具通信协议

1. 为什么现在必须亲手写一个MCP Server——不是用现成SDK&#xff0c;而是从Socket层开始“MCP Server”这个词最近三个月在开发者社区的搜索量翻了4倍&#xff0c;但绝大多数人点开教程后第一眼看到的是“安装yakit插件”“配置Figma Token”“下载蓝湖客户端”&#xff0c;然…

作者头像 李华
网站建设 2026/9/16 4:36:21

MCP251863+RA8:构建高可靠CAN FD确定性通信架构

1. 项目概述&#xff1a;当一颗CAN FD控制器遇上一颗车规级MCU&#xff0c;通信架构正在被重写最近在几个汽车电子研发群里看到不少工程师在讨论MCP251863和R7KA8D2KFLCAC这对组合——不是单纯问“能不能用”&#xff0c;而是反复确认“为什么非得用它”“有没有更便宜的替代方…

作者头像 李华