简介:
本篇文章主要写的是关于本人对于STM32F103 按键控制LED灯的学习,功能为:
①按键1控制 LED0
②按键2 控制 LED1 亮
③按键3 控制 LED0 和 LED1 翻转
④WK_UP 关闭 LED0 和 LED1
原理介绍:
LED:
上图为STM32F103中的LED0和LED1的原理图,当输入为0时,二者导通。当输入为1时,二者阻滞。故输入为低电平时,LED0与1才会亮。
KEY:
从原理图来看,KEY0、KEY1 和 KEY2 是低电平有效的,而 KEY_UP 则是高电平有 效的,并且外部都没有上下拉电阻,所以需要在 STM32F103 内部设置上下拉,来确定设置空闲 电平状态。
代码部分:
LED:
#include "./BSP/LED/led.h"
void led_init(void)
{
GPIO_InitTypeDef GPIO_LD;
LED0_GPIO_CLK_ENABLE();
LED1_GPIO_CLK_ENABLE();
GPIO_LD.Pin = LED0_GPIO_PIN;
GPIO_LD.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_LD.Pull = GPIO_PULLUP;
GPIO_LD.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(LED0_GPIO_PORT,&GPIO_LD);
GPIO_LD.Pin = LED1_GPIO_PIN;
HAL_GPIO_Init(LED1_GPIO_PORT,&GPIO_LD);
LED0(1);
LED1(1);
}
#ifndef __LED_H
#define __LED_H
#include "./SYSTEM/sys/sys.h"
#define LED0_GPIO_PORT GPIOB
#define LED0_GPIO_PIN GPIO_PIN_5
#define LED0_GPIO_CLK_ENABLE() do{__HAL_RCC_GPIOB_CLK_ENABLE();}while(0)
#define LED1_GPIO_PORT GPIOE
#define LED1_GPIO_PIN GPIO_PIN_5
#define LED1_GPIO_CLK_ENABLE() do{__HAL_RCC_GPIOE_CLK_ENABLE();}while(0)
#define LED0(x) do{ x ?\
HAL_GPIO_WritePin(LED0_GPIO_PORT, LED0_GPIO_PIN, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(LED0_GPIO_PORT, LED0_GPIO_PIN, GPIO_PIN_RESET); \
}while(0)
#define LED1(x) do{ x ?\
HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_RESET); \
}while(0)
#define LED0_TogglePin() do{HAL_GPIO_TogglePin(LED0_GPIO_PORT,LED0_GPIO_PIN);} while(0)
#define LED1_TogglePin() do{HAL_GPIO_TogglePin(LED1_GPIO_PORT,LED1_GPIO_PIN);} while(0)
void led_init(void);
#endif
以上为led.c与led.h的代码led.h主要是进行宏定义,使得功能看起来比较清晰,led.c的功能是开时钟以及设置LED有关引脚的输出模式以及频率。
KEY:
#ifndef __KEY_H
#define __KEY_H
#include "./SYSTEM/sys/sys.h"
#define KEY0_GPIO_PORT GPIOE
#define KEY0_GPIO_PIN GPIO_PIN_4
#define KEY0_GPIO_CLK_ENABLE() do{__HAL_RCC_GPIOE_CLK_ENABLE();}while(0)
#define KEY1_GPIO_PORT GPIOE
#define KEY1_GPIO_PIN GPIO_PIN_3
#define KEY1_GPIO_CLK_ENABLE() do{__HAL_RCC_GPIOE_CLK_ENABLE();}while(0)
#define KEY2_GPIO_PORT GPIOE
#define KEY2_GPIO_PIN GPIO_PIN_2
#define KEY2_GPIO_CLK_ENABLE() do{__HAL_RCC_GPIOE_CLK_ENABLE();}while(0)
#define WKUP_GPIO_PORT GPIOA
#define WKUP_GPIO_PIN GPIO_PIN_0
#define WKUP_GPIO_CLK_ENABLE() do{__HAL_RCC_GPIOA_CLK_ENABLE();}while(0)
#define KEY0 HAL_GPIO_ReadPin(KEY0_GPIO_PORT,KEY0_GPIO_PIN)
#define KEY1 HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)
#define KEY2 HAL_GPIO_ReadPin(KEY2_GPIO_PORT,KEY2_GPIO_PIN)
#define WKUP HAL_GPIO_ReadPin(WKUP_GPIO_PORT,WKUP_GPIO_PIN)
#define KEY0_PRES 1
#define KEY1_PRES 2
#define KEY2_PRES 3
#define WKUP_PRES 4
uint8_t key_scan(uint8_t mode);
void key_init(void);
#endif
#include "./BSP/KEY/key.h"
#include "./SYSTEM/delay/delay.h"
void key_init(void)
{
GPIO_InitTypeDef GPIO_ANJIAN;
KEY0_GPIO_CLK_ENABLE();
KEY1_GPIO_CLK_ENABLE();
KEY2_GPIO_CLK_ENABLE();
WKUP_GPIO_CLK_ENABLE();
GPIO_ANJIAN.Pin = KEY0_GPIO_PIN;
GPIO_ANJIAN.Mode = GPIO_MODE_INPUT;
GPIO_ANJIAN.Pull = GPIO_PULLUP;
GPIO_ANJIAN.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(KEY0_GPIO_PORT,&GPIO_ANJIAN);
GPIO_ANJIAN.Pin = KEY1_GPIO_PIN;
GPIO_ANJIAN.Mode = GPIO_MODE_INPUT;
GPIO_ANJIAN.Pull = GPIO_PULLUP;
GPIO_ANJIAN.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(KEY1_GPIO_PORT,&GPIO_ANJIAN);
GPIO_ANJIAN.Pin = KEY2_GPIO_PIN;
GPIO_ANJIAN.Mode = GPIO_MODE_INPUT;
GPIO_ANJIAN.Pull = GPIO_PULLUP;
GPIO_ANJIAN.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(KEY2_GPIO_PORT,&GPIO_ANJIAN);
GPIO_ANJIAN.Pin = WKUP_GPIO_PIN;
GPIO_ANJIAN.Mode = GPIO_MODE_INPUT;
GPIO_ANJIAN.Pull = GPIO_PULLDOWN;
GPIO_ANJIAN.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(WKUP_GPIO_PORT,&GPIO_ANJIAN);
}
uint8_t key_scan(uint8_t mode)
{
static uint8_t key_up = 1;
uint8_t keyval = 0;
if(mode)
{
key_up = 1;
}
if (key_up && (KEY0 == 0 || KEY1 == 0 || KEY2 == 0 || WKUP == 1))
{
delay_ms(10);
key_up = 0;
if (KEY0 == 0)
keyval = KEY0_PRES;
if (KEY1 == 0)
keyval = KEY1_PRES;
if (KEY2 == 0)
keyval = KEY2_PRES;
if (WKUP == 1)
keyval = WKUP_PRES;
}
else if( KEY0 == 1 && KEY1 == 1 && KEY2 == 1 && WKUP == 0)
{
key_up = 1;
}
return keyval;
}
key.c中:
void key_init(void) 用于初始化按键。它首先使能了按键所在GPIO端口的时钟,然后配置了每个按键的GPIO属性(如模式、上拉/下拉电阻、速度等),最后调用HAL_GPIO_Init
函数来初始化GPIO。
uint8_t key_scan(uint8_t mode)里定义了一个key_scan
函数,用于检测按键的状态。使用静态变量key_up
来记录按键是否处于释放状态,并在按键被按下时通过条件判断来设置相应的按键keyval。通过mode
参数来重置按键状态,以及在检测到按键状态变化时进行了消抖。如果所有按键都未被按下,则重置key_up
为释放状态。
key.h中:
主要用于定义与按键相关的宏和声明按键操作的函数。
MAIN:
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/delay/delay.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/KEY/key.h"
#include <stdio.h>
int main(void)
{
HAL_Init();
sys_stm32_clock_init(RCC_PLL_MUL9);
delay_init(72);
led_init();
key_init();
uint8_t key;
while(1)
{
key = key_scan(0);
if (key)
{
switch(key)
{
case KEY0_PRES:
LED0(0);
break;
case KEY1_PRES:
LED1(0);
break;
case KEY2_PRES:
LED0_TogglePin();
LED1_TogglePin();
break;
case WKUP_PRES:
LED0(1);
LED1(1);
break;
}
}
}
}
while(1)
循环用于不断检测按键的状态。
key = key_scan(0);
:调用key_scan
函数扫描按键状态,并将结果保存在key
变量中。0
作为参数传递给key_scan
,可能表示不需要重置按键状态。
if (key)
:如果key
的值不为0(即有按键被按下)。
switch(key)
:根据key
的值选择相应的case来执行。
KEY0_PRES
:如果按键0被按下,打开LED0。
KEY1_PRES
:如果按键1被按下,打开LED1。
KEY2_PRES
:如果按键2被按下,LED1与LED0的状态进行翻转。
WKUP_PRES
:如果WKUP按键被按下,关闭LED0和LED1。
演示视频:
按键控制led演示