STM32-按键控制LED灯亮灭

795 阅读5分钟

原理图以及电路介绍

本篇文章使用的STM32F103系列的开发板,其原理示意图如下所示:

MCU原理图.png 从原理图中我们可以看到LED1-LED4接PE2-PE5口,按键KEY1接在PA0口其余按键KEY2-KEY4接在PC4-PC5口,因此我们可以明确一会进行GPIO配置时对哪些GPIO口进行初始化,在明确对哪些接口进行初始化后,我们介绍一下LED的原理图和按键的原理图。

LED原理图如下图所示:

LED原理图.png 由以上LED的原理图可以知道LED的1号引脚接高电平,所以当LED的2号引脚接低电平的时候LED会亮。介绍了LED的原理图后我们接着介绍按键的原理图。

按键原理图如下图所示:

按键原理图.png 由上图可以看到KEY1接GND而KEY2-KEY4接VCC,因此当KEY1没有按下的时候KEY1始终为低电平,同理KEY2-KEY4没有按下的时候其一直为高电平所以我们可以通过判断其当前电平状态来判断按键是否按下。

代码部分

通过原理图我们大概了解了LED和按键的原理,接下来我们看一下代码部分。

LED部分代码

在对STM32板子进行代码编写的时候,我们首先要了解的是LED接在板子的那个部分以此来了解该部分属于哪个时钟。

库函数.png 由库函数可以知道GPIOE属于APB2的时钟,所以我们应该开启GPIOE的时钟。

微信图片_20250525152931.png 开启完时钟后我们应该初始化GPIO,在进行GPIO初始化的时候,我们通过结构体进行初始化。如图所示。

微信图片_20250525153145.png 由上图可知,我们将GPIODE的2-5号接口都配置为推挽输出的方式。最后由上文我们知道了灯为低电平的时候亮,因此我们一开始通过GPIO_SetBits(GPIOE, GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5);函数将这些接口一开始输出高电平。 最后就是控制LED亮灭的逻辑函数了,在此我想的是通过一个state标志位来控制灯的亮灭,一开始定义一个static uint8_t state = 1,当LED状态改变时通过改变state的值来改变LED端口的电平以此来实现亮灭。 因此LED部分完整代码为:

`#include "stm32f10x.h"

void LED_Init(void) { /* 开启GPIOE的时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &GPIO_InitStructure);

/* 初始化LED为灭 */
GPIO_SetBits(GPIOE, GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5);

}

void LED1_Turn(void) {

static uint8_t state = 1; // 1表示灭,0表示亮
if (state)
{
    GPIO_ResetBits(GPIOE, GPIO_Pin_2);
    state = 0;
}
else
{
    GPIO_SetBits(GPIOE, GPIO_Pin_2);
    state = 1;
}

}

void LED2_Turn(void) {

static uint8_t state = 1;
if (state)
{
    GPIO_ResetBits(GPIOE, GPIO_Pin_3);
    state = 0;
}
else
{
    GPIO_SetBits(GPIOE, GPIO_Pin_3);
    state = 1;
}

}

void LED3_Turn(void) {

static uint8_t state = 1;
if (state)
{
    GPIO_ResetBits(GPIOE, GPIO_Pin_4);
    state = 0;
}
else
{
    GPIO_SetBits(GPIOE, GPIO_Pin_4);
    state = 1;
}

}

void LED4_Turn(void) {

static uint8_t state = 1;
if (state)
{
    GPIO_ResetBits(GPIOE, GPIO_Pin_5);
    state = 0;
}
else
{
    GPIO_SetBits(GPIOE, GPIO_Pin_5);
    state = 1;
}

}`

按键部分代码

通过前面LED的介绍,我们对按键的操作第一步也应该为开启时钟以及初始化GPIO,其操作如图所示:

按键初始化.png 在对按键进行初始化后,应该编写按键控制LED的代码了,但是如何让每个按键控制一个LED呢?在这里我通过对按键设置不同的值来控制LED灯,其具体操作如下图所示:

keynum.png 在这里,设置KeyNum初始值为0,通过GPIO_ReadInputDataBit()函数来判断此时按键的状态,在这里介绍一下第一个按键的原理,其它操作同理。在由上面的原理图可以知道KEY1一开始接低电平,因此当KEY1按下的时候会变为高电平,因此通过判断此时的电平状态来判断此时是否按下,当按下的时候由于按键的机械素质会有抖动导致电压不稳,所以对其进行20ms的延时,当20ms延时结束后如果继续是高电平表示不是因为抖动导致电平发生的变化,此时等待按键松手,因此用while来跳过这一过程,当松手后KEY1变为低电平,跳出while,改变keynum的值。其代码如下所示: #include "stm32f10x.h" #include "Delay.h"

void Key_Init(void) { /* 开启GPIOA和GPIOC的时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE);

GPIO_InitTypeDef GPIO_InitStructure;

/* 配置GPIOA.0为输入上拉模式 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

/* 配置GPIOC.4、GPIOC.5、GPIOC.6为输入上拉模式 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;
GPIO_Init(GPIOC, &GPIO_InitStructure);

}

uint8_t Get_KeyNum(void)
{ uint8_t KeyNum = 0;

if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 1)
{ 
    Delay_ms(20); // 按键去抖
    if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 1)
    {
        while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 1 );
					KeyNum = 1;
    }
}
else if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4) == 0)
{ 
    Delay_ms(20); // 按键去抖
    if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4) == 0)
    {
       while (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4) == 0); // 等待按键释放
					KeyNum = 2;
    }
}
else if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_5) == 0)
{
    Delay_ms(20); // 按键去抖
    if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_5) == 0)
    {
       while (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_5) == 0); // 等待按键释放
					KeyNum = 3;
    }
}
else if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_6) == 0)
{ 
    Delay_ms(20); // 按键去抖
    if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_6) == 0)
    {
        while (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_6) == 0); // 等待按键释放
					KeyNum = 4;
    }
}
return KeyNum;

} 介绍完LED和KEY部分的代码后,我们进入main函数,来实现控制,main函数具体代码如下所示: #include "stm32f10x.h" // Device header

#include "Delay.h"

#include "OLED.h"

#include "LED.h"

#include "Key.h"

int main(void) {

LED_Init();
Key_Init();

while (1)
{
			uint8_t Key;
    Key = Get_KeyNum();
    if (Key == 1)
    { 
					LED1_Turn();
    }
    if (Key == 2){ 
					LED2_Turn();
    }
    if (Key == 3){ 
        LED3_Turn();
    }
    if (Key == 4){
					LED4_Turn();
    }
}

}

总结

这里是我目前刚刚学习STM32对其的理解,希望对大家也有一定的帮助,如果有哪里的错误也请大家批评指正我们一起进步!