嵌入式学习日志————STM32之按键控制LED(一)
前言
该学习日志是我在观看江科大的视频以后的总结归纳,如果有任何疑问都可以去哔哩哔哩看原视频来解答,欢迎大家提出问题或者建议。
正文
一、GPIO基本知识
GPIO就是从芯片内部引出来一根功能复用的口线(电线)
功能复用是指:GPIO的引脚可以由CPU配置成不同的功能
比如:输入功能 输出功能 模拟功能 复用功能等等
1.基本结构
(1)所有的GPIO都是挂载在APB2外设总线上的。
(2)寄存器是32位的,但IO口只有16个,所以只有低16位有对应端口,高16位没有用到。只负责存储数据。
2.位结构

3.GPIO的模式

二、实验
1.接线图
注:该图源于江科大(接线采用低电平点亮方式——LED灯正极接VCC,负极接引脚)
2.LED灯
3.电路
1)按键接法
下接按键(常用)
图一:按键按下,PA0口电压为低电平,按键松手PA0悬空,所以在此接法下要求PA0是上拉输入的模式。
图二:按键按下,PA0口电压为低电平,按键松手PA0为高电平,所以此时,PA0可以是上拉输入或者浮空输入。
上拉按键
图三:按键按下,PA0口电压为高电平,按键松手PA0为低电平,所以此时,PA0可以是下拉输入或者浮空输入。
图四: 按键按下,PA0口电压为高电平,按键松手PA0悬空,所以在此接法下要求PA0是下拉输入的模式。
2)特别说明
我所记录的这个实验采用的是下拉按键来实现控制LED灯的亮灭。所以在接下来的代码中,当读取到按键对应IO口电平为低电平时说明按键按下。
4.原理说明
利用读取按键对应端口的输入电平来控制LED灯的亮灭。按键按下与松开时对KeyNum赋不同的值,在通过对KeyNum值的判断,来设置LED灯对应端口的电平值,以此控制LED的亮灭。
5.代码
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"
uint8_t KeyNum;
int main(void)
{
LED_Init();
Key_Init();
while (1)
{
KeyNum = Key_GetNum();
if (KeyNum == 1)
{
LED1_Turn();
}
if (KeyNum == 2)
{
LED2_Turn();
}
}
}
2)led.c
#include "stm32f10x.h" // Device header
void LED_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟
/*GPIO初始化*/
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); //将PA1和PA2引脚初始化为推挽输出
/*设置GPIO初始化后的默认电平*/
GPIO_SetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2); //设置PA1和PA2引脚为高电平
}
/*LED1亮*/
void LED1_ON(void)
{
GPIO_ResetBits(GPIOA, GPIO_Pin_1); //设置PA1引脚为低电平
}
/*LED1灭*/
void LED1_OFF(void)
{
GPIO_SetBits(GPIOA, GPIO_Pin_1); //设置PA1引脚为高电平
}
/*LED1状态翻转*/
void LED1_Turn(void)
{
if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1) == 0) //判断此时LED的状态
{
GPIO_SetBits(GPIOA, GPIO_Pin_1);
}
else
{
GPIO_ResetBits(GPIOA, GPIO_Pin_1);
}
}
/*LED2亮*/
void LED2_ON(void)
{
GPIO_ResetBits(GPIOA, GPIO_Pin_2); //设置PA2引脚为低电平
}
/*LED2灭*/
void LED2_OFF(void)
{
GPIO_SetBits(GPIOA, GPIO_Pin_2); //设置PA2引脚为高电平
}
/*LED2状态翻转*/
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);
}
3)key.c
#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;
}
作者:sunflower_2024