野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 10608|回复: 9

读取按键代码

[复制链接]
发表于 2019-6-12 09:08:31 | 显示全部楼层 |阅读模式
[mw_shl_code=c,true]#include "stm32f10x.h"
#include "key.h"
#include "delay.h"

//////////////////////
u32 Keycode;
u32 KEY_Trg;
u32 KEY_Cont=0;
//////////////////////

/**
  * @brief  初始化GPIOB的引脚11到15,分别对应按键1到5
  * @param  无   
  * @retval 无
  */
void KEY_Init(void)
{
        GPIO_InitTypeDef GPIOStructure;
       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);                                                                                                                                 //使能GPIOB
        GPIOStructure.GPIO_Mode = GPIO_Mode_IPU;                                                                                                                                                                                        //上拉输入
        GPIOStructure.GPIO_Pin =GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;        //KEY1-5用到的GPIO口为GPIOB11-15
        GPIOStructure.GPIO_Speed = GPIO_Speed_10MHz;
        GPIO_Init(GPIOB, &GPIOStructure);
}


static uint32_t Change_GPIOCode(void)
{
        u32 GPIO_Data;
        GPIO_Data=(((GPIOB->IDR)>>11)&0xffff)|(~(KEY1BIT+KEY2BIT+KEY3BIT+KEY4BIT+KEY5BIT));
        return GPIO_Data;
}


unsigned char KEY_Read(void)
{
        u32 ReadData = Change_GPIOCode()^0XFFFFFFFF;     // 异或后,ReadData的位5-31均为0,
        KEY_Trg = ReadData & (ReadData ^ KEY_Cont);      // 2
        KEY_Cont = ReadData;
        if(KEY_Cont)
        {
                        delay_ms(10);
                        ReadData = Change_GPIOCode()^0XFFFFFFFF;   // 1
                        KEY_Trg = ReadData & (ReadData ^ KEY_Cont);      // 2
                        KEY_Cont = ReadData;
                        if(KEY_Cont)
                        {
                                switch(KEY_Cont)
                                {
                                        case K_1:{Keycode = K_1_S; break;}
                                        case K_2:{Keycode = K_2_S; break;}        
                                        case K_3:{Keycode = K_3_S; break;}
                                        case K_4:{Keycode = K_4_S; break;}
                                        case K_5:{Keycode = K_5_S; break;}
                                        default:{Keycode = K_NO; break;}
                                }       
                        }
        }
        return Keycode;
}


void KEY_EXIT(void)
{
        if(Keycode != K_NO)
        {
                Keycode = K_NO;
        }       
}
[/mw_shl_code]

大佬救救我,unsigned char KEY_Read(void),static uint32_t Change_GPIOCode(void)这两个函数干嘛用的?
(~(KEY1BIT+KEY2BIT+KEY3BIT+KEY4BIT+KEY5BIT))这句代码有什么用,前人没打备注完全看不懂啊。


[mw_shl_code=c,true]#ifndef __key_H
#define __key_H

#include "stm32f10x.h"

#define YES          1
#define NO          0

#define T_10mS        ((u32)10)
#define T_1S        ((u32)1000)
#define T_330mS        ((u32)330)
///////////////////////////////
#define KEY1BIT GPIO_Pin_0
#define KEY2BIT GPIO_Pin_1
#define KEY3BIT GPIO_Pin_2
#define KEY4BIT GPIO_Pin_3
#define KEY5BIT GPIO_Pin_4

////////原始码值///////////////
#define K_1                KEY1BIT
#define K_2                KEY2BIT
#define K_3                KEY3BIT
#define K_4                KEY4BIT
#define K_5                KEY5BIT

//////////////////////////////

////////码值重映射////////////
#define K_1_S                0X01      
#define K_2_S                0X02
#define K_3_S                0X03
#define K_4_S                0X04
#define K_5_S                0X05

#define K_1_L                0X0B        
#define K_2_L                0X0C
#define K_3_L                0X0D
#define K_4_L                0X0E
#define K_5_L                0X0F

#define K_NO                0X00000000
///////////////////////////////////

extern u32 KEY_Trg;
extern u32 KEY_Cont;
extern u32 Keycode;

void KEY_Init(void);
unsigned char KEY_Read(void);
void KEY_EXIT(void);


#endif
[/mw_shl_code]
回复

使用道具 举报

发表于 2019-6-12 10:04:17 | 显示全部楼层
Change_GPIOCode  里面用 GPIOB->IDR 读取 变化的了GPIO状态值?然后KEY_Read里面有再用一次但感觉又不像消抖的意思,看晕了……
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-6-12 10:57:11 | 显示全部楼层
WishWish 发表于 2019-6-12 10:04
Change_GPIOCode  里面用 GPIOB->IDR 读取 变化的了GPIO状态值?然后KEY_Read里面有再用一次但感觉又不像消 ...

他的意思貌似是:因为按键原来接在pin11到pin15,change_GPIOCode()是将pin11-pin15的值右移到pin0-pin4.
然后KEY_Read函数返回了1、2、3、4、5代表5个按键,就不在用引脚表示5个按键了,后面要用到这些返回值做运算应该。

GPIO_Data=(((GPIOB->IDR)>>11)&0xffff)|(~(KEY1BIT+KEY2BIT+KEY3BIT+KEY4BIT+KEY5BIT));这句代码后面的(~(KEY1BIT+KEY2BIT+KEY3BIT+KEY4BIT+KEY5BIT))什么意思?
回复 支持 反对

使用道具 举报

发表于 2019-6-12 11:30:18 | 显示全部楼层
wx_qI5uA9eD 发表于 2019-6-12 10:57
他的意思貌似是:因为按键原来接在pin11到pin15,change_GPIOCode()是将pin11-pin15的值右移到pin0-pin4. ...

0X1F取反就是相当于~(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4) 应该是为了获取哪些按键按下了吧
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-6-12 12:02:00 | 显示全部楼层
非谢家之宝树 发表于 2019-6-12 11:30
0X1F取反就是相当于~(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4) 应该是为了获取哪些按键 ...

GPIO_pin0-4默认为1吗?我记得好像是默认为0
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-6-12 12:03:08 | 显示全部楼层
非谢家之宝树 发表于 2019-6-12 11:30
0X1F取反就是相当于~(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4) 应该是为了获取哪些按键 ...

GPIO_Pin_0、GPIO_Pin_1、GPIO_Pin_2、GPIO_Pin_3、GPIO_Pin_4这四个引脚没有配置,默认值是多少?
回复 支持 反对

使用道具 举报

发表于 2019-6-12 13:11:14 | 显示全部楼层
本帖最后由 非谢家之宝树 于 2019-6-12 13:15 编辑
wx_qI5uA9eD 发表于 2019-6-12 12:03
GPIO_Pin_0、GPIO_Pin_1、GPIO_Pin_2、GPIO_Pin_3、GPIO_Pin_4这四个引脚没有配置,默认值是多少?

这个在st的库里有定义,可以看看就知道了[mw_shl_code=c,true]#define GPIO_Pin_0                 ((uint16_t)0x0001)  /*!< Pin 0 selected */
#define GPIO_Pin_1                 ((uint16_t)0x0002)  /*!< Pin 1 selected */
#define GPIO_Pin_2                 ((uint16_t)0x0004)  /*!< Pin 2 selected */
#define GPIO_Pin_3                 ((uint16_t)0x0008)  /*!< Pin 3 selected */
#define GPIO_Pin_4                 ((uint16_t)0x0010)  /*!< Pin 4 selected */
#define GPIO_Pin_5                 ((uint16_t)0x0020)  /*!< Pin 5 selected */
#define GPIO_Pin_6                 ((uint16_t)0x0040)  /*!< Pin 6 selected */
#define GPIO_Pin_7                 ((uint16_t)0x0080)  /*!< Pin 7 selected */
#define GPIO_Pin_8                 ((uint16_t)0x0100)  /*!< Pin 8 selected */
#define GPIO_Pin_9                 ((uint16_t)0x0200)  /*!< Pin 9 selected */
#define GPIO_Pin_10                ((uint16_t)0x0400)  /*!< Pin 10 selected */
#define GPIO_Pin_11                ((uint16_t)0x0800)  /*!< Pin 11 selected */
#define GPIO_Pin_12                ((uint16_t)0x1000)  /*!< Pin 12 selected */
#define GPIO_Pin_13                ((uint16_t)0x2000)  /*!< Pin 13 selected */
#define GPIO_Pin_14                ((uint16_t)0x4000)  /*!< Pin 14 selected */
#define GPIO_Pin_15                ((uint16_t)0x8000)  /*!< Pin 15 selected */
#define GPIO_Pin_All               ((uint16_t)0xFFFF)  /*!< All pins selected */[/mw_shl_code]
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-6-12 16:50:29 | 显示全部楼层
非谢家之宝树 发表于 2019-6-12 13:11
这个在st的库里有定义,可以看看就知道了[mw_shl_code=c,true]#define GPIO_Pin_0                 ((uin ...

谢谢大神,问题已解决。万分感谢
回复 支持 反对

使用道具 举报

发表于 2019-7-21 11:22:22 | 显示全部楼层
wx_qI5uA9eD 发表于 2019-6-12 16:50
谢谢大神,问题已解决。万分感谢

兄弟,我还是没搞懂,能解释下吗,万分感谢
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-8-1 20:55:55 | 显示全部楼层
wx_sXxgHXxa 发表于 2019-7-21 11:22
兄弟,我还是没搞懂,能解释下吗,万分感谢

[mw_shl_code=c,true]/**
  *                与1异或相当于取反,与0异或相当于不变。
        *                第一种情况:没有按键按下的时候,GPIO_Data为0XFFFFFFFF,ReadData经过取反后自然是0X0了。KEY_Trg = 0&(0^0) = 0X0。(初始状态下Cont为0)
        *                                                                KEY_Cont = ReadData = 0。结果就是ReadData = 0;KEY_Trg = 0;KEY_Cont = 0;即没有按键按下。
        *
        *                第二种情况:Key1第一次按下,GPIO_Data为0XFFFFFFFE,ReadData经过取反后自然是0X01了。KEY_Trg = 0X01&(0X01^0) = 0X01。这是第一次按下Cont
        *                                                                仍为上次的值。KEY_Cont = ReadData = 0X01。所以ReadData = 0X01;KEY_Trg = 0X01;KEY_Cont = 0X01。
        *
        *                第三种情况:key1长按着不放,GPIO_Data为0XFFFFFFFE,ReadData经过取反后自然是0X01了。KEY_Trg = 0X01&(0X01^0X01) = 0X0。Cont是上次按下的值
        *                                                                并没有对Cont清零的语句。所以ReadData = 0X01;KEY_Trg = 0X0;KEY_Cont = 0X01。
        *                                                                只要按键按着不放,一直执行这个函数,ReadData永远不变,KEY_Cont永远为上次值,即0X01,KEY_Trg永远为0X0。
        *
        *                第四种情况:key1按键松开,GPIO_Data为0XFFFFFFFF,ReadData经过取反后自然是0X0了。KEY_Trg = 0 &(0^0X1) = 0X0,KEY_Cont = ReadData = 0。
        *                                                                结果就是ReadData = 0;KEY_Trg = 0;KEY_Cont = 0;即没有按键按下。
        *
        *                总结                 :Trg就是跳变,只要按键按下,电平从1到0跳变了,那么KEY_Trg对应的按键位置1。KEY_Trg的值每次按下只会出现一次(只会在情况二出现一次),
        *                                                                然后立马被清除。不需要其它判断条件。
  * @brief  读取五个按键的状态,并返回对应的按键编码。
  * @param  无   
  * @retval Keycode:按键对应编号,
  */[/mw_shl_code]
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-5-27 13:00 , Processed in 0.040603 second(s), 29 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表