zoukankan      html  css  js  c++  java
  • 菜鸟学STM32之按键输入

    微信公众号:小樊Study
    关注共同学习,问题或建议,请公众号留言!!!

    跑马灯实验我们学习了STM32F4的IO口作为输出的使用,这次我们将向大家介绍如何使用 STM32F4的IO口作为输入用,今天我们将利用开发板的4个按键,来控制开发板的两个LED的亮灭和蜂鸣器的开关。通过本次学习,你将了解到STM32F4的IO口作为输入口的使用方法。

    硬件连接


    KEY0、KEY1 和 KEY2 是低电平有效的,而 KEY_UP 是高电平有效的,并且外部都没有上下拉电阻,所以,需要在STM32F4内部设置上下拉

     

    软件设计

    key.c

     1#include "key.h"
    2#include "delay.h" 
    3//////////////////////////////////////////////////////////////////////////////////     
    4
    5
    6//按键初始化函数
    7void KEY_Init(void)
    8
    {
    9
    10    GPIO_InitTypeDef  GPIO_InitStructure;
    11
    12  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOA,GPIOE时钟
    13
    14  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4; //KEY0 KEY1 KEY2对应引脚
    15  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
    16  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M
    17  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
    18  GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,3,4
    19
    20
    21  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//WK_UP对应引脚PA0
    22  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;//下拉
    23  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA0
    24
    25
    26//按键处理函数
    27//返回按键值
    28//mode:0,不支持连续按;1,支持连续按;
    29//0,没有任何按键按下
    30//1,KEY0按下
    31//2,KEY1按下
    32//3,KEY2按下 
    33//4,WKUP按下 WK_UP
    34//注意此函数有响应优先级,KEY0>KEY1>KEY2>WK_UP!!
    35u8 KEY_Scan(u8 mode)
    36
    {     
    37    static u8 key_up=1;//按键按松开标志
    38    if(mode)key_up=1;  //支持连按         
    39    if(key_up&&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1))
    40    {
    41        delay_ms(10);//去抖动 
    42        key_up=0;
    43        if(KEY0==0)return 1;
    44        else if(KEY1==0)return 2;
    45        else if(KEY2==0)return 3;
    46        else if(WK_UP==1)return 4;
    47    }else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)key_up=1;      
    48     return 0;// 无按键按下
    49}


    这段代码包含 2 个函数,void KEY_Init(void)和 u8 KEY_Scan(u8 mode),KEY_Init 是用来初始化按键输入的 IO 口的。实现 PA0、PE2~4 的输入设置
    KEY_Scan 函数,则是用来扫描这 4 个 IO 口是否有按键按下。KEY_Scan 函数,支持两种扫描方式,通过 mode 参数来设置。
    当 mode 为 0 的时候,KEY_Scan 函数将不支持连续按,扫描某个按键,该按键按下之后必须要松开,才能第二次触发,否则不会再响应这个按键,这样的好处就是可以防止按一次多次触发,而坏处就是在需要长按的时候比较不合适。
    当 mode 为 1 的时候,KEY_Scan 函数将支持连续按,如果某个按键一直按下,则会一直返回这个按键的键值,这样可以方便的实现长按检测。
    有了 mode 这个参数,大家就可以根据自己的需要,选择不同的方式。这里要提醒大家,因为该函数里面有 static 变量,所以该函数不是一个可重入函数,在有 OS 的情况下,这个大家要留意下。同时还有一点要注意的就是,该函数的按键扫描是有优先级的,最优先的是 KEY0,第二优先的是 KEY1,接着 KEY2,最后是 KEY3(KEY3 对应 KEY_UP 按键)。该函数有返回值,如果有按键按下,则返回非 0 值,如果没有或者按键不正确,则返回 0。

    key.h

     1#ifndef __KEY_H
    2#define __KEY_H     
    3#include "sys.h" 
    4
    5/*下面方式是通过位带操作方式读取IO*/
    6
    7#define KEY0         PEin(4)     //PE4
    8#define KEY1         PEin(3)     //PE3 
    9#define KEY2         PEin(2)     //P32
    10#define WK_UP     PAin(0)     //PA0
    11
    12
    13
    14#define KEY0_PRES     1
    15#define KEY1_PRES    2
    16#define KEY2_PRES    3
    17#define WKUP_PRES   4
    18
    19void KEY_Init(void);    //IO初始化
    20u8 KEY_Scan(u8);          //按键扫描函数    
    21
    22#endif


    main.c

     1#include "sys.h"
    2#include "delay.h"
    3#include "usart.h"
    4#include "led.h"
    5#include "beep.h"
    6#include "key.h"
    7
    8
    9
    10
    11int main(void)
    12

    13
    14  u8 key;           //保存键值
    15    delay_init(168);  //初始化延时函数
    16    LED_Init();             //初始化LED端口 
    17    BEEP_Init();      //初始化蜂鸣器端口
    18    KEY_Init();       //初始化与按键连接的硬件接口
    19    LED0=0;                 //先点亮红灯
    20    while(1)
    21    {
    22        key=KEY_Scan(0);        //得到键值
    23        if(key)
    24        {                          
    25            switch(key)
    26            {                
    27                case WKUP_PRES: //控制蜂鸣器
    28                    BEEP=!BEEP;
    29                    break;
    30                case KEY0_PRES: //控制LED0翻转
    31                    LED0=!LED0;
    32                    break;
    33                case KEY1_PRES: //控制LED1翻转   
    34                    LED1=!LED1;
    35                    break;
    36                case KEY2_PRES: //同时控制LED0,LED1翻转 
    37                    LED0=!LED0;
    38                    LED1=!LED1;
    39                    break;
    40            }
    41        }else delay_ms(10); 
    42    }
    43
    44}

    主函数代码比较简单,先进行一系列的初始化操作,然后在死循环中调用按键扫描函数KEY_Scan()扫描按键值,最后根据按键值控制 LED 和蜂鸣器的翻转。

    下载验证

    在下载完之后,我们可以按 KEY0、KEY1、KEY2和 KEY_UP 来看看 DS0 和 DS1 以及蜂鸣器的变化,是否和我们预期的结果一致?

     

    下面的是我的公众号二维码图片,欢迎关注。

    图注:小樊Study图注:小樊Study
  • 相关阅读:
    FJNU 1151 Fat Brother And Geometry(胖哥与几何)
    FJNU 1157 Fat Brother’s ruozhi magic(胖哥的弱智术)
    FJNU 1159 Fat Brother’s new way(胖哥的新姿势)
    HDU 3549 Flow Problem(最大流)
    HDU 1005 Number Sequence(数列)
    Tickets(基础DP)
    免费馅饼(基础DP)
    Super Jumping! Jumping! Jumping!(基础DP)
    Ignatius and the Princess IV(基础DP)
    Keywords Search(AC自动机)
  • 原文地址:https://www.cnblogs.com/fw-qql/p/12747910.html
Copyright © 2011-2022 走看看