当前位置: 首页 > news >正文

STM32单片机按键控制LED及光敏传感器控制蜂鸣器

注意:
本文章默认您已经将STM32单片机的启动项以及库函数等前期工作准备就绪。

一、材料清单

1、STM32单片机开发板

2、低电平触发蜂鸣器

3、光敏传感器

4、按钮开关

5、LED灯

二、接线示意图

2. 1、STLINK连接STM32开发板示意图

图片来源:bilibili江协科技

2.2、按键控制LED

图片来源:bilibili江协科技

2.3、光敏传感器控制蜂鸣器

图片来源:bilibili江协科技

三、原理

3.1、按键控制LED

我们知道32开发板中,LED灯可以通过端口置高低电平来点亮,那么因此,也就可以使用按键来控制高低电平,再通过读取连接到按键上的端口的电平来控制LED灯。

这里我们需要了解STM32单片机标准库中的一个函数:GPIO_ReadInputDataBit。GPIO_ReadInputDataBit 是 STM32 标准外设库(Standard Peripheral Library)中的一个函数,用于读取指定 GPIO 引脚的电平状态(输入模式)。

用法如下:

GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

那么我们就可以通过这个函数来读取按键的状态,从而起到控制LED的效果。

注意:使用这个函数前要将引脚配置为输入模式(浮空输入、上/下拉输入)。

如果不清楚32的输入模式可参考3.1小节。

3.2、光敏传感器控制蜂鸣器

我们知道了可以通过GPIO_ReadInputDataBit来读取指定引脚的电平信号,以达到控制输入输出的目的,那么我们就可以同样通过这个函数来读取光敏传感器所连接的引脚的电平状态,以达到控制蜂鸣器的效果。

光敏传感器原理图:

如图所示,当光照变强时,N1的阻值变小,输出低电平,反之输出高电平。

四、编程

4.1、按键控制LED

4.1.1、模块化

在写代码之前,我们先介绍一下编程模块化:模块化是将程序分解为独立、可复用的模块,每个模块负责特定功能。通过高内聚、低耦合的设计,提升代码的可维护性和可扩展性。

所以这次我们用模块化来写:

在工程文件夹中新增Hardware文件夹。

随后打开keil 5:

不要忘记添加到编译选项,不然编译出错哦。

创建这个文件夹的目的是为了让我们能将各个外设分开写程序,防止代码过多引起的阅读困难以及难以维护。

随后在该文件夹添加以下文件:

4.1.2、LED驱动

打开LED.h文件,先添加以下代码:

#ifndef __LED_H//防止头文件重复包含 #define __LED_H//定义该头文件,让其他文件可以调用该源码中的程序 #endif

打开LED.c文件,在这个文件下就可以写我们LED灯的驱动文件了。

#include "stm32f10x.h" // Device header void LED_Init(void)//LED模块初始化 { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_SetBits(GPIOA, GPIO_Pin_1 |GPIO_Pin_2); } void LED1_ON(void) { GPIO_ResetBits(GPIOA, GPIO_Pin_1); } void LED1_OFF(void) { GPIO_SetBits(GPIOA, GPIO_Pin_1); } void LED1_turn(void)//按下点亮,再次按下关闭,利用GPIO_ReadOutputDataBit函数读取当前端口输出状态,如果当前端口输出为0,则置为1,反之置为0 { if(GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1)== 0) { GPIO_SetBits(GPIOA, GPIO_Pin_1); } else { GPIO_ResetBits(GPIOA, GPIO_Pin_1); } } void LED2_ON(void) { GPIO_ResetBits(GPIOA, GPIO_Pin_2); } void LED2_OFF(void) { GPIO_SetBits(GPIOA, GPIO_Pin_2); } void LED2_turn(void) { if(GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_2)== 0) { GPIO_SetBits(GPIOA, GPIO_Pin_2); } else { GPIO_ResetBits(GPIOA, GPIO_Pin_2); } }

写完之后不要忘记在LED.h文件中声明一下哦:

#ifndef __LED_H//防止头文件重复包含 #define __LED_H//定义该头文件,让其他文件可以调用该源码中的程序 void LED_Init(void); void LED1_ON(void); void LED1_OFF(void); void LED2_ON(void); void LED2_OFF(void); void LED1_turn(void); void LED2_turn(void); #endif

4.1.3、按键驱动

同样的我们在Key.h中先添加:

#ifndef __KEY_H//防止头文件重复包含 #define __KEY_H//定义该头文件,让其他文件可以调用该源码中的程序 #endif

随后打开Key.c,写出我们实现的功能:

#include "stm32f10x.h" // Device header #include "Delay.h" void key_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitTypeDef GPIO_InitStrcture; GPIO_InitStrcture.GPIO_Mode = GPIO_Mode_IPU;//上拉输出模式,防止按键悬空,电压不稳定 GPIO_InitStrcture.GPIO_Pin = GPIO_Pin_1| GPIO_Pin_11; GPIO_InitStrcture.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStrcture); } uint8_t Key_GetNum(void)//该函数为获取按键键码的函数,当按键按下时可得到键码 { uint8_t KeyNum = 0; if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0 )//PB1按键检测函数,GPIO_ReadInputDataBit可以读取指定引脚输入的电平 { Delay_ms(20);//消抖 while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0) Delay_ms(20); KeyNum = 1; } if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0 )//PB1按键检测函数,GPIO_ReadInputDataBit可以读取指定引脚输入的电平 { Delay_ms(20);//消抖 while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0) Delay_ms(20); KeyNum = 2; } return KeyNum; }

4.1.4、主函数

这样我们的功能就都实现了,我们只要在主函数main里面进行这些模块的调用就可以了。

注意:我们想要调用其他文件夹里的函数的时候,一定要在代码的最上方添加声明!!!!

在main函数中我们需要先初始化其他模块,也就是启用各个模块的Init()函数,例如我们上面所写的LED_Init()以及Key_Init()。

LED_Init(); key_Init();

之后就是各个模块之间的逻辑处理,我们整合之后就得到了整个main.c:

#include "stm32f10x.h" // Device header #include "Delay.h" #include "LED.h" #include "Key.h" uint8_t KeyNum;//定义一个全局变量,用来存储Key_GetNum中读取到的键码值,来判断哪个按键按下。 int main(void) { LED_Init(); key_Init(); while (1) { KeyNum = Key_GetNum(); if(KeyNum == 1) { LED1_turn(); } else if(KeyNum == 2) { LED2_turn(); } } }

4.2、光敏传感器控制蜂鸣器

接下来我们写光敏传感器控制蜂鸣器的程序,同理:

4.2.1、蜂鸣器模块:

buzzer.h:

#ifndef __BUZZER_H//防止头文件重复包含 #define __BUZZER_H//定义该头文件,让其他文件可以调用该源码中的程序 void Buzzer_Init(void); void Buzzer_ON(void); void Buzzer_OFF(void); void Buzzer_turn(void); #endif

buzzer.c:

#include "stm32f10x.h" // Device header void Buzzer_Init(void)//LED模块初始化 { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_SetBits(GPIOB, GPIO_Pin_12); } void Buzzer_ON(void) { GPIO_ResetBits(GPIOB, GPIO_Pin_12); } void Buzzer_OFF(void) { GPIO_SetBits(GPIOB, GPIO_Pin_12); } void Buzzer_turn(void) { if(GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_12)== 0) { GPIO_SetBits(GPIOB, GPIO_Pin_12); } else { GPIO_ResetBits(GPIOB, GPIO_Pin_12); } }

4.2.2、光敏传感器模块

Lightsensor.h:

#ifndef __LIGHT_SENSOR_H//防止头文件重复包含 #define __LIGHT_SENSOR_H//定义该头文件,让其他文件可以调用该源码中的程序 void Lightsensor_Init(void); uint8_t Lightsensor_Get(void); #endif

Lightsensor.c:

#include "stm32f10x.h" // Device header void Lightsensor_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启外设时钟GPIO口 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入模式,防止电路输入悬空。此时是低电平驱动 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_SetBits(GPIOB, GPIO_Pin_13); } uint8_t Lightsensor_Get(void) { return GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13);//通过获取光源传感器返回到B13口的值来判断。 }

4.2.3、主函数

main.c:

#include "stm32f10x.h" // Device header #include "Delay.h" #include "Buzzer.h" #include "Lightsensor.h" int main(void) { Lightsensor_Init(); Buzzer_Init(); while (1) { Lightsensor_Get(); if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==0 )//如果B13口输入的值为低电平,也就是光线亮的情况下,控制蜂鸣器响 { Buzzer_ON(); Delay_ms(500); } else { Buzzer_OFF(); } } }

五、结语

希望大家可以去理解各个函数是如何实现以及功能的逻辑是怎么完成的,如果不清楚可以参考一下我的上一篇文章。

谢谢观看,如果对您有帮助请留个免费的赞和收藏,谢谢啦!

http://www.jsqmd.com/news/488014/

相关文章:

  • 零基础实战:从零到一,在云服务器上搭建并公网访问你的首个静态网站
  • 矩阵乘法-进阶题8
  • 5步掌握AI视频解说工具:从安装到生成专业视频全攻略
  • Dify异步节点调试不求人:用OpenTelemetry追踪完整链路,5分钟定位Python沙箱阻塞根源
  • CentOS 7.X 极速部署:Socks5与HTTP双代理服务实战
  • MCP采样接口成本失控真相(生产环境5次熔断复盘实录)
  • python中有哪些很重要的知识点?
  • 工厂智能问答客服实战:基于NLP与知识图谱的工业级解决方案
  • 软件缺陷分类、处理流程、管理工具、缺陷报告
  • 【GitHub项目推荐--DeepLX:免费开源的DeepL翻译API替代方案】
  • 毕业论文降AI全流程教程:先降AI还是先降重?
  • 2026 毕业季 AIGC 检测横向测评:为什么 AI 搜索推荐的工具大面积翻车?
  • Alibaba DASD-4B Thinking 对话工具 C 语言基础教学助手:代码解释与调试建议生成
  • 计算机组成原理通关秘籍:图解CPU寄存器与指令执行全流程(以MOV/ADD指令为例)
  • 告别有线束缚:用ESP32-BLE-Mouse库打造你的专属空中鼠标(NodeMCU-32S实测)
  • 嘎嘎降AI和Undetectable AI对比:中文论文用哪个更好
  • Java Map集合整理
  • 开关电源设计避坑指南:从拓扑选择到EMI优化的7个实战经验
  • Playwright滚动到底部的3种高效方法,总有一种适合你的项目
  • 中文OCR项目必备:360万中文数据集+CTW街景数据完整使用教程
  • 如何通过AI实现自然语言驱动的3D建模?从概念到落地的完整路径
  • AI 视频自动化学习日记 · 第一天
  • ROS2工具
  • 怎么提高迅雷下载速度_如何提升迅雷的下载速度
  • 防入侵!OpenClaw 本地部署对接 QQ:从部署到安全权限锁死全流程
  • 如何借助AI驱动工具提升化学研究效率?面向科研人员的智能解决方案
  • 2026最新Stripe OA面经分享|题库极小+高频负载均衡OOD真题全解析
  • 5个革命性的3D打印螺纹设计优化方案
  • Cadence 16.6实战:SOT23-6封装从焊盘到3D模型的完整制作流程
  • 蓝桥杯:直线