GPIO输入
在 《STM8S自学笔记-003 GPIO输出:点亮LED灯 and 跑马灯特效》中,我们曾经把LED的GPIO设置为推挽输出模式,而它只是GPIO输出功能中的一种。同样,GPIO的输入功能也不止有一种。
浮空输入,无中断
上拉输入,无中断
浮空输入,有中断
上拉输入,有中断
今天不讨论带有中断的的输入功能。
我的STM8S开发板上有3个按键,位置分别与3个LED对应,这些按键都有外部的上拉电阻。所以在初始化按键GPIO时,我们可以设置为浮空输入,也可以设置为上拉输入,两种设置方式对按键检测来说没有差别;如果没有外部上拉电阻,那就建议设置为内部上拉,以保证GPIO输入端口电压的稳定。
按键检测
目标功能
今天要实现的功能是:如果按住某个按键,那么,这个按键对应的LED就点亮,否则就熄灭。
对应代码
在Drv_GPIO.c中追加按键GPIO初始化、按键检查 共2个函数。同时,在Drv_GPIO.h中追加新增函数的声明与按键定义。
当前,完整的Drv_GPIO.c内容如下:
/**
******************************************************************************
* @file Drv_GPIO.c
* @author Elsa
* @version V1.0.0
* @date 7-August-2021
* @brief
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "Drv_GPIO.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief Initializes the LEDx according to the specified parameters.
* @param led_map : This parameter contains the pin number
* @retval None
*/
void LED_Init(uint8_t led_map)
{
if (led_map & LED1) GPIO_Init(LED1_GPIO, LED1_GPIO_PIN, GPIO_MODE_OUT_PP_LOW_SLOW); //LED1 ON
if (led_map & LED2) GPIO_Init(LED2_GPIO, LED2_GPIO_PIN, GPIO_MODE_OUT_PP_LOW_SLOW); //LED2 ON
if (led_map & LED3) GPIO_Init(LED3_GPIO, LED3_GPIO_PIN, GPIO_MODE_OUT_PP_LOW_SLOW); //LED3 ON
}
/**
* @brief Light on the specified LEDs.
* @param led_map : This parameter contains the pin number
* @retval None
*/
void LED_On(uint8_t led_map)
{
if (led_map & LED1) GPIO_WriteLow(LED1_GPIO, LED1_GPIO_PIN);
if (led_map & LED2) GPIO_WriteLow(LED2_GPIO, LED2_GPIO_PIN);
if (led_map & LED3) GPIO_WriteLow(LED3_GPIO, LED3_GPIO_PIN);
}
/**
* @brief Light off the specified LEDs.
* @param led_map : This parameter contains the pin number
* @retval None
*/
void LED_Off(uint8_t led_map)
{
if (led_map & LED1) GPIO_WriteHigh(LED1_GPIO, LED1_GPIO_PIN);
if (led_map & LED2) GPIO_WriteHigh(LED2_GPIO, LED2_GPIO_PIN);
if (led_map & LED3) GPIO_WriteHigh(LED3_GPIO, LED3_GPIO_PIN);
}
/**
* @brief Blink the specified LEDs.
* @param led_map : This parameter contains the pin number
* @retval None
*/
void LED_Reverse(uint8_t led_map)
{
if (led_map & LED1) GPIO_WriteReverse(LED1_GPIO, LED1_GPIO_PIN);
if (led_map & LED2) GPIO_WriteReverse(LED2_GPIO, LED2_GPIO_PIN);
if (led_map & LED3) GPIO_WriteReverse(LED3_GPIO, LED3_GPIO_PIN);
}
/**
* @brief Control the specified LEDs.
* @param led_map : This parameter contains the pin number
* @retval None
*/
void LED_Control(uint8_t led_map)
{
if (led_map & LED1) GPIO_WriteLow(LED1_GPIO, LED1_GPIO_PIN);
else GPIO_WriteHigh(LED1_GPIO, LED1_GPIO_PIN);
if (led_map & LED2) GPIO_WriteLow(LED2_GPIO, LED2_GPIO_PIN);
else GPIO_WriteHigh(LED2_GPIO, LED2_GPIO_PIN);
if (led_map & LED3) GPIO_WriteLow(LED3_GPIO, LED3_GPIO_PIN);
else GPIO_WriteHigh(LED3_GPIO, LED3_GPIO_PIN);
}
/**
* @brief Initializes the KEYx according to the specified parameters.
* @param key_map : This parameter contains the pin number
* @retval None
*/
void KEY_Init(uint8_t key_map)
{
if (key_map & KEY1) GPIO_Init(KEY1_GPIO, KEY1_GPIO_PIN, GPIO_MODE_IN_FL_NO_IT); //KEY1
if (key_map & KEY2) GPIO_Init(KEY2_GPIO, KEY2_GPIO_PIN, GPIO_MODE_IN_FL_NO_IT); //KEY2
if (key_map & KEY3) GPIO_Init(KEY3_GPIO, KEY3_GPIO_PIN, GPIO_MODE_IN_FL_NO_IT); //KEY3
}
/**
* @brief Read input of specified KEYs.
* @param key_map : This parameter contains the pin number
* @retval None
*/
uint8_t KEY_Read(uint8_t key_map)
{
uint8_t result = 0;
if (key_map & KEY1 != RESET && GPIO_ReadInputPin(KEY1_GPIO, KEY1_GPIO_PIN) == RESET)
result |= KEY1;
if (key_map & KEY2 != RESET && GPIO_ReadInputPin(KEY2_GPIO, KEY2_GPIO_PIN) == RESET)
result |= KEY2;
if (key_map & KEY3 != RESET && GPIO_ReadInputPin(KEY3_GPIO, KEY3_GPIO_PIN) == RESET)
result |= KEY3;
return result;
}
/***************************************************************END OF FILE****/
当前,完整的Drv_GPIO.h内容如下:
/**
******************************************************************************
* @file Drv_GPIO.h
* @author ANNA
* @version V1.0.0
* @date 03-August-2021
* @brief This file contains the headers of the Drv_GPIO.c
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __DRV_GPIO_H
#define __DRV_GPIO_H
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Exported types ------------------------------------------------------------*/
/* Exported defines ----------------------------------------------------------*/
//Maps of LEDx
#define LED(n) ((uint8_t)(0x01<<(uint8_t)(n-1)))
#define LED1 LED(1)
#define LED2 LED(2)
#define LED3 LED(3)
//GPIO Definition of LEDx
#define LED1_GPIO GPIOC
#define LED1_GPIO_PIN GPIO_PIN_3
#define LED2_GPIO GPIOC
#define LED2_GPIO_PIN GPIO_PIN_4
#define LED3_GPIO GPIOD
#define LED3_GPIO_PIN GPIO_PIN_2
//Maps of KEYs
#define KEY(n) ((uint8_t)(0x01<<(uint8_t)(n-1)))
#define KEY1 KEY(1)
#define KEY2 KEY(2)
#define KEY3 KEY(3)
//GPIO Definition of KEYx
#define KEY1_GPIO GPIOB
#define KEY1_GPIO_PIN GPIO_PIN_3
#define KEY2_GPIO GPIOD
#define KEY2_GPIO_PIN GPIO_PIN_3
#define KEY3_GPIO GPIOD
#define KEY3_GPIO_PIN GPIO_PIN_7
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported function prototypes ----------------------------------------------*/
void LED_Init(uint8_t led_map);
void LED_On(uint8_t led_map);
void LED_Off(uint8_t led_map);
void LED_Reverse(uint8_t led_map);
void LED_Control(uint8_t led_map);
void KEY_Init(uint8_t key_map);
uint8_t KEY_Read(uint8_t key_map);
#endif
/***************************************************************END OF FILE****/
【提示】
在Drv_GPIO.c中,定义了LED和KEY初始化和操作函数,这些函数的入口是我们自己定义的LED1/2/3和KEY1/2/3,与STM8的底层寄存器无关。也就是说,在调用这些函数时,不会直接调用这些MCU的底层寄存器,而是通过我们自定义的(入口)接口来实现对应的功能。所以,可以将Drv_GPIO.h中形如
#define LED1_GPIO GPIOC
#define LED1_GPIO_PIN GPIO_PIN_3
的代码块全部移入Drv_GPIO.c。
功能实现
在主函数中,添加下述代码,实现按键检测与LED显示:
/**
* @brief Main program.
* @param None
* @retval None
*/
void main(void)
{
static uint8_t key_value;
CLOCK_HSE(CLK_PRESCALER_CPUDIV1);
KEY_Init(KEY1 | KEY2 | KEY3);
LED_Init(LED1 | LED2 | LED3);
while (1)
{
/* Key_Scan */
key_value = KEY_Read(KEY1 | KEY2 | KEY3);
/* Led Show */
if (key_value & KEY1)
LED_On(LED1);
else
LED_Off(LED1);
if (key_value & KEY2)
LED_On(LED2);
else
LED_Off(LED2);
if (key_value & KEY3)
LED_On(LED3);
else
LED_Off(LED3);
}
}
按键滤波
虽然开发板在按键的硬件层面上,从相应的GPIO口各引出了一个接地的滤波电容,但是按下后仍可能有抖动。对此,我们可以从软件上进行滤波。
延时滤波
延时滤波是一种简便的办法。在学校里做单片机实验时,我们就用过这种方法;但在工作中,我从没在按键检测函数里面加过“无用的”延时函数。
if (key_map & KEY1 != RESET && GPIO_ReadInputPin(KEY1_GPIO, KEY1_GPIO_PIN) == RESET)
{
Delay_1ms(7);
if (key_map & KEY1 != RESET && GPIO_ReadInputPin(KEY1_GPIO, KEY1_GPIO_PIN) == RESET)
{
result |= KEY1;
}
}
循环滤波
循环滤波可能是最为常见的按键软件检测方法。它要求在按键按下的情况呈现一定规律时,就认为按下有效。
在本例中,我设定的规律是:按键连续按下100次。那么,对应的修改是:
/**
* @brief Read input of specified KEYs.
* @param key_map : This parameter contains the pin number
* @retval None
*/
uint8_t KEY_Read(uint8_t key_map)
{
volatile uint8_t result = 0;
static uint8_t count[3] = {0};
/* Cyclic filtering */
count[0] = (key_map & KEY1 != RESET && GPIO_ReadInputPin(KEY1_GPIO, KEY1_GPIO_PIN) == RESET)? (++count[0]):0;
count[1] = (key_map & KEY2 != RESET && GPIO_ReadInputPin(KEY2_GPIO, KEY2_GPIO_PIN) == RESET)? (++count[1]):0;
count[2] = (key_map & KEY3 != RESET && GPIO_ReadInputPin(KEY3_GPIO, KEY3_GPIO_PIN) == RESET)? (++count[2]):0;
/* Overflow check */
count[0] = (count[0] >= 250)? 250:count[0];
count[1] = (count[1] >= 250)? 250:count[1];
上一篇:STM8S自学笔记-005 精准延时
下一篇:STM8的线中断和端口中断
推荐阅读最新更新时间:2024-11-11 10:19
推荐帖子
- 初次使用必看!S5pv210系列:E8卡片电脑系统烧写或者更换
- 在启动卡制作完成后,使用下面步骤更新或者更换系统。烧写/更新Android/ubuntu/Linux系统1、选中SecureCRT软件,选择数字键“1”,从TQBoardDNW下载烧写镜像uboot文件双击烧写。如:u-boot_E8_20130826.bin(对应VGA:1024*768)2、选择“h”进行关机,选中SecureCRT软件,按住空格键开机,进入uboot下载界面。3、选中SecureCRT软件,选择数字键“9”进入区间分区菜单,若准备下载Ubuntu系,选中“1”分两个
- 小小宇宙 ARM技术
- 2012年9月份北京举办的一些重要行业展会和研讨会
- IHS行业分析亚太峰会展会场馆:北京国家会议中心举办时间:2012年9月20日8:30–17:30第十七届中国国际医药(工业)展览会暨技术交流会展会场馆:北京国家会议中心展会日期:2012年9月24日~2012年9月27日第21届中国国际信息通信展览会展会场馆:北京朝阳区三环东路六号中国国际展览中心举办时间:2012年9月18日~2012年9月22日第十四届国际电力设备及技术展览会展会场馆:北京朝阳区三环东路六号中国国际展览中心举办时间:2012年9
- jameswangsynnex 安防电子
- 软件测试经典资料大推荐(五)---google软件测试之道
- 软件测试经典资料大推荐(五)---google软件测试之道程序员之间流传着这样一句顺口溜:有人喜欢创造世界,他们做了开发者;有的人喜欢开发者,他们做了测试员。什么是软件测试?软件测试就是一场本该在用户面前发生的灾难提前在自己面前发生了,这会让他们生出一种救世主的感觉,拯救了用户,也就拯救者这个软件,避免了他们被卸载的命运。近年来,软件测试一直呈现出火爆的发展势头。为什么软件测试最近这么火。在这背后是有一定的深层次原因的。在中国的很多软件企业存
- tiankai001 下载中心专版
- stm32f测试小程序
- 希望对新手有用!使用内部晶振,PC口进行闪灯! stm32f.JPG(51.25KB)下载次数:132010-9-2816:41stm32f测试小程序还不错很简洁但很实用的一段程序好像太简洁了,有空去楼主的博客逛逛有用就好!感觉还不错,应该有应用的场合
- 86846642996 stm32/stm8
- 太阳能热水器控制仪的水位传感器是什么原理
- 测量了传感器的电阻,在不同的的水位,电阻值都会缓慢的上升,最终都是60k或接近,请问这是什么原理,或者是测量方法不对.现在设计一个电路,可以测温度,也可以测水位。测温度,就是用测量电阻,然后转换为频率,单片机检测接收。测量水位,看到传感器里面是几根线,从传感器引出是两根线。里面似乎没有芯片或是液位传感器,它是通过不同的水位变化输出不同的阻值,我看了一些资料,都是这样说的,可是为什么阻值总是会上升到60K,在不同的水位情况下都是这样?太阳能热水器控制仪的水位传感器是什么原理是不是你的传感器坏
- djf876 嵌入式系统
- 【2024 DigiKey 创意大赛】带健康提醒的86盒桌面助手
- **一、作品简介**设计名称:带健康提醒的86盒桌面助手项目用到的板卡:使用ESP32-S3-LCD-Ev-Board开发板,采用的是ESP32-S3这款MCU,板卡板载了4寸的电容触摸屏,功能强悍,做HMI应用十分合适。作品功能介绍:借此次得捷大赛的机会,制作了一款带健康提醒的86盒桌面助手,86盒可以摆在桌子上,实时地检测前方的温度,也就是监测使用者的体表温度,并显示在屏幕上面,并可通过网络来获取时间、天气等显示在屏幕上,给使用者提供出行建议等,软件采用LVGL开源GUI界面
- pomin DigiKey得捷技术专区
设计资源 培训 开发板 精华推荐
- LT6656ACS6-2.048、2.048V 精密电流和升压基准电压源的典型应用
- ISD-ES1600B-Prog,基于ISD1600b/12B/16B/20B的ChipCorder 16xx系列编程器演示板
- LT3970EMS-3.3 5V、2MHz 降压转换器的典型应用
- PCF85063AT-ARD: Arduino Shield -I2C总线
- QMK客制化键盘84键 USB HUB 验证板
- 用于仪表的 3 至 18V 模拟放大
- DER-364 - 12W 高效率(>88%)、功率因数校正的LED驱动器,用于BR40灯管
- 使用 ROHM Semiconductor 的 BD4943 的参考设计
- LT1021CMH-5 用于处理更高负载电流的电压基准的典型应用
- LTC3110EUF 3.3V/2A 输出的典型应用电路来自具有有源电压平衡的超级电容器备份/再充电应用
- 【把你我的经验串一串,共享丰收】EEWORLD优秀主题/回复第17期活动开始拉
- 直播:TI SimpleLink MCU无线平台及软件介绍!丰富的提问礼在这里等你~
- 【报名赢小米手环、膳魔师保温杯等好礼】罗德与施瓦茨HDMI 1.4b/2.1 接口测试
- 有奖直播|如何借助Mentor Xpedition AMS对汽车CAN总线进行仿真优化分析?
- 抢先体验:TI MSPM0L1306 LaunchPad开发套件,赢三模无线键盘
- 观展有礼 | 到 e 络盟展台,领星巴克咖啡券(上海慕尼黑电子展)
- TE白皮书下载|《散热桥技术——电子设备散热领域的创新》
- ADI有奖下载活动之21:ADI民用雷达解决方案