赞
踩
目录
GPIO_Write()函数和GPIO_ReadInputData()函数
了解矩阵键盘之前,应当要对基本按键的检测要有认识:如下图
右边按键一端接低电平,一段接PB1。设置PB1为上拉输入,相当于按键两端分别置0和1(低电平和高电平)。按键未按下时,对PB1检测,PB1电平就为高(1)。那么当按键按下时,PB1与地导通,此时对PB1检测,PB1电平就为低(0)。
所以,通过检测原来高电平的引脚是否变低则可以判断按键是否按下。
这里我初始化是将高四位引脚设置为上拉输入,低四位引脚设置为推挽输出。
- #include "stm32f10x.h" // Device header
- #include "Delay.h"
- uint16_t keyz=0;
-
- void Key_Init(void)
- {
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE );
-
- GPIO_InitTypeDef GPIO_KEY0_3;
- GPIO_KEY0_3.GPIO_Mode=GPIO_Mode_Out_PP;
- GPIO_KEY0_3.GPIO_Pin=GPIO_Pin_0 |GPIO_Pin_1 |GPIO_Pin_2 |GPIO_Pin_3 ;
- GPIO_KEY0_3.GPIO_Speed=GPIO_Speed_50MHz;
- GPIO_Init (GPIOA ,&GPIO_KEY0_3);
-
- GPIO_InitTypeDef GPIO_KEY1_4;
- GPIO_KEY1_4.GPIO_Mode=GPIO_Mode_IPU;
- GPIO_KEY1_4.GPIO_Pin=GPIO_Pin_4 |GPIO_Pin_5 |GPIO_Pin_6 |GPIO_Pin_7 ;
- GPIO_KEY1_4.GPIO_Speed=GPIO_Speed_50MHz;
- GPIO_Init (GPIOA ,&GPIO_KEY1_4);
- }
GPIO_Write()函数可以对多个引脚同时进行配置,此函数有两个参数,第一个为引脚分组,第二个为一个十六进制数。这个十六进制数就是按其对应的二进制对引脚电平进行配置。如GPIO_Write(GPIOA ,0xF0);为1111 0000,即对PA0-PA3引脚置低电平,对PA4-PA8引脚置高电平。
GPIO_ReadInputData()函数输出的是十六进制表示的引脚状态。
当按键未按下时使用 GPIO_ReadInputData()函数读取按键,读取值为0xF0,即1111 0000;
高四位代表 列 对应引脚状态,低四位代表 行 对应引脚状态。
如果当按键按下时使用 GPIO_ReadInputData()函数读取按键,此时按下按键 列数 对应的引脚为0,再进行Lie=~GPIO_ReadInputData (GPIOA ); Lie=Lie&0xF0; 则得到列数。
将行对应引脚电位逐次拉高,当轮到 按下按键对应行数时 ,由于按键两端都为1,则(GPIO_ReadInputData (GPIOA )&0xF0)!=0xF0;否则(GPIO_ReadInputData (GPIOA )&0xF0)==0xF0;由此可得行数。
- u16 Key_Scan(void)
- {
- uint8_t Hang,Lie,k,i;
-
- GPIO_Write(GPIOA ,0xF0); //将A0-A3口和A4-7口电位分别置成低电位和高电位
- //0xF0 转换成二进制为 1111 0000;
- if((GPIO_ReadInputData(GPIOA)&0xF0)!=0xF0) //判断按键是否按下
- {
- Delay_ms (40); //按键消抖
- if((GPIO_ReadInputData(GPIOA)&0xF0)!=0xF0) //再次判断
- {
-
- Hang=GPIO_ReadInputData (GPIOA ); //给Hang赋上初值,读取按键按下后得到的代码,假设为1011 0000 (0xB0)
- Lie=~Hang; //对Hang按位取反,即0100 1111
- Lie=Lie&0xF0; //0100 1111 &1111 0000得到0100 0000 即为列数
- //得到列数
- for(i=0;i<4 && ((Hang&0xF0)!=0xF0);i++) //逐次将行拉高,判断列数中原来变低的位是否变高
- { //读到之前检测到为低的列变高则推出
- GPIO_Write (GPIOA ,0xF0|(0x01<<i)); //进行行扫描,逐次将行口线拉高,列保持为按下的状态
- Hang=GPIO_ReadInputData (GPIOA ); //读取IO口,用以判断是否扫描到行坐标
- }
- Hang&=0x0F;
- //得到行值
- k=Hang|Lie; //行列相加则得到键码
-
- GPIO_Write (GPIOA ,0xF0); //A0-A3拉低,A4-A7拉高,此处用来将行状态初始化为未按下时的状态
- while((GPIO_ReadInputData(GPIOA)&0xF0)!=0xF0)//判释放
- {
- Delay_ms (40); //后延消抖。时间需要长一点
- }
- return k;
- //返回键码
- }
-
- }
- return (0); //无键按下,返回0
- }
- u16 Key_Get(void)
- {
- keyz =Key_Scan ();
- uint16_t Keyx=0;
- if (keyz!=0)
- {
- switch(keyz)
- {
- case 0x81:Keyx=1;break;
- case 0x82:Keyx=2;break;
- case 0x84:Keyx=3;break;
- case 0x88:Keyx=4;break;
- case 0x41:Keyx=5;break;
- case 0x42:Keyx=6;break;
- case 0x44:Keyx=7;break;
- case 0x48:Keyx=8;break;
- case 0x21:Keyx=9;break;
- case 0x22:Keyx=10;break;
- case 0x24:Keyx=11;break;
- case 0x28:Keyx=12;break;
- case 0x11:Keyx=13;break;
- case 0x12:Keyx=14;break;
- case 0x14:Keyx=15;break;
- case 0x18:Keyx=16;break;
- default:break;
- }
- }
- return Keyx;
-
- }
实例:单数遇到双数按键分别亮两个不同的灯mat key · 灵槐梦/stm32 - 码云 - 开源中国 (gitee.com)
更新,对于行判断的解释:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。