32单片机 小项目2-按钮和光敏传感器控制灯泡和蜂鸣器 一、目标在掌握了按键控制 LED 的模块化编程后我开始尝试处理多条件输入。本实验的目标是利用光敏传感器PA4和独立按键PA5的双重信号联动控制 LED 灯PA0和蜂鸣器PA1的工作状态。这次的重点依然是代码封装。我将“LED控制”、“蜂鸣器控制”和“按键/传感器初始化”分别封装成独立的模块主函数只负责逻辑判断。虽然目前用的是简单的 GPIO 读取法来触发但这让我对 GPIO 输入输出配合有了更深的理解。二、硬件连接说明LED模块I/O 引脚接 PA0低电平触发点亮或高电平根据你的电路设计。蜂鸣器模块I/O 引脚接 PA1低电平触发鸣叫。光敏传感器模块DO 引脚接 STM32 的 PA4用于输出高低电平亮/暗。独立按键模块I/O 引脚接 PA5按下时输出高电平或低电平取决于电路。原理简述当环境光线变化PA41且按键被按下PA51时程序驱动 LED 亮起与蜂鸣器鸣叫 500ms然后熄灭并延时 500ms形成声光报警效果。三、代码块main函数#includestm32f10x.h#includedelay.h#includeLED.hintmain(){led_init();buzzer_init();key_init();while(1){if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_4)1GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_5)0){led0(1);buzzer1(1);Delay_ms(500);led0(0);buzzer1(0);Delay_ms(500);}}}LED模块#include “stm32f10x.h” // Device headervoid led_init(void){RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_ModeGPIO_Mode_Out_PP ;GPIO_InitStruct.GPIO_PinGPIO_Pin_0;GPIO_InitStruct.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(GPIOA,GPIO_InitStruct);GPIO_SetBits(GPIOA,GPIO_Pin_0);}void buzzer_init(void){RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_ModeGPIO_Mode_Out_PP ;GPIO_InitStruct.GPIO_PinGPIO_Pin_1;GPIO_InitStruct.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(GPIOA,GPIO_InitStruct);GPIO_SetBits(GPIOA,GPIO_Pin_1);}void key_init(void){RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_ModeGPIO_Mode_IPU;GPIO_InitStruct.GPIO_PinGPIO_Pin_4 | GPIO_Pin_5;GPIO_InitStruct.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(GPIOA,GPIO_InitStruct);GPIO_SetBits(GPIOA,GPIO_Pin_4 | GPIO_Pin_5);}void led0(uint16_t x){if (x0)GPIO_SetBits(GPIOA,GPIO_Pin_0);if (x1)GPIO_ResetBits(GPIOA,GPIO_Pin_0);}void buzzer1(uint16_t x){if (x0)GPIO_SetBits(GPIOA,GPIO_Pin_1);if (x1)GPIO_ResetBits(GPIOA,GPIO_Pin_1);}四、个人学习心得与踩坑记录作为一个刚入门 STM32 的初学者这次写代码时我又遇到了一些“小麻烦”但也收获颇丰关于变量类型的选择一开始我把 number 定义成了 uint8_t 结果发现最大只能存 255永远达不到 300 的阈值蜂鸣器死活不响。后来改成 uint16_t 才解决。这个低级错误提醒我定义变量时一定要先算好数据范围对“软硬结合”的初体验以前觉得代码就是代码现在发现代码必须配合硬件特性。比如那个 Delay_ms(30) 如果去掉它循环跑得太快 number 瞬间就爆表了蜂鸣器就会一直狂叫。原来延时不仅仅是为了让人眼看清更是为了配合程序的逻辑节奏。封装带来的便利这次直接调用 led0() 和 buzzer1() 完全不用去管底层是读哪个寄存器这种感觉太棒了我觉得这就是模块化的魅力让我能专注于逻辑本身。五、存在的不足与改进方向目前的程序虽然能跑但我深知这只是最基础的“玩具级”实现还有很多需要向大佬们学习的地方阈值设定的随意性现在的判断条件都是我在 while 循环里试出来的“玄学数字”。如果环境光变化剧烈可能需要更稳定的滤波算法。功能单一目前只能实现“同时满足才报警”未来可以尝试增加“或”逻辑或者加入定时器实现更复杂的闪烁模式。代码复用性虽然做了封装但引脚还是硬编码在函数里未来可以改成传参形式让函数更通用。