
一、目标在掌握了按键控制 LED 的模块化编程后我开始尝试处理模拟量输入。本实验的目标是利用光敏电阻检测环境亮度并据此控制蜂鸣器的报警。这次的重点依然是代码封装。我将“光敏传感器读取”和“蜂鸣器控制”分别封装成独立的模块主函数只负责逻辑判断。虽然目前用的是简单的软件计数法来模拟阈值触发但这让我对 GPIO 输入输出配合有了更深的理解。二、硬件连接说明光敏传感器模块DO 引脚接 STM32 的 PA1或其他 GPIO用于输出高低电平亮/暗。蜂鸣器模块I/O 引脚接 PB12低电平触发鸣叫。原理简述当环境光线变暗时光敏模块输出高电平程序通过累加计数来判断是否达到报警阈值从而驱动蜂鸣器响一声并重置计数。三、代码块main主函数#includestm32f10x.h// Device header#includedelay.h#includebuzzer.h#includelightsensor.huint16_tnumber0;intmain(){BUZZER__init();lightsensor__init();while(1){if(lightsensor_get()1){number30;}if(number300){BUZZER_on();number0;Delay_ms(100);}else{BUZZER_off();}Delay_ms(30);}}buzzer.c#includestm32f10x.h// Device headervoidBUZZER__init(void){RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitTypeDef GPIO_InitStruct1;GPIO_InitStruct1.GPIO_ModeGPIO_Mode_Out_PP;GPIO_InitStruct1.GPIO_PinGPIO_Pin_12;GPIO_InitStruct1.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(GPIOB,GPIO_InitStruct1);GPIO_SetBits(GPIOB,GPIO_Pin_12);}voidBUZZER_on(void){GPIO_ResetBits(GPIOB,GPIO_Pin_12);}voidBUZZER_off(void){GPIO_SetBits(GPIOB,GPIO_Pin_12);}voidBUZZER_turn(void){if(GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_12)0){GPIO_SetBits(GPIOB,GPIO_Pin_12);}else{GPIO_ResetBits(GPIOB,GPIO_Pin_12);}}lightsensor#includestm32f10x.h// Device headervoidlightsensor__init(void){RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitTypeDef GPIO_InitStruct1;GPIO_InitStruct1.GPIO_ModeGPIO_Mode_IPU;GPIO_InitStruct1.GPIO_PinGPIO_Pin_13;GPIO_InitStruct1.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(GPIOB,GPIO_InitStruct1);GPIO_SetBits(GPIOB,GPIO_Pin_13);}uint8_tlightsensor_get(void){returnGPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13);}四、个人学习心得与踩坑记录作为一个刚入门 STM32 的初学者这次写代码时我又遇到了一些“小麻烦”但也收获颇丰关于变量类型的选择一开始我把 number 定义成了 uint8_t 结果发现最大只能存 255永远达不到 300 的阈值蜂鸣器死活不响。后来改成 uint16_t 才解决。这个低级错误提醒我定义变量时一定要先算好数据范围对“软硬结合”的初体验以前觉得代码就是代码现在发现代码必须配合硬件特性。比如那个 Delay_ms(30) 如果去掉它循环跑得太快 number 瞬间就爆表了蜂鸣器就会一直狂叫。原来延时不仅仅是为了让人眼看清更是为了配合程序的逻辑节奏。封装带来的便利这次直接调用 lightsensor_get() 完全不用去管底层是读哪个寄存器这种感觉太棒了我觉得这就是模块化的魅力让我能专注于逻辑本身。五、存在的不足与改进方向目前的程序虽然能跑但我深知这只是最基础的“玩具级”实现还有很多需要向大佬们学习的地方阈值设定的随意性现在的 30 和 300 都是我在 while 循环里试出来的“玄学数字”。如果环境光变化或者延时时间改变这些数字就得重调。我知道应该用 ADC 采集具体电压值来做精确判断但目前还没学会 ADC只能用 GPIO 凑合一下。阻塞式延时的弊端这里的 Delay_ms(100) 会让 CPU 傻等 100 毫秒这段时间里系统是什么都做不了的。如果以后要同时控制电机或者屏幕这种写法肯定不行。定时器中断是我接下来的必学内容。缺乏迟滞比较现在的逻辑在临界点可能会让蜂鸣器“抖动”响一下停一下。如果能加入类似“施密特触发”的逻辑比如大于 300 响小于 200 才停效果应该会好很多。