3.4 按键控制LED/光敏传感器控制蜂鸣器
一、按键控制LED
1.1 硬件电路搭建

这里使用了两个按键和两个 LED。
- 按键分别连接到 PB1 和 PB11 端口,一端接 GPIO 口,另一端接地,通过检测 GPIO 口的电平变化来判断按键是否按下。
- LED 则分别连接到 PA1 和 PA2 端口,一端接 GPIO 口,另一端接 VCC,采用低电平点亮。
1.2 LED驱动代码
模块化编程:
为了使代码结构清晰、易于管理和移植,经常采用了模块化编写。对于驱动代码,通常将其封装起来,单独放在
.c和.h文件中。以按键和 LED 的驱动代码为例,在工程文件夹中新建一个名为
hardware的文件夹,专门用于存放硬件驱动。然后在Target中新建一个hardware并添加到头文件路径列表中。
创建文件:在
hardware文件夹中分别新建LED.c和LED.h文件。LED.c用于存放驱动程序的主体代码,LED.h用于存放该驱动可以对外提供的函数或变量的声明。LED初始化函数:
开启 GPIOA 的时钟。定义结构体变量,配置端口模式为通用推挽输出,选择 PA1 和 PA2 端口,输出速度为 50MHz。最后调用GPIO_Init完成 GPIOA 外设的初始化。点亮,熄灭和翻转 LED 的函数:
void LED1_On (void)和void LED1_Off (void):分别通过GPIO_SetBits()和GPIO_ResetBits()来控制 LED 的亮灭。void LED1_Turn(void)和void LED2_Turn(void):通过读取 GPIO 口的状态来判断 LED 的状态,从而翻转 LED 的状态。
#include "stm32f10x.h" // Device header void LED_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStucture; GPIO_InitStucture.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStucture.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2; GPIO_InitStucture.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStucture); 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) { 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 LED1_Turn(void); void LED2_ON(void); void LED2_OFF(void); void LED2_Turn(void); #endif
1.3 按键驱动代码
创建文件:在
hardware文件夹中新建key.c和key.h文件。键盘初始化函数:
开启 GPIOB 的时钟。然后定义结构体变量,配置端口模式为上拉输入,选择 PB1 和 PB11 端口,输出速度 50MHz(此时为输入模式,此参数没有实际作用)。最后调用GPIO_Init()完成 GPIOB 外设的初始化。读取按键值函数:编写
uint8_t Key_GetNum(void)函数来读取按键值,函数内部首先定义一个变量Key_Number用于存储按键键码。然后通过GPIO_ReadInputDataBit()函数读取 GPIO 端口的值,判断按键是否按下。如果按键按下,先进行 20ms 的延时消除按键抖动,随后通过一个 while 循环等待按键松手,松手后再进行 20ms 的延时消抖,最后将Key_Number赋值为 1,表示按键 1 按下。#include "stm32f10x.h" // Device header #include "delay.h" void Key_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); } uint8_t Key_GetNum(void) { uint8_t KeyNum = 0; if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0) { Delay_ms(20); //按键去抖动 while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0); //等待按键松手 Delay_ms(20); //按键去抖动 KeyNum = 1; } if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0) { Delay_ms(20); while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0); Delay_ms(20); KeyNum = 2; } return KeyNum; }头文件:
key.h存放函数和变量声明。#ifndef _KEY_H #define _KEY_H void Key_Init(void); uint8_t Key_GetNum(void); #endif
1.4 主函数调用
在主函数 main.c 中,首先包含相应的头文件,如 #include "LED.h" 和 #include "key.h"。然后进行初始化操作,如 LED_Init (); 和 Key_Init ();。在主循环中,通过调用按键读取函数获取按键值,并根据按键值执行相应的 LED 控制操作。
#include "Device/Include/stm32f10x.h"
#include "delay.h"
#include "LED.h"
#include "Key.h"
uint8_t KeyNum = 1;
int main(void)
{
LED_Init();
Key_Init();
while(1)
{
KeyNum = Key_GetNum();
if (KeyNum == 1)
{
LED1_Turn();
}
if (KeyNum == 2)
{
LED2_Turn();
}
}
}二、光敏传感器与蜂鸣器电路

- 蜂鸣器 VCC 和 GND 分别接电源正负极,控制脚接 PB12 号口。
- 光敏传感器 VCC 和 GND 同样接电源正负极,数字输出端 DIO 接 PB13 号口。
当光线变化时,光敏传感器的输出电平会相应改变,通过检测这个电平变化,可以实现对蜂鸣器的控制。
代码和之前的按键控制 LED 类似:
2.1 Buzzer.c 代码:
#include "stm32f10x.h" // Device header
void Buzzer_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStucture;
GPIO_InitStucture.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStucture.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStucture.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStucture);
GPIO_SetBits(GPIOB, GPIO_Pin_12);
}
void Buzzer_ON(void)
{
GPIO_SetBits(GPIOB, GPIO_Pin_12);
}
void Buzzer_OFF(void)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
}
void Buzzer_Turn(void)
{
if (GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_12) == 0)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
}
else
{
GPIO_SetBits(GPIOB, GPIO_Pin_12);
}
}2.2 LightSensor.c 代码:
#include "stm32f10x.h" // Device header
void LightSensor_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
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);
}
uint16_t LightSensor_Get(void)
{
return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13);
}2.3 main.c 代码:
#include "stm32f10x.h" // Device header
#include "delay.h"
#include "LED.h"
#include "Key.h"
#include "Buzzer.h"
#include "LightSensor.h"
int main(void)
{
Buzzer_Init();
LightSensor_Init();
while(1)
{
if (LightSensor_Get() == 1)
{
Buzzer_ON();
} else
Buzzer_OFF();
}
}