前阵子帮学弟改毕设的时候翻到这么个STM32做的智能窗帘晾衣架方案,刚好是那种没实物但资料全到能直接套的DIY向项目,特别适合手头上没零件又想攒项目的朋友唠唠

张开发
2026/4/4 19:20:59 15 分钟阅读
前阵子帮学弟改毕设的时候翻到这么个STM32做的智能窗帘晾衣架方案,刚好是那种没实物但资料全到能直接套的DIY向项目,特别适合手头上没零件又想攒项目的朋友唠唠
基于STM32单片机的智能窗帘/晾衣架系统资料无实物仅提供资料和配套报告支持光线雨滴定时开关功能STM32单片机负责数据处理OLED显示模式、光照强度、时间等信息光敏传感器采集光照雨滴传感器检测天气定时模式可设置关闭时间按键用于模式切换和参数调整适合DIY爱好者和项目开发者先给大家捋捋整体逻辑这玩意就是把STM32当大脑光敏传感器当“眼睛”测光照雨滴传感器当“天气预报员”测有没有下雨按键用来切模式改参数OLED屏幕把当前状态全给你摆出来还能定时开关不管是学生党做课程设计还是DIY爱好者折腾小玩意都够用。先唠最基础的光照采集模块毕竟自动开关窗帘的核心依据就是光照强度嘛很多新手一开始怕ADC配置麻烦其实STM32的HAL库已经把坑填得差不多了我把精简后的核心代码扒出来给大家看// ADC初始化PA0接光敏传感器模块 void ADC1_Init(void) { GPIO_InitTypeDef GPIO_InitStruct {0}; ADC_HandleTypeDef hadc1; // 先开时钟STM32的传统艺能 __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_ADC1_CLK_ENABLE(); // 把PA0配置成模拟输入光敏模块直接插这就行 GPIO_InitStruct.Pin GPIO_PIN_0; GPIO_InitStruct.Mode GPIO_MODE_ANALOG; HAL_GPIO_Init(GPIOA, GPIO_InitStruct); // ADC基础配置用12位分辨率足够日常用了 hadc1.Instance ADC1; hadc1.Init.ScanConvMode DISABLE; hadc1.Init.ContinuousConvMode ENABLE; hadc1.Init.ExternalTrigConv ADC_SOFTWARE_START; hadc1.Init.DataAlign ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion 1; HAL_ADC_Init(hadc1); // 绑定通道0也就是PA0 ADC_ChannelConfTypeDef sConfig {0}; sConfig.Channel ADC_CHANNEL_0; sConfig.Rank 1; sConfig.SamplingTime ADC_SAMPLETIME_28CYCLES; HAL_ADC_ConfigChannel(hadc1, sConfig); HAL_ADC_Start(hadc1); } // 直接调用就能拿到当前光敏的ADC数值范围0-4095 uint16_t Get_Light(void) { HAL_ADC_PollForConversion(hadc1, 100); return HAL_ADC_GetValue(hadc1); }这段代码其实没啥花活就是把ADC配置成连续读取模式每次调用就能拿到当前的光照数值。我当初第一次用的时候踩过坑没开对应引脚的时钟结果死活读不到值后来翻了HAL库的官方例程才搞定。而且不用非得转换成lux直接判断数值高低就行——比如晴天的时候数值大概在3000阴天可能就1000以内直接写if(Get_Light() 1000)就可以触发开窗帘的动作新手不用纠结校准的事先跑通再说。雨滴传感器就更简单了大部分模块都是输出高低电平没雨的时候拉高下雨的时候拉低初始化代码甚至比ADC还短// 雨滴传感器初始化PA1接模块输出 void Rain_Init(void) { GPIO_InitTypeDef GPIO_InitStruct {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); // 配置成上拉输入避免浮空乱跳 GPIO_InitStruct.Pin GPIO_PIN_1; GPIO_InitStruct.Mode GPIO_MODE_INPUT; GPIO_InitStruct.Pull GPIO_PULLUP; HAL_GPIO_Init(GPIOA, GPIO_InitStruct); } // 检测是否下雨返回1就是下雨了 uint8_t Get_Rain(void) { // 模块下雨时输出低电平取反一下就能拿到正确状态 return !HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1); }我当初第一次接雨滴模块的时候居然忘了加消抖结果下雨的时候传感器疯狂跳变后来加了个10ms的延时滤波就搞定了这点新手一定要注意。接下来是OLED显示模块这个是让项目看起来像那么回事的关键我用的是12864的SSD1306屏幕I2C接口直接抄正点原子的驱动改改引脚就能用。贴一段主循环里的显示代码// 主循环里的显示逻辑每100ms刷新一次 char buf[32]; uint16_t light_val Get_Light(); uint8_t rain_state Get_Rain(); OLED_Clear(); // 一定要清屏不然会叠残影我当初踩过这个坑 // 显示光照强度 sprintf(buf, Light: %d, light_val); OLED_ShowString(0, 0, (uint8_t*)buf, 16); // 显示下雨状态 sprintf(buf, Rain: %s, rain_state ? YES : NO); OLED_ShowString(0, 20, (uint8_t*)buf, 16); // 显示当前模式和定时时间 sprintf(buf, Mode: Auto Time: %dh, set_time); OLED_ShowString(0, 40, (uint8_t*)buf, 16); OLED_Refresh(); // 刷新屏幕才会显示出来这里用sprintf格式化字符串是最省事的写法不用自己一个个点阵拼字符新手直接抄就行记得改一下字体大小和显示位置就行。按键切换和定时功能按键这块我推荐用扫描法不用搞外部中断主循环里扫一下就行还能顺便做消抖// 按键扫描返回键值1模式切换2加定时时间3减定时时间 uint8_t Key_Scan(void) { static uint8_t key_up 1; // 静态变量记录按键状态 uint8_t key_val 0; if(key_up (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2) 0 || HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_3) 0 || HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) 0)) { HAL_Delay(10); // 消抖延时避免误触发 key_up 0; // 判断按下的是哪个按键 if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2) 0) key_val 1; else if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_3) 0) key_val 2; else if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) 0) key_val 3; } else if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2) 1 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_3) 1 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) 1) { key_up 1; // 按键松开了重置状态 } return key_val; }定时功能我是用定时器中断做的设置1秒中断一次计数到3600就是1小时配合按键修改定时时间逻辑特别简单比如短按加1小时长按减1小时稍微改一下扫描代码就能实现。最后是主循环的整体逻辑其实就是个流水线先扫按键改参数再读传感器数据然后根据当前模式执行动作最后刷新屏幕。贴一段精简后的主循环int main(void) { HAL_Init(); SystemClock_Config(); // 这个是STM32CubeMX自动生成的不用自己改 ADC1_Init(); Rain_Init(); OLED_Init(); uint8_t current_mode 0; // 0自动模式1定时模式2手动模式 uint8_t set_time 1; // 默认定时1小时 uint32_t timer_cnt 0; while (1) { uint8_t key Key_Scan(); // 按键逻辑 if(key 1) current_mode (current_mode 1) % 3; // 循环切换模式 else if(key 2) set_time (set_time 1) % 24; // 最多定时23小时 else if(key 3) set_time set_time 0 ? set_time -1 : 23; // 定时模式逻辑 if(current_mode 1) { timer_cnt; if(timer_cnt 3600) { timer_cnt 0; set_time--; if(set_time 0) { // 到点了执行开关动作 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET); } } } // 自动模式逻辑 if(current_mode 0) { if(light_val 1000) HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET); // 开窗帘 else if(light_val 3000) HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); // 关窗帘 if(rain_state 1) HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET); // 下雨关晾衣架 } Update_OLED(); // 就是之前的显示代码封装成函数就行 HAL_Delay(100); } }这里要注意STM32的GPIO输出电流不够驱动电机一定要加继电器或者L298N电机驱动模块我当初差点直接用GPIO接电机还好学长提醒了不然板子直接冒烟。最后唠两句这个项目真的特别适合入门不管是想练手STM32还是想凑个课程设计/毕设项目都能直接套现成的资料和代码。而且就算没有实物用Proteus画个仿真图就能跑起来论坛里也有很多配套的报告模板可以直接改。唯一要注意的就是引脚对应和传感器阈值调整别直接抄代码就完事根据自己用的模块改一改就能用。基于STM32单片机的智能窗帘/晾衣架系统资料无实物仅提供资料和配套报告支持光线雨滴定时开关功能STM32单片机负责数据处理OLED显示模式、光照强度、时间等信息光敏传感器采集光照雨滴传感器检测天气定时模式可设置关闭时间按键用于模式切换和参数调整适合DIY爱好者和项目开发者

更多文章