完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
一 .矩阵按键原理
矩阵按键有两种扫描方式: 方法一: 逐行扫描:我们可以通过低四位轮流输出低电平来对矩阵键盘进行逐行扫描,当高四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一位为0来判断是哪一个按键被按下。 方法二: 行列扫描:我们可以通过高四位全部输出低电平,低四位输出高电平。当接收到的数据,低四位不全为高电平时,说明有按键按下,然后通过接收的数据值,判断是哪一列有按键按下,然后再反过来,高四位输出高电平,低四位输出低电平,然后根据接收到的高四位的值判断是那一行有按键按下,这样就能够确定是哪一个按键按下了。 此次采用的是行扫描方式,与单片机连接如下: C4 -->PB7 C3–>PB6 C2–>PB5 C1–>PB4 R1–>PB3 R2–>PB2 R3–>PB1 R4–>PB0 **二.完整程序** 最开始我使用的是GPIOD的Pin0-Pin5,但是导致了LCD无法正常使用,猜测是GPIOD中的某个IO在LCD中也使用了,导致冲突,具体是哪一个还不知道(技术太菜,LCD里面太多内容,看不懂.....) 1.MatrixButton.h头文件: #ifndef __MatrixButton_H #define __MatrixButton_H #include "sys.h" #define DelayTimes 10 void GPIOF_Int_Init(void); void GPIOB_Int_Init(void); void KEY_Scan(void); void Multiple_Control(void); #endif 2.MatrixButton.c文件代码: #include "MatrixButton.h" #include "delay.h" u16 KeyValue=17;//17只是为了在没有按键按下的时候给一个数值让LCD显示 void GPIOF_Int_Init(void) //(这个函数不属于矩阵按键配置,初始化所要控制的IO口) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);//使能GPIOF时钟 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;//IO输出引脚选用PF0-PF5 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//输出模式 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//输出速度50MHZ GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_DOWN;//下拉 GPIO_Init(GPIOF,&GPIO_InitStructure);//初始化GPIOF } void GPIOB_Int_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);//使能GPIOB的时钟 GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_OUT;//输出模式 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_OType=GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP; GPIO_Init(GPIOB,&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN;//输入模式,用来检测哪一行按下 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP; GPIO_Init(GPIOB,&GPIO_InitStruct); } void KEY_Scan(void) //(行列扫描方式的矩阵按键配置) { GPIO_ResetBits(GPIOB,GPIO_Pin_3); //第一行检测 GPIO_SetBits(GPIOB,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2); if(((GPIOB->IDR )&0xF0)!=0xF0) //说明PD4-PD7状态发生变化,列检测 { delay_ms(DelayTimes); //按键消抖 if(((GPIOB->IDR )&0xF0)!=0xF0) //再次判断是否有按键按下 { switch((GPIOB->IDR )&0xF7)//检测输入数据寄存器PB4-PB7对应位的电平状态 { case 0xE7:KeyValue=1;break;//说明PB4接收到低电平,第一行第一列对应第一个按键 case 0xD7:KeyValue=2;break; case 0xB7:KeyValue=3;break; case 0x77:KeyValue=4;break; default:break; } } } GPIO_ResetBits(GPIOB,GPIO_Pin_2); GPIO_SetBits(GPIOB,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_3); if(((GPIOB->IDR )&0xF0)!=0xF0) //说明PD4-PD7状态发生变化,列检测 { delay_ms(DelayTimes); //按键消抖 if(((GPIOB->IDR )&0xF0)!=0xF0) //再次判断是否有按键按下 { switch((GPIOB->IDR )&0xFB) { case 0xEB:KeyValue=5;break; case 0xDB:KeyValue=6;break; case 0xBB:KeyValue=7;break; case 0x7B:KeyValue=8;break; default:break; } } } GPIO_ResetBits(GPIOB,GPIO_Pin_1); //Pin1输出低电平 GPIO_SetBits(GPIOB,GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_3);//Pin0,Pin2,Pin3输出高电平 if(((GPIOB->IDR )&0xF0)!=0xF0) //说明PD4-PD7状态发生变化,列检测 { delay_ms(DelayTimes); //按键消抖 if(((GPIOB->IDR )&0xF0)!=0xF0) //再次判断是否有按键按下 { switch((GPIOB->IDR )&0xFD) { case 0xED:KeyValue=9;break; case 0xDD:KeyValue=10;break; case 0xBD:KeyValue=11;break; case 0x7D:KeyValue=12;break; default: break; } } } GPIO_ResetBits(GPIOB,GPIO_Pin_0); //Pin0输出低电平 GPIO_SetBits(GPIOB,GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);//Pin1-Pin3输出高电平 if(((GPIOB->IDR )&0xF0)!=0xF0) //说明PD4-PD7状态发生变化,列检测 { delay_ms(DelayTimes); //按键消抖 if(((GPIOB->IDR )&0xF0)!=0xF0) //再次判断是否有按键按下 { switch((GPIOB->IDR )&0xFE) { case 0xEE:KeyValue=13;break; case 0xDE:KeyValue=14;break; case 0xBE:KeyValue=15;break; case 0x7E:KeyValue=16;break; default:break; } } } } void Multiple_Control(void)//控制IO口输出(这个函数通过矩阵键盘的按键控制IO口输出) { if(KeyValue!=17) //说明有按键按下 { switch(KeyValue) { case 1: { GPIO_ResetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2);break;//000 } case 2: { GPIO_ResetBits(GPIOF,GPIO_Pin_1|GPIO_Pin_2); GPIO_SetBits(GPIOF,GPIO_Pin_0);break;//001 } case 3: { GPIO_ResetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_2); GPIO_SetBits(GPIOF,GPIO_Pin_1);break;//010 } case 4: { GPIO_ResetBits(GPIOF,GPIO_Pin_2); GPIO_SetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_1);break;//011 } case 5: { GPIO_ResetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_1); GPIO_SetBits(GPIOF,GPIO_Pin_2);break;//100 } case 6: { GPIO_ResetBits(GPIOF,GPIO_Pin_1); GPIO_SetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_2);break;//101 } case 7: { GPIO_ResetBits(GPIOF,GPIO_Pin_0); GPIO_SetBits(GPIOF,GPIO_Pin_1|GPIO_Pin_2);break;//110 } case 8: { GPIO_SetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2);break;//111 } case 9: { GPIO_ResetBits(GPIOF,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5);break;//000 } case 10: { GPIO_ResetBits(GPIOF,GPIO_Pin_4|GPIO_Pin_5); GPIO_SetBits(GPIOF,GPIO_Pin_3);break;//001 } case 11: { GPIO_ResetBits(GPIOF,GPIO_Pin_3|GPIO_Pin_5); GPIO_SetBits(GPIOF,GPIO_Pin_4); break;//010 } case 12: { GPIO_ResetBits(GPIOF,GPIO_Pin_5); GPIO_SetBits(GPIOF,GPIO_Pin_3|GPIO_Pin_4);break;//011 } case 13: { GPIO_ResetBits(GPIOF,GPIO_Pin_3|GPIO_Pin_4); GPIO_SetBits(GPIOF,GPIO_Pin_5);break;//100 } case 14: { GPIO_ResetBits(GPIOF,GPIO_Pin_4); GPIO_SetBits(GPIOF,GPIO_Pin_5|GPIO_Pin_3);break;//101 } case 15: { GPIO_ResetBits(GPIOF,GPIO_Pin_3); GPIO_SetBits(GPIOF,GPIO_Pin_4|GPIO_Pin_5);break;//110 } case 16: { GPIO_SetBits(GPIOF,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5);break;//111 } } } } 3.主函数main.c: #include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "MatrixButton.h" #include "lcd.h" extern u16 KeyValue; int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置系统中断优先级分组2 delay_init(168); //初始化延时函数 uart_init(115200); //初始化串口波特率为115200 LED_Init(); //初始化LED GPIOF_Int_Init(); LED0=0; LCD_Init(); //初始化LCD接口 GPIOB_Int_Init(); //初始化矩阵键盘所连接IO口 LCD_Display_Dir(1); //横屏显示 POINT_COLOR=RED; while(1) { if(KeyValue!=KeyValue)//按键值改变时才清屏 LCD_Clear(WHITE); LCD_ShowString(30,150,200,16,16,"KeyValue_is:"); //这里显示了KeyValue_is: KEY_Scan(); //行扫描矩阵按键 LCD_ShowxNum(134,150,KeyValue,2,16,0); Multiple_Control(); //矩阵按键控制IO口输出 LED0=!LED0; delay_ms(50); } } |
|
|
|
只有小组成员才能发言,加入小组>>
3322 浏览 9 评论
3000 浏览 16 评论
3497 浏览 1 评论
9070 浏览 16 评论
4090 浏览 18 评论
1191浏览 3评论
613浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
603浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2341浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1899浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-28 21:40 , Processed in 1.129948 second(s), Total 79, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号