stm控制乘矩阵键盘程序带松手检测
proteus中4乘4矩阵键盘代码
KeyValue=KeyValue+12;
break;
//default:KeyValue=17;
}
while((a<50)&&(GPIO_KEY!=0xf0))//检测按键松手检测
{
Delay10ms();
a++;
}
a=0;
}
}
// switch(KeyValue)
// {
// case(10):
// case(14):
// KeyValue=KeyValue;
// break;
// case(15):
// KeyValue=KeyValue;
// break;
// }
}
/*******************************************************************************
*函数名: Delay10ms
*函数功能:延时函数,延时10ms
*输入:无
*输出:无
*******************************************************************************/
void Delay10ms(void) //误差0us
{
unsigned char a,b,c;
for(c=1; c>0; c--)
for(b=38; b>0; b--)
for(a=130; a>0; a--);
}
#include <Key.h>
unsigned char KeyValue;//用来存放读取到的键值
单片机控制的矩阵键盘扫描程序集
单片机控制的矩阵键盘扫描程序集各种各样的矩阵键盘扫描程序集矩阵键盘的扫描对初学者来说是不可避免的,然而也相对来说有点难度.鉴于此,我整理了一下,我所遇到的矩阵键盘扫描程序集,将相继贴上来,供大家参考! 说明:这些大多都是网上转贴来的,其所有权归原作者!谢谢合作.最简单矩阵键盘扫描程序key:MOV p0,#00001111b;上四位和下四位分别为行和列,所以送出高低电压检查有没有按键按下jmp k10;跳到K10处开始扫描,这里可以改成其它条件转移指令来决定本次扫描是否要继续,例如减1为0转移或者位为1或0才转移,这主要用来增加功能,确认上一按键功能是否完成?是否相当于经过了延时?是否要封锁键盘?goend:jmp kend;如果上面判断本次不执行键盘扫描程序,则立即转到程序尾部,不要浪费CPU的时间k10:jb p0.0,k20;扫描正式开始,先检查列1四个键是否有键按下,如果没有,则跳到K20检查列2k11:MOV p0,#11101111b;列1有键按下时,P0.0变低,到底是那一个键按下?现在分别输出各行低电平jb p0.0,k12;该行的键不按下时,p0.0为高电平,跳到到K12,检查其它的行MOV r1,#1;如果正好是这行的键按下,将寄存器R0写下1,表示1号键按下了k12:MOV p0,#11011111bjb p0.0,k13MOV r1,#2;如果正好是这行的键按下,将寄存器R0写下2,表示2号键按下了k13:MOV p0,#10111111bjb p0.0,k14MOV r1,#3;如果正好是这行的键按下,将寄存器R0写下3,表示3号键按下了k14:MOV p0,#01111111bjb p0.0,kend;如果现在四个键都没有按下,可能按键松开或干扰,退出扫描(以后相同)MOV r1,#4如果正好是这行的键按下,将寄存器R0写下4,表示4号键按下了jmp kend;已经找到按下的键,跳到结尾吧k20:jb p0.1,k30;列2检查为高电平再检查列3、4k21:MOV p0,#11101111b;列2有健按下时,P0.0会变低,到底是那一行的键按下呢?分别输出行的低电平jb p0.1,k22;该行的键不按下时p0.0为高电平,跳到到K22,检查另外三行MOV r1,#5;如果正好是这行的键按下,将寄存器R0写下5,表示5号键按下了(以后相同,不再重复了)k22:MOV p0,#11011111bjb p0.1,k23MOV r1,#6k23:MOV p0,#10111111bjb p0.1,k24MOV r1,#7k24:MOV p0,#01111111bjb p0.1,kendMOV r1,#8jmp kend;已经找到按下的键,跳到结尾吧(以后相同,不要重复了)k30:jb p0.2,k40k31:MOV p0,#11101111bjb p0.2,k32MOV r1,#9k32:MOV p0,#11011111bjb p0.2,k33MOV r1,#10k33:MOV p0,#10111111bjb p0.2,k34MOV r1,#11k34:MOV p0,#01111111bjb p0.2,kendMOV r1,#12jmp kendk40:jb p0.3,kendk41:MOV p0,#11101111bjb p0.3,k42MOV r1,#13k42:MOV p0,#11011111bjb p0.3,k43MOV r1,#14k43:MOV p0,#10111111bjb p0.3,k44MOV r1,#15k44:MOV p0,#01111111bjb p0.3,kendMOV r1,#16kend: ret行列扫描键盘可检测出双键按下#include <reg52.h>#define ulong unsigned long#define uint unsigned int#define uchar unsigned charextern void delay(unsigned int x);unsigned char Tab_key[]= //行列式键盘映射{0x00, //无键按下’’7’’,’’8’’,’’9’’,’’/’’,’’4’’,’’5’’,’’6’’,’’*’’,’’1’’,’’2’’,’’3’’,’’-’’,’’C’’,’’0’’,’’=’’,’’+’’,//下面为按’’C’’同时再按的键:’’7’’,’’8’’,’’9’’,’’/’’,’’4’’,’’5’’,’’6’’,’’*’’,’’1’’,’’2’’,’’3’’,’’-’’,’’0’’,’’=’’,’’+’’,};// P1口行列式键盘//#define KEYPIN_L P1 // 定义键扫描列端口为P1低四位输入//#define KEYPIN_H P1 // 定义键扫描行端口为P1高四位扫描输出//// P1口行列式键盘////公用函数unsigned char KeysCAN(void); // 键扫描函数// //内部私有函数unsigned char fnKeycode(unsigned char key); // 根据键盘映射表输出顺序键值///*// P1口行列式键盘//extern unsigned char KeysCAN(void); // 键扫描函数//*/// P1口行列式键盘////---------------------------------------------------------------------------//unsigned char KeysCAN(void) // 键扫描函数//{unsigned char sccode,recode,keytemp = 0;KEYPIN_L = KEYPIN_L|0x0f; // P1低四位为列线输入//KEYPIN_H = KEYPIN_H&0x0f; // P1高四位为行线发全零扫描码//if ((KEYPIN_L&0x0f) != 0x0f){delay(10); // 延时10 MS 消抖//if ((KEYPIN_L&0x0f) != 0x0f){sccode = 0xef; // 逐行扫描码初值(1110 1111) //while(sccode != 0xff) //将扫描4次,keytemp为每次键值相或的值//{KEYPIN_H = sccode; // 输出行扫描码//if ((KEYPIN_L&0x0f) != 0x0f) // 本行有键按下//{recode = (KEYPIN_L&0x0f)|0xf0; // 只要低位,高位置1 //keytemp |= (~sccode)+(~recode); //特征码(高位为列P3,低位为行KEYPIN_H) //}sccode = (sccode << 1)|0x01; // 扫描码0向高位移动//}}}KEYPIN_H = KEYPIN_H|0xf0;return(fnKeycode(keytemp));}//---------------------------------------------------------------------------//unsigned char fnKeycode(unsigned char key) // 根据键盘映射表输出顺序键值//{switch(key){case 0x11: // 1 键//key = 0x01;break;case 0x21: // 2 键// key = 0x02;break;case 0x41: // 3 键// key = 0x03;break;case 0x81: // 4 键// key = 0x04;break;case 0x12: // 5 键// key = 0x05;break;case 0x22: // 6 键// key = 0x06;break;case 0x42: // 7 键// key = 0x07;break;case 0x82: // 8 键// key = 0x08;break;case 0x14: // 9 键// key = 0x09;break;case 0x24: // 10 键// key = 0x0A;break;case 0x44: // 11 键// key = 0x0B;break;case 0x84: // 12 键// key = 0x0C;break;case 0x18: // 13 键// key = 0x0D;break;case 0x28: // 14 键// key = 0x0E;break;case 0x48: // 15 键// key = 0x0F;break;case 0x88: // 16 键// key = 0x10;break;//以下为功能键//case 0x19: // ’’C’’ +1 键//key = 0x11;break;ca se 0x29: // ’’C’’ +2 键//key = 0x12;break;case 0x49: // ’’C’’ +3 键//key = 0x13;break;case 0x89: // ’’C’’ +4 键//key = 0x14;break;case 0x1A: // ’’C’’ +5 键// key = 0x15;break;case 0x2A: // ’’C’’ +6 键// key = 0x16;break;case 0x4A: // ’’C’’ +7 键// key = 0x17;break;case 0x8A: // ’’C’’ +8 键// key = 0x18;break;case 0x1C: // ’’C’’ +9 键//key = 0x19;break;case 0x2C: // ’’C’’ +10 键// key = 0x1A;break;case 0x4C: // ’’C’’ +11 键// key = 0x1B;break;case 0x8C: // ’’C’’ +12 键// key = 0x1C;break;// case 0x18: // ’’C’’ +13 键// // key = 0x1D;// break;case 0x38: // ’’C’’ +14 键// key = 0x1D;break;case 0x58: // ’’C’’ +15 键// key = 0x1E;break;case 0x98: // ’’C’’ +16 键// key = 0x1F;break;default : // 无键//key = 0x00;break;}return(Tab_key[key]);}矩键查寻键值44程序与显示#include <reg52.h>//#include <math.h>#include <intrins.h>#define uchar unsigned char#define TURE 1#define FALSE 0int key;int del;void Tkey(void);void led(void);/************主程序*************/void main(void){void tkey(void);void led(void);void delay(int);SCON=0x00;TI=0;while(TURE){Tkey();led();delay(2000);}}/********矩键查寻键值4*4程序******/按键为P1.0---P1.7 void Tkey(void){uchar readkey;//rereadkey;uchar x_temp,y_temp;P1=0x0f;x_temp=P1&0x0f;if(x_temp==0x0f) goto keyout;P1=0xf0;y_temp=P1&0xf0;readkey=x_temp|y_temp;readkey=~readkey;switch(readkey){case 0x11:key=0; break;case 0x21:key=1; break;case 0x41:key=2; break;case 0x81:key=3; break;case 0x12:key=4; break;case 0x22:key=5; break;case 0x42:key=6; break;case 0x82:key=7; break;case 0x14:key=8; break;case 0x24:key=9; break;case 0x44:key=10;break;case 0x84:key=11;break;case 0x18:key=12;break;case 0x28:key=13;break;case 0x48:key=14;break;case 0x88:key=15;break;default: key=16;break;}keyout:_nop_();}/************显示程序*************/void led(void){uchar code LEDValue[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //0-9 uchar data num[6];uchar k;num[0]=0;num[1]=0;num[2]=0;num[3]=0;num[4]=key/10;num[5]=key-(key/10)*10;for(k=0;k<=5;k++){SBUF=LEDValue[num[5-k]];while(TI==0);TI=0;}}/************延时程序*************/void delay(del){for(del;del>0;del--);;伪定义KEYBUF EQU 30H ;键值暂存单元,查表时用;*************************************;* *;* 主程序和中断程序入口*;* *;*************************************ORG 0000H ;程序执行开始地址AJMP MAIN ;跳至MAIN执行;*************************************;* *;* 主程序*;* *;*************************************ORG 0040HMAIN: MOV P1,#0FFHMOV P3,#0FFHLCALL KEYSCAN ;主体程序。
实验一 矩阵键盘检测
实验一矩阵键盘检测一、实验目的:1、学习非编码键盘的工作原理和键盘的扫描方式。
2、学习键盘的去抖方法和键盘应用程序的设计。
二、实验设备:51/AVR实验板、USB连接线、电脑三、实验原理:键盘接口电路是单片机系统设计非常重要的一环,作为人机交互界面里最常用的输入设备。
我们可以通过键盘输入数据或命令来实现简单的人机通信。
1、按键的分类一般来说,按键按照结构原理可分为两类,一类是触点式开关按键,如机械式开关、导电橡胶式开关等;另一类是无触点式开关按键,如电气式按键,磁感应按键等。
前者造价低,后者寿命长。
目前,微机系统中最常见的是触点式开关按键(如本学习板上所采用按键)。
按键按照接口原理又可分为编码键盘与非编码键盘两类,这两类键盘的主要区别是识别键符及给出相应键码的方法。
编码键盘主要是用硬件来实现对键的识别,非编码键盘主要是由软件来实现键盘的识别。
全编码键盘由专门的芯片实现识键及输出相应的编码,一般还具有去抖动和多键、窜键等保护电路,这种键盘使用方便,硬件开销大,一般的小型嵌入式应用系统较少采用。
非编码键盘按连接方式可分为独立式和矩阵式两种,其它工作都主要由软件完成。
由于其经济实用,较多地应用于单片机系统中(本学习板也采用非编码键盘)。
2、按键的输入原理在单片机应用系统中,通常使用机械触点式按键开关,其主要功能是把机械上的通断转换成为电气上的逻辑关系。
也就是说,它能提供标准的TTL 逻辑电平,以便与通用数字系统的逻辑电平相容。
此外,除了复位按键有专门的复位电路及专一的复位功能外,其它按键都是以开关状态来设置控制功能或输入数据。
当所设置的功能键或数字键按下时,计算机应用系统应完成该按键所设定的功能。
因此,键信息输入是与软件结构密切相关的过程。
对于一组键或一个键盘,通过接口电路与单片机相连。
单片机可以采用查询或中断方式了解有无按键输入并检查是哪一个按键按下,若有键按下则跳至相应的键盘处理程序处去执行,若无键按下则继续执行其他程序。
STM矩阵键盘程序
/--------------------------------------------------------------------------------------矩阵键盘驱动文件:keyboard.c编写人:LiuHui描述:扫描4x4矩阵键盘输入,并返回键值适用范围:驱动采用ST3.5库编写,适用于STM32F10x系列单片机所用引脚:PA0-PA7编写时间:2014年5月20日--------------------------------------------------------------------------------------/include"stm32f10x.h"include"keyboard.h"include"dealy.h"/--------------------------------矩阵键盘初始化----------------------------------------功能:初始化stm32单片机GPIO//PA0-PA7参数传递:输入:无返回值:无--------------------------------------------------------------------------------------/voidKeyBoard_Initvoid{GPIO_InitTypeDefGPIO_InitStructure;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitGPIOA,&GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;GPIO_InitGPIOA,&GPIO_InitStructure;GPIO_SetBitsGPIOA,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;GPIO_ResetBitsGPIOA,GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;}/------------------------------矩阵键盘扫描--------------------------------------------功能:扫描矩阵键盘,并返回键值参数:输入:无返回:有键按下返回该键值无键按下时则返回0--------------------------------------------------------------------------------------/u8Read_KeyValuevoid{u8KeyValue=0;ifGPIO_ReadInputDataGPIOA&0xff=0x0f{Delay_ms10;ifGPIO_ReadInputDataGPIOA&0xff=0x0f{GPIO_SetBitsGPIOA,GPIO_Pin_0;GPIO_ResetBitsGPIOA,GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; switchGPIO_ReadInputDataGPIOA&0xff{case0x11:KeyValue=1;break;case0x21:KeyValue=5;break;case0x41:KeyValue=9;break;case0x81:KeyValue=13;break;}GPIO_SetBitsGPIOA,GPIO_Pin_1;GPIO_ResetBitsGPIOA,GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_3; switchGPIO_ReadInputDataGPIOA&0xff{case0x12:KeyValue=2;break;case0x22:KeyValue=6;break;case0x42:KeyValue=10;break;case0x82:KeyValue=14;break;}GPIO_SetBitsGPIOA,GPIO_Pin_2;GPIO_ResetBitsGPIOA,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_3;switchGPIO_ReadInputDataGPIOA&0xff{case0x14:KeyValue=3;break;case0x24:KeyValue=7;break;case0x44:KeyValue=11;break;case0x84:KeyValue=15;break;}GPIO_SetBitsGPIOA,GPIO_Pin_3;GPIO_ResetBitsGPIOA,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2; switchGPIO_ReadInputDataGPIOA&0xff{case0x18:KeyValue=4;break;case0x28:KeyValue=8;break;case0x48:KeyValue=12;break;case0x88:KeyValue=16;break;}GPIO_SetBitsGPIOA,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; GPIO_ResetBitsGPIOA,GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;whileGPIO_ReadInputDataGPIOA&0xff=0x0f;returnKeyValue;}}return0;}/--------------------------------THEEND--------------------------------------------//--------------------------------------------------------------------------------------矩阵键盘驱动文件:keyboard.h编写人:LiuHui描述:扫描4x4矩阵键盘输入,并返回键值适用范围:驱动为ST3.5库编写,适用于STM32F10x系列单片机所用引脚:PA0-PA7编写时间:2013 年11 月22日版本:1.0--------------------------------------------------------------------------------------/ifndef__KEYBOARD_Hdefine__KEYBOARD_HvoidKeyBoard_Initvoid;u8Read_KeyValuevoid;endif/----------------------------------THEEND------------------------------------------include"stm32f10x.h"voidKeyBoard_Initvoid{GPIO_InitTypeDefGPIO_InitStructure;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_All;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitGPIOA,&GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_All;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;GPIO_InitGPIOB,&GPIO_InitStructure;GPIO_SetBitsGPIOB,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6; GPIO_ResetBitsGPIOB,GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10; }//3êˉPA,PBvoidDelay_msinttime{inti=0;whiletime--{i=12000;whilei--;}}u8Read_KeyValuevoid{u8KeyValue=1;ifGPIO_ReadInputDataGPIOB&0xff=0x0f{Delay_ms10;ifGPIO_ReadInputDataGPIOB&0xff=0x0f{GPIO_SetBitsGPIOB,GPIO_Pin_3;GPIO_ResetBitsGPIOB,GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6; switchGPIO_ReadInputDataGPIOB&0xff{case0x11:KeyValue=7;break;case0x21:KeyValue=4;break;case0x41:KeyValue=1;break;case0x81:KeyValue=0;break;}GPIO_SetBitsGPIOB,GPIO_Pin_4;GPIO_ResetBitsGPIOB,GPIO_Pin_3|GPIO_Pin_5|GPIO_Pin_6; switchGPIO_ReadInputDataGPIOB&0xff{case0x12:KeyValue=8;break;case0x22:KeyValue=5;break;case0x42:KeyValue=2;break;case0x82:KeyValue=0;break;}GPIO_SetBitsGPIOB,GPIO_Pin_5;GPIO_ResetBitsGPIOB,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_6;switchGPIO_ReadInputDataGPIOB&0xff{case0x14:KeyValue=9;break;case0x24:KeyValue=6;break;case0x44:KeyValue=3;break;case0x84:KeyValue=0;break;}GPIO_SetBitsGPIOB,GPIO_Pin_6;GPIO_ResetBitsGPIOB,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;switchGPIO_ReadInputDataGPIOB&0xff{case0x18:KeyValue=0;break;case0x28:KeyValue=0;break;case0x48:KeyValue=0;break;case0x88:KeyValue=0;break;}GPIO_SetBitsGPIOB,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6; GPIO_ResetBitsGPIOB,GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10; //whileGPIO_ReadInputDataGPIOB&0xff=0x0f;returnKeyValue;}}return0;}uint16_ttable={0xEB,0x28,0xB3,0xBA,0x78,0xDA,0xDB,0xA8,0xFB,0xFA}; intmain{RCC_APB2PeriphClockCmdRCC_APB2Periph_GPIOA,ENABLE;RCC_APB2PeriphClockCmdRCC_APB2Periph_GPIOB,ENABLE;KeyBoard_Init;intkeyvalue=Read_KeyValue;GPIO_WriteGPIOA,tablekeyvalue;/while1{inti;fori=0;i<10;i++{GPIO_WriteGPIOA,tablei;Delay_ms500;}}//u8keyvalue;forinti=0;;i++{KeyBoard_Init;keyvalue=Read_KeyValue;GPIO_WriteGPIOA,tablekeyvalue;Delay_ms500;}/}include"stm32f10x.h"voidKeyBoard_Initvoid{GPIO_InitTypeDefGPIO_InitStructure;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_All;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitGPIOA,&GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6| GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;GPIO_InitGPIOB,&GPIO_InitStructure;GPIO_SetBitsGPIOB,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6;GPIO_ResetBitsGPIOB,GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10;}voidDelay_msinttime{inti=0;whiletime--{i=12000;whilei--;}}u8Read_KeyValuevoid{ifGPIO_ReadInputDataGPIOB&0xff=0x73//在这个程序下为什么无论是GPIO_ReadInputDataGPIOB&0xff=0x73还是GPIO_ReadInputDataGPIOB&0xff==0x73都能往下运行,而在屏蔽Delay_ms10后则只能运行一种,是因为这个Delay_ms10对if里的判断有影响吗{Delay_ms10;GPIO_WriteGPIOA,0x33;}return0;}intmain{RCC_APB2PeriphClockCmdRCC_APB2Periph_GPIOA,ENABLE;RCC_APB2PeriphClockCmdRCC_APB2Periph_GPIOB,ENABLE;KeyBoard_Init;Read_KeyValue;}。
51单片机矩阵键盘线反转法体会
51单片机矩阵键盘线反转法体会独立式键盘扫描只需读取IO口状态,而矩阵式键盘描通常有两种实现方法:逐行扫描法和线反转法。
(1)逐行扫描法依次从第一至最末行线上发出低电平信号, 如果该行线所连接的键没有按下的话, 则列线所接的端口得到的是全“1”信号, 如果有键按下的话, 则得到非全“1”信号。
(2)线反转法线反转法比行扫描速度快,原理是先将行线作为输出线, 列线作为输入线, 行线输出全“0”信号, 读入列线的值, 那么在闭合键所在的列线上的值必为0;然后从列线输出全“0”信号,再读取行线的输入值,闭合键所在的行线值必为 0。
这样,当一个键被按下时, 必定可读到一对唯一的行列值。
再由这一对行列值可以求出闭合键所在的位置。
/*在TX-1C实验板上实现如下描述:实验板上电时,数码管不显示,顺序按下矩阵键盘后,在数码管上依次显示0~F,6个数码管同时显示。
这里用“线反转”的方法写,可以代替郭天祥书上例【4.2.1】该书上使用逐行扫描的方式。
*/#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit duan=P2^6; //打开位选和段选sbit wei=P2^7;uchar code table[]={ //数码管显示数值表0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};void delay(uint x) //毫秒级延时函数{uint i,j;for(i=x;i>0;i--)for(j=110;j>0;j--);}void xianshi(uchar num) //段选显示函数{P0=table[num];duan=1;duan=0;}uchar keyscan(void) //矩阵键盘扫描函数{uchar h,l; //定义行、列值中间变量P3=0x0f; //列线输出全为0h=P3&0x0f; //读入行线if(h!=0x0f) //检测有无按键按下{ delay(10); //延时去抖if(h!=0x0f) //如果确实按下{h=P3&0x0f; //再次读入行线P3=0xf0; //输出当前列线值,行线反转l=P3&0xf0; //读入列线值return (h+l); //键盘最后组合编码值,也就是键值}}return 0xff; //其余情况返回该值}void main(){uchar key;P0=0; //关闭所有数码管段选,实验板上电数码管不显示duan=1;duan=0;P0=0xc0; //选中6位数码管wei=1;wei=0;while(1){key=keyscan(); //用key读取keyscan()的值switch(key){case 0xee: key=0; while(keyscan()!=0xff); xianshi(key); break;//while(keyscan()!=0xff)是松手检测语句,松手时检测case 0xde: key=1; while(keyscan()!=0xff); xianshi(key); break; //keyscan()函数会得到返回值0xff,!=oxff时表示按下去了case 0xbe: key=2; while(keyscan()!=0xff); xianshi(key); break;case 0x7e: key=3; while(keyscan()!=0xff); xianshi(key); break;case 0xed: key=4; while(keyscan()!=0xff); xianshi(key); break;case 0xdd: key=5; while(keyscan()!=0xff); xianshi(key); break;case 0xbd: key=6; while(keyscan()!=0xff); xianshi(key); break;case 0x7d: key=7; while(keyscan()!=0xff); xianshi(key); break;case 0xeb: key=8; while(keyscan()!=0xff); xianshi(key); break;case 0xdb: key=9; while(keyscan()!=0xff); xianshi(key); break;case 0xbb: key=10; while(keyscan()!=0xff); xianshi(key); break;case 0x7b: key=11; while(keyscan()!=0xff); xianshi(key); break;case 0xe7: key=12; while(keyscan()!=0xff); xianshi(key); break;case 0xd7: key=13; while(keyscan()!=0xff); xianshi(key); break;case 0xb7: key=14; while(keyscan()!=0xff); xianshi(key); break;case 0x77: key=15; while(keyscan()!=0xff); xianshi(key); break;default: break;}}}/*后记*//*刚开始写这个程序时我把主函数里面的switch—case语句这样写的,while(1){key=keyscan(); //用key读取keyscan()的值switch(key){case 0xee: key=0; break;case 0xde: key=1; break;case 0xbe: key=2; break;case 0x7e: key=3; break;case 0xed: key=4; break;case 0xdd: key=5; break;case 0xbd: key=6; break;case 0x7d: key=7; break;case 0xeb: key=8; break;case 0xdb: key=9; break;case 0xbb: key=10; break;case 0x7b: key=11; break;case 0xe7: key=12; break;case 0xd7: key=13; break;case 0xb7: key=14; break;case 0x77: key=15; break;default: break;}xianshi(key);}运行程序后发现当手按下按键时会有数码的显示,但是一旦放开按键数码管就什么都不显示了。
51单片机4×4矩阵按键扫描方法
key=0xf0;//低四位为0
if(key==0xf0)//若无变化,证明按键松开
return 0;//返回0
else//否则,按键未松开
return 1;//返回1
}
//*********主函数*********//
int main()
{
key=0xff;//按键初始化
led=0xff;//关闭LED灯
//送至led显示
/*
eg:如果是第三行第二列按键按下
则第3个、第6(2列+4)个LED灯亮
如下图所示(Proteus仿真电路图)
*/
}
}
led_arry[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//数组定义,便于显示
//******检测是否有按键按下*****//
uchar Check_Button()
{
key=0x0f;//高四位为0
if(key==0x0f)//若无变化,证明无按键按下
return 0;//返回0
else//否则
return 1;//返回1
}
//********行检测********//
uchar Line[]={0x0e,0x0d,0x0b,0x07}; //那个按键按下,检测出的状态则对应数组中的第几个数
void Check_Line()
{
uchar i;
key=0x0f;//高四位为0
/*****4×4按键扫描******/
/***编程要点
1.首先检测是否有按键按下
2.若有按键按下,即进行行检测,列检测
3.行检测:高4位设为0,低4位为1,进行检测0x0f
矩阵键盘检测
很多盘检4*46个也就较好时,低电键按标,独立键盘多按键时就检测。
这里4键盘实现IO 口控无论是独就是检测与好检测,而,先送一列电平,若有按下,送下,然后对其盘与单片机就会浪费里以4*4现了用8控制9个按独立按键还与该键对而矩阵键盘列低电平有低电平则下一列低其编码后矩阵键盘机相连时,很多的IO 矩阵键盘个IO 口控按键,5*5还是矩阵键对应的IO 盘就需要,其余为则证明该电平,通编程扫描盘检测及,每个按键O 口,鉴于盘为例,下控制16个实现10键盘,单口是否为要人为控制高电平,该列有键按过这种方描了。
及其运用键都要占用于对IO 口下面是其与个按键,当个IO 口控片机检测为低电平。
制端口电平立即轮流按下,若无方法,我们用一个IO 口的节省,与单片机连当然也可以控制25个测的依据都独立按键平变化来检流检测一下无低电平证们便可以确O 口,当用引入矩阵连接电路以以3*3实个按键。
都是一样的键一端固定检测了。
检下各行是否证明该列没确定按键的用到阵键图:实现。
的,定比检测否有没有的坐以下是软件流程图:NYNNY N扫描四行按键程序会很长,下面我编程实现扫描出第一行按键,其他各行可用相同方法进行扫描:开始寄存器初始化IO口初始化检测是否有键按下延时10ms 检测是否真有键按下检测按键是否释放执行相应代码/*******************************************************// ////‐‐‐函数功能:扫描矩阵键盘,返回相应按键代表的值 ////‐‐‐主函数中可以利用这一返回值选择执行相关代码 ////‐‐‐这样就实现了矩阵按键对器件的操作 //// //*******************************************************/ unsigned char Matrixkeyscan(){unsigned char temp,key;P3=0xfe; //送一列低电平其余为高确定该列temp=P3; //将P3口的值读回来temp=temp&0xf0; //if(temp!=0xf0) //看是否有IO口为低电平{Delayms(10); //延时去抖temp=P3; //重新读回P3口的值temp=temp&0xf0;if(temp!=0xf0) //看是否真有键按下{temp=P3; //temp的值发生变化需重新读回switch(temp) //判断是哪一行按键被按下,确定按键位置{case 0xee:key=1;break;case 0xde:key=2;break;case 0xbe:key=3;break;case 0x7e:key=4;break;}while(temp!=0xf0)//松手检测 {temp=P3;temp=temp&0xf0;}}}//P3=0xfd; //扫描下一行//。
单片机的矩阵键盘程序
#include<reg52.h>#define uint unsigned int#define uchar unsigned charuchar code table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82 ,0xF8,0x80,0x90,0xff};//数码管段选sbit shu1=P3^0;//数码管位选sbit shu2=P3^1;//数码管位选uchar num;void delay(uint z)//延时函数{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}uchar keyscan();//键盘扫描函数void main(){num=17;while(1){keyscan(); //键盘扫描if(num==17)//如果没有键按下{P2=table[10]; //数码管什么也不显示}else//有键按下{shu1=1;//打开数码管P2=table[(num-1)/10]; // 显示十位delay(7);//延时显示shu1=0;//关闭数码管shu2=1; //打开数码管P2=table[(num-1)%10]; // 显示个位delay(7);//延时显示shu2=0; //关闭数码管}}}uchar keyscan()//键盘扫描{P1=0xfe;while(P1!=0xfe) //第一行有键按下{delay(5);//延时消抖while(P1!=0xfe)//确实有键按下{switch(P1)//检测是哪个键按下{case 0xee:num=1;break;case 0xde:num=2;break;case 0xbe:num=3;break;case 0x7e:num=4;break;}while(P1!=0xfe);//松手检测}P1=0xfd;while(P1!=0xfd)//第二行有键按下{delay(5);//延时消抖while(P1!=0xfd)//确实有键按下{switch(P1)//检测是哪个键按下{case 0xed:num=5;break;case 0xdd:num=6;break;case 0xbd:num=7;break;case 0x7d:num=8;break;}while(P1!=0xfd) ;//松手检测}P1=0xfb;while(P1!=0xfb)//第三行有键按下{delay(5);//延时消抖while(P1!=0xfb)//确实有键按下{switch(P1)//检测是哪个键按下{case 0xeb:num=9;break;case 0xdb:num=10;break;case 0xbb:num=11;break;case 0x7b:num=12;break;}while(P1!=0xfb);//松手检测}}P1=0xf7;while(P1!=0xf7)//第四行有键按下{delay(5);//延时消抖while(P1!=0xf7)//确实有键按下{switch(P1)//检测是哪个键按下{case 0xe7:num=13;break;case 0xd7:num=14;break;case 0xb7:num=15;break;case 0x77:num=16;break;}while(P1!=0xf7);//松手检测}}return num;}。
51单片机矩阵键盘按键C语言程序
#include<reg52.h>#define uchar unsigned char#define uint unsigned intucharsmg_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x7 1} ;uchar smg_we[]={0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78} ;//有一篇74HC573必须为高电平//*************************8//12M频率下大约50US延时//**************************void delay_50us(uint t){uchar j;for(;t>0;t--)for(j=19;j>0;j--) ;}void delay_50ms(uint t){uchar j;for(;t>0;t--)for(j=6245;j>0;j--);}/*这个程序可以不用松手检测,因为我们程序首选判断键是否按下然后发现按下后我们延时5MS,然后再检测。
确实是按下啦。
我们再执行在第二个循环假如我们继续检测,那么消耗时间10MS这个短时间中我们的按键已经松手啦。
不会在执行后面的。
*/void main(){uchar key_l,key_h;uchar key;while(1){P3=0xf0; //首先给P3口赋值key_l=P3; //从p3口读一个数据到key_lkey_l=key_l&0xf0;if(key_l!=0xf0) //如果不等于的话,说明有按键按下去{delay_50us(100);//稍微延时一下if(key_l!=0xf0){key_l=P3&0xf0;// 11100000 再读一次P3的值然后和0xf0相与key_l=key_l|0x0f; // 11101111P3=key_l; //在把key_l的值送给P3口//此时P3口的值为11101111,而正在此时我们把键按下啦因此按下的键为11101110与11101111// 相与还是11101110;key_h=P3; //再读一次P3口,键还是按下,可以得到行的值。
(实验四)单片机矩阵键盘检测和液晶仿真实验
实验四单片机矩阵键盘检测和液晶仿真实验(4学时)一、实验任务利用51单片机实现4X4矩阵键盘和LCD1602液晶显示人机交互系统,编程实现:(1)按键扫描(1、2、……9、A、B、C、D、E、F)和LCD1602显示按键的键号,格式为:KEYNUM+按键号;(2)LCD1602的第一行显示加1功能,初始数字为980,显示位置自己确定,每次按下某一个按键,数字加1,范围为15---20;二、实验目的1、掌握仿真软件Proteus和单片机联调的方法;2、掌握矩阵键盘扫描检测的原理,并且编程实现键盘按键的检测;3、掌握LCD1602液晶显示的原理,并且编程实现LCD1602的显示功能;4、掌握利用单片机实现键盘检测和液晶显示的功能组合,并掌握独立编程控制的能力。
三、实验设备电脑、Proteus软件、Keil软件四、实验原理(一)矩阵键盘扫描检测原理按照按键结构原理可分为两类,一类是触点式开关按键,如机械式开关、导电橡胶式开关等;另一类是无触点开关按键,如电气式按键、磁感应按键等。
在单片机应用系统中,通过按键实现控制功能和数据输入是非常普遍的。
在所需按键数量不多时,系统常采用独立式按键。
独立式按键是指每个按键单独占有一根I/O口线,且其工作状态不会影响其他I/O口线的工作状态。
这种按键的电路配置灵活,软件结构简单。
不过在实际应用中,由于不同的系统对按键的要求不同,因此,对按键程序的设计要考虑全面,以便更好地完成按键所设定的功能。
在按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式,如图4.1所示。
在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。
这样一个端口(如P1口)就可以构成4×4=16个按键,比直接将端口线用于键盘多出了一倍,而且线数越多,区别越明显,比如再多加一条线就可以构成20键的键盘,而直接用端口线则只能多出1键(共9键)。
由此可见,在需要的键数比较多时,采用矩阵法来做键盘是合理的。
stm32矩阵按键扫描
原理图各位大侠,这是我写的矩阵按键扫描程序,大家可以参考参考思维是和一般的按键扫描一样的,欢迎大家吐槽。
说明:微处理器:STM32F103VET6,开发软件:IAR for ARM。
(本来想复制文本文档的,发现代码层次感全变了,而且看着不舒服,所以采用截图的方式)其中需要注意的是:1、HKey是利用位带定义然后宏定义的,如下:PEin(n)利位带宏定义,(如果不明白可以百度一下stm32 位带操作)。
2、此函数是利用定时器设置30ms进行一次中断,而按键扫描的时间则由KeyScanEn确定3、关于KeyHData=HKey 编译器一直报警告,(但是程序跑起来为发现问题,不知道有没有什么潜在的风险)为了安全起见,大家可以直接去读寄存器也行4、按键消抖是利用计数器的方式,(说白了就是需要检测到两次后再处理)。
5、关于Delay(1)函数,试过不用也行,这里是置输入脚后马上检测输出感觉应该给点反应时间。
6、此函数只取出了键值,判断的话需要在另外的函数,最好不在中断函数里来做判断。
思路:1、首先置行线全为高,然后检测HEKEY这四位是不是全为0(当然,先要把这四个脚设置为下拉输入),如果不全是0,侧说明有按键按下。
2、然后依次将PE12-PE15置高进行扫描,(将一位置高后,然后检测输入引脚,如果输入引脚不是0x00,则说明按键在此行。
如若不是则循环置下一个引脚为高再判断),因为是循环扫描,此时循环次数就说明了在第几行。
所以键值=列键值(读取的键值)+ 循环的次数(行键值)。
3、取出按键的键值依次是:0x11 0x21 0x41 0x810x12 0x22 0x42 0x820x13 0x23 0x43 0x830x14 0x24 0x44 0x844、从上面的键值表可以看出:键值的后四位说明了按键的行数,键值的前四位则说明了按键所在的列数。
单片机矩阵键盘实验
单片机独立按键和矩阵键盘操作[实验要求]独立按键操作: 试操作P3.4~P3.7控制的四个独立按键中的某一个, 每按一次, 数码管上显示数字作一次加1或减1变化, 显示数字在0~9之间.矩阵键盘操作: 依次按下4*4 矩阵键盘上从第1 到第20 个键,同时在六位数码管上依次显示0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F。
[实验原理](1) 按键识别去抖动原理:我们在手动按键的时候, 由于机械抖动或是其它一些非人为的因素很有可能造成误识别, 一般手动按下一次键然后接着释放, 按键两片金属膜接触的时间大约为50ms 左右,在按下瞬间到稳定的时间为5-10ms,在松开的瞬间到稳定的时间也为5-10ms,如果我们在首次检测到键被按下后延时10ms 左右再去检测,这时如果是干扰信号将不会被检测到,如果确实是有键被按下,则可确认,以上为按键识别去抖动的原理。
(2) 独立按键识别: 判断是否按下键盘,当单片机上电时所有I/O 口为高电平,参照实验电路图, S2 键一端接地另一端接P3.4,所以当键被按下时P3.4 口直接接地,此时检测P3.4 肯定为低电平。
(3) 矩阵键盘识别: 参照实验电路图, 矩阵键盘的四行分别与P3.0-P3.3 连接,四列分别与P3.4-P3.7 连接。
如识别第1列按键, 可给P3.4送低电平,其余为高电平, 把P3口数据读回, 判断其第4位是否全为1, 如果全为1,则该列无键按下, 可继续判断下1列, 如有某位为0, 则有键按下,并可根据其位置识别按键所在行,从而确定该按键位置和键值. 其它各列按键识别类同.[实验目的](1)掌握独立按键的识别方法.(2)掌握按键去抖动的基本原理。
(3)了解矩阵键盘检测的操作方法。
(4)进一步巩固掌握数码管的显示操作方法.[硬件电路]图1 独立键盘和矩阵键盘电路图图2 矩阵键盘接口图。
51单片机_矩阵按键检测
}
returnk;//返回扫描到的键值
}
void main()
{
int num=0, tmp;
while(1)
{
tmp = MatrixKeyscan();//扫描键盘判断是否有按键按下
if(tmp != -1) num = tmp;//当有按键按下时,将键值赋给num(无键按下时扫描键盘返回值-1)
《51系列单片机_矩阵按键检测》
此程序使用单片机89SC52
//1、此程序实现矩阵按键的检测功能,按下按键时,数码管显示按键的相应键值
#include<reg52.h>
voiddelay_ms(int n)//延时函数,延时n毫秒
{
inti, j;
for(i=0; i<n; i++)
for(j=0; j<110; j++);
}
voiddisplay(int num)//控制数码管按位输出显示数值num
{
charBitSet[8] =
{
0x7f, 0xbf, 0xdf, 0xef,
0xf7, 0xfb, 0xfd, 0xfe
};//用于设置(低电平位选)数码管的位选信号,从低到高对应8个数码管
charNumberCode[16] =
for(i=0; i<4; i++)
{
P1 = line[i];//将行扫描值逐个送至P1端口
tmp = P1;//再读取P1口的值
if(tmp != line[i])//若读取的数值不等于送入的行扫描值,表示有按键被按下
{
delay_ms(10);//延时,重新读取判断,确认有键按下
单片机与4x4键盘去抖松手检测程序
刚写的一个 4*4 键盘, 去抖 松手检测程序。 项目中要用 4*4 键盘,扫描的程 序有。但是去抖,和松手检测的程序没有,那么为了提 高效率,可靠性,以及更加合理化。到网上找了一些关 于”状态机“的资料,按照它的思路写了一 个,写了半天,写好一个,经过特发帖纪录一下。
{
return_key_num=temp_key_num; // 按键仍按下, 赋值给 返回按键值
key_state = key_state_2; // 状态转换到键释放态
}
else
{
key_state=key_state_0; //回到初始状态
} } else ///没有按键按下 {
key_state=key_state_0; //回到初始状态 } break;
temp_key_num=KeyMap();//读取 4*4 键盘返回的按键值 不要去抖
switch(key_state)//检测状态
{ case key_state_0: if(temp_key_num!=0) //如果按键返回不是 0 说明
有按键按下 {
key_num_flag1=temp_key_num; //记录下 第一次按 键按下的值
//对按键扫描的值 进行处理 去抖 松手检测 uint8_t key_scan(void) { static uint8_t key_state = 0; static uint8_t key_num_flag1=0;
uint8_t temp_key_num=0; uint8_t re key_state_2:
if(temp_key_num==0) //如果没有按键按下。 说明 按键松手了
按键-松手有效
.
先看独立键盘(和矩阵键盘的算法一样) ----------------------------------------------------------------------#include<reg52.h> #include<intrins.h>
temp=P2&0xF0;//读取 P2 线数据
if(temp!=0xF0)//低电平判断 {
num_check++;
if(num_check==10)//连续 10 次(10ms)低电平有效,则认为按键有效 {
key_flag=1;//使能按键有效标识 temp_code=temp;//保存按键值 } } else//松手时判断 { num_check=0;
break;
case 0xED: num_key=5;
break;
case 0xDD: num_key=6;
break;
case 0xBD: num_key=7;
break;
case 0x7D: num_key=8;
//P2^2 线
break;
case 0xEB: num_key=9;
break;
case 0xDB: num_key=10;
*************************************************************************/
if(key_flag==1)//按键有效 {
key_flag=0;
switch(temp_code)//读取按键号 {
case 0xE0: num_key=1; break;
实验4 矩阵键盘的使用
*函数功能:主函数
*输入:无
*输出:无
*******************************************************************************/
void main(void)
{
while(1)
{
KeyDown();
GPIO_DIG = ~DIG_CODE[KeyValue];
ORG 0000H
MOV SP,#6FH
MOV R0,#5;延时0.5秒
LOOP1:MOV R1,#200
LOOP2:MOV R2,#250
DJNZ R2,$
DJNZ R1,LOOP2
DJNZ R0,LOOP1
MOV DPTR,#4003H ;8255初始化
MOV A,#10000001B; A口、B口方式0输出,C口高4位输出,低4位输入
MOVX @DPTR,A
LOOP3:LCALL DISP;调用显示子程序DIS,设显示子程序入口为DISP
LCALL KEY;调用键盘扫描子程序,设键盘扫描子程序入口为KEY
CJNE A,#0FFH,LOOP4;如果有键按下转
SJMP LOOP3
LOOP4:MOV 20H,21H
MOV 21H,22H
入口:行列关键值码放在累加器A中,高4位是列驱动码(被扫描列的对应位为0,其余位均为1),低4位是行状态(按下键的对应位为0,其余位均为1)。
出口:键码放在A中带出。
占用:R1、A、PSW、DPTR。
程序清单如下:
;查键值子程序,起始地址为KEY20
KEY20:PUSH ACC;暂存关键值
MOV R1,#00H;查键值自变量清0
stm控制乘矩阵键盘程序带松手检测
/*本文件的函数,主要实现矩阵键盘的功能。
矩阵键盘使用PA0到PA7引脚,其中,PA0到PA3固定为推挽输出,PA4到PA7固定为
下拉输入。
即,无键按下时,对应PA4到PA7为0,有键按下时,PA4到PA7中,对应的引脚为高。
此程序有一点要注意:要用到的IO口,必须是PX0-PX7,,不能是其他连续的数字。
如果非要改。
如:已经没有连续的0-7的IO口,需要在几个地方修改,请注意!!
此程序带有松手检测。
*/
void InitKey(void) return -1;
else
{
delay_ms(5); return -1;
}
GPIO_Write(GPIOA,(GPIOA->ODR & 0xfff0 | 0x1)); switch(GPIOA->IDR & 0x00f0)
switch(GPIOA->IDR & 0x00f0)
switch(GPIOA->IDR & 0x00f0)
switch(GPIOA->IDR & 0x00f0) //对PA4到PA7的值进行判断,以输出不同的键值。
{
case 0x0010: KeyVal=12; break;
case 0x0020: KeyVal=8; break;
case 0x0040: KeyVal=4; break;
case 0x0080: KeyVal=0; break;
}
return KeyVal;
}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
s t m控制乘矩阵键盘程
序带松手检测
Document serial number【NL89WT-NY98YT-NC8CB-NNUUT-NUT108】
#include"stm32f10x.h"
#include"delay.h"
/*本文件的函数,主要实现矩阵键盘的功能。
矩阵键盘使用PA0到PA7引脚,其中,PA0到PA3固定为推挽输出,PA4到PA7固定为
下拉输入。
即,无键按下时,对应PA4到PA7为0,有键按下时,PA4到PA7中,对应的引脚为高。
此程序有一点要注意:要用到的IO口,必须是PX0-PX7,,不能是其他连续的数字。
如果非要改。
如:已经没有连续的0-7的IO口,需要在几个地方修改,请注意!!
此程序带有松手检测。
*/
voidInitKey(void)//初始化矩阵键盘要使用的GPIO口。
{
GPIO_InitTypeDefGPIOStru;
GPIOStru.GPIO_Mode=GPIO_Mode_Out_PP;//定义PA0到PA3为推挽输出。
GPIOStru.GPIO_Speed=GPIO_Speed_50MHz;
GPIOStru.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_Init(GPIOA,&GPIOStru);
GPIOStru.GPIO_Mode=GPIO_Mode_IPD;//定义PA4到PA7为下拉输入。
GPIOStru.GPIO_Speed=GPIO_Speed_50MHz;
GPIOStru.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
//因为上面定义引脚为输出时,已经打开整个GPIOA的时钟了,所以此处不再需要函数RCC_APB2PeriphClockCmd()来打开时钟了。
GPIO_Init(GPIOA,&GPIOStru);
}
intkey(void)//实现矩阵键盘。
返回值为,各按键的键值,此键值由用户自己定义。
{
intKeyVal=0; //keyVal为最后返回的键值。
u16WriteVal=0; //WriteVal为要写给PA口的数据。
GPIO_Write(GPIOA,(GPIOA->ODR&0xfff0|0xf));//先让PA0到PA3全部输出高。
if((GPIOA->IDR&0x00f0)==0x0000)//如果,PA4到PA7全为0,则,没有键按下。
此时,返回值为-1.
return-1;
else
{
delay_ms(5);//延时5ms去抖动。
if((GPIOA->IDR&0x00f0)==0x0000)//如果,延时5ms后,PA4到PA7又全为0,则,刚才引脚的电位变化是抖动产生的.
return-1;
}
GPIO_Write(GPIOA,(GPIOA->ODR&0xfff0|0x1)); //让PA3到PA0输出二进制的0001.
switch(GPIOA->IDR&0x00f0) //对PA4到PA7的值进行判断,以输出不同的键值。
{
case0x0010:KeyVal=15; break;
case0x0020:KeyVal=11; break;
case0x0040:KeyVal=7; break;
case0x0080:KeyVal=3; break;
}
GPIO_Write(GPIOA,(GPIOA->ODR&0xfff0|0x2)); //让PA3到PA0输出二进制的0010.
switch(GPIOA->IDR&0x00f0) //对PA4到PA7的值进行判断,以输出不同的键值。
{
case0x0010:KeyVal=14; break;
case0x0020:KeyVal=10; break;
case0x0040:KeyVal=6; break;
case0x0080:KeyVal=2; break;
}
GPIO_Write(GPIOA,(GPIOA->ODR&0xfff0|0x4)); //让PA3到PA0输出二进制的0100.
switch(GPIOA->IDR&0x00f0) //对PA4到PA7的值进行判断,以输出不同的键值。
{
case0x0010:KeyVal=13; break;
case0x0020:KeyVal=9; break;
case0x0040:KeyVal=5; break;
case0x0080:KeyVal=1; break;
}
GPIO_Write(GPIOA,(GPIOA->ODR&0xfff0|0x8)); //让PA3到PA0输出二进制的1000.
switch(GPIOA->IDR&0x00f0) //对PA4到PA7的值进行判断,以输出不同的键值。
{
case0x0010:KeyVal=12; break;
case0x0020:KeyVal=8; break;
case0x0040:KeyVal=4; break;
case0x0080:KeyVal=0; break;
}
returnKeyVal;
}。