上次我们讲解了操作STM32的GPIO-输出的3种方法和关键代码,这节我们讲关于GPIO按键输入的关键要点,分为按键(查询/中断)两种方法讲解相关的核心代码。
编程要点:(查询方法)
1. 使能 GPIO 端口时钟;
2. 初始化 GPIO 目标引脚为输入模式(浮空输入);
3. 编写按键检测程序,检测按键的状态,实现按键控制 LED 灯;
#ifndef __KEY_H
#define __KEY_H
#include "stm32f10x.h"
#define KEY1_GPIO_CLK RCC_APB2Periph_GPIOA
#define KEY1_GPIO_PORT GPIOA
#define KEY1_GPIO_PIN GPIO_Pin_0
#define KEY_ON 1
#define KEY_OFF 0
void Key_GPIO_Config(void);
uint8_t Key_Scan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin);
#endif
#include "key.h"
void Key_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(KEY1_GPIO_CLK,ENABLE);
GPIO_InitStructure.GPIO_Pin = KEY1_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(KEY1_GPIO_PORT, &GPIO_InitStructure);
}
uint8_t Key_Scan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin)
{
if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON )
{
while(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON);
return KEY_ON;
}
else
return KEY_OFF;
}
#ifndef __LED_H
#define __LED_H
#include "stm32f10x.h"
#define LED_GPIO_PORT GPIOB
#define LED_GPIO_CLK RCC_APB2Periph_GPIOB
#define LED_GPIO_PIN GPIO_Pin_5
#define ON 0
#define OFF 1
#define LED(a) if (a) \
GPIO_SetBits(LED_GPIO_PORT,LED_GPIO_PIN);\
else \
GPIO_ResetBits(LED_GPIO_PORT,LED_GPIO_PIN)
void LED_GPIO_Config(void);
#endif
#include "led.h"
void LED_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( LED_GPIO_CLK , ENABLE);
GPIO_InitStructure.GPIO_Pin = LED_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LED_GPIO_PORT, &GPIO_InitStructure);
GPIO_SetBits(LED_GPIO_PORT, LED_GPIO_PIN);
}
#include "stm32f10x.h"
#include "led.h"
#include "key.h"
int main(void)
{
LED_GPIO_Config();
Key_GPIO_Config();
while(1)
{
if(Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) == KEY_ON)
{
LED(ON);
}
}
}
以上是查询的方法,在讲按键中断的方法前,我们先说说我们之前学的51是怎么配置外部中断的?
:51单片机就2个外部中断引脚 INT0,INT1;
然后去选择中断触发方式,上升沿/下降沿;
最后编写中断响应子程序;
而我们的STM32是很强大的,它所以的GPIO都可以触发中断,那么这么多的中断来源,STM32是如何管理,分配的呐~?
:就是通过
:EXTI(External interrupt/event controller)—外部中断/事件控制器;
:NVIC(Nested Vectored Interrupt controller) 是嵌套向量中断控制器;
一个管理中断的配置,一个管理中断的优先级。
#ifndef __EXTI_H
#define __EXTI_H
#include "stm32f10x.h"
#define KEY1_INT_GPIO_PORT GPIOA
#define KEY1_INT_GPIO_CLK RCC_APB2Periph_GPIOA
#define KEY1_INT_GPIO_PIN GPIO_Pin_0
#define KEY1_INT_EXTI_PORTSOURCE GPIO_PortSourceGPIOA
#define KEY1_INT_EXTI_PINSOURCE GPIO_PinSource0
#define KEY1_INT_EXTI_LINE EXTI_Line0
#define KEY1_INT_EXTI_IRQ EXTI0_IRQn
#define KEY1_IRQHandler EXTI0_IRQHandler
void EXTI_Key_Config(void);
#endif
#include "exti.h"
static void NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void EXTI_Key_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK ,ENABLE);
NVIC_Config();
GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);
GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE);
EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
void KEY1_IRQHandler(void)
{
if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET)
{
LED(ON);
EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);
}
}
#include "stm32f10x.h"
#include "led.h"
#include "exti.h"
int main(void)
{
LED_GPIO_Config();
EXTI_Key_Config();
while(1)
{
;
}
}
如果大家觉得实验中一些寄存器的配置不是很明白,大家就拿出咱们吃饭的家伙数据手册来把实验中出现的寄存器在手册中查找,去理解。
欢迎大家的留言和评论我会在看到的第一时间内答复。
看完后感觉得到帮助的小伙伴,要点点赞哦~
给笔者一些动力嘛!谢谢啦~