矩阵键盘扫描的C语言实例.docx

上传人:b****8 文档编号:9223865 上传时间:2023-05-17 格式:DOCX 页数:18 大小:33.25KB
下载 相关 举报
矩阵键盘扫描的C语言实例.docx_第1页
第1页 / 共18页
矩阵键盘扫描的C语言实例.docx_第2页
第2页 / 共18页
矩阵键盘扫描的C语言实例.docx_第3页
第3页 / 共18页
矩阵键盘扫描的C语言实例.docx_第4页
第4页 / 共18页
矩阵键盘扫描的C语言实例.docx_第5页
第5页 / 共18页
矩阵键盘扫描的C语言实例.docx_第6页
第6页 / 共18页
矩阵键盘扫描的C语言实例.docx_第7页
第7页 / 共18页
矩阵键盘扫描的C语言实例.docx_第8页
第8页 / 共18页
矩阵键盘扫描的C语言实例.docx_第9页
第9页 / 共18页
矩阵键盘扫描的C语言实例.docx_第10页
第10页 / 共18页
矩阵键盘扫描的C语言实例.docx_第11页
第11页 / 共18页
矩阵键盘扫描的C语言实例.docx_第12页
第12页 / 共18页
矩阵键盘扫描的C语言实例.docx_第13页
第13页 / 共18页
矩阵键盘扫描的C语言实例.docx_第14页
第14页 / 共18页
矩阵键盘扫描的C语言实例.docx_第15页
第15页 / 共18页
矩阵键盘扫描的C语言实例.docx_第16页
第16页 / 共18页
矩阵键盘扫描的C语言实例.docx_第17页
第17页 / 共18页
矩阵键盘扫描的C语言实例.docx_第18页
第18页 / 共18页
亲,该文档总共18页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

矩阵键盘扫描的C语言实例.docx

《矩阵键盘扫描的C语言实例.docx》由会员分享,可在线阅读,更多相关《矩阵键盘扫描的C语言实例.docx(18页珍藏版)》请在冰点文库上搜索。

矩阵键盘扫描的C语言实例.docx

矩阵键盘扫描的C语言实例

矩阵键盘扫描的C语言实例

1、按键扫描(线反转)

//--------------------------------------------------------------------------------------------------

//函数名称:

program_SCANkey

//函数功能:

程序扫描键盘,

//有键按下完成按键处理,无键按下直接返回

//--------------------------------------------------------------------------------------------------

voidprogram_SCANkey()

{

unsignedcharkey_code;

if(judge_hitkey())//判断是否有键按下

{

delay(1000);//延时20ms左右,消除抖动干扰

if(judge_hitkey())//判断是否有效按键

{

key_code=scan_key();//获取键值

while(judge_hitkey());//等待按键释放

{

}

key_manage(key_code);//键盘扫描、键盘散转、按键处理

}

}

}

//--------------------------------------------------------------------------------------------------

//函数名称:

judge_hitkey

//函数功能:

//判断是否有键按下,有返回1,没有返回0

//列判断,还可以用行判断。

//--------------------------------------------------------------------------------------------------

bitjudge_hitkey()//判断是否有键按下,有返回1,没有返回0

{

unsignedcharscancode,keycode;

scancode=0x0F;//开始设定P1.0~P1.3输出全1(初值)即表明无键闭合

KEY=scancode;

keycode=KEY;//读取P1.0~P1.3的真实状态,从而确定有没有键被按下

if(keycode==0x0F)

return(0);//全1则无键闭合

else

return

(1);//否则有键闭合

}

//--------------------------------------------------------------------------------------------------

//函数名称:

scan_key

//函数功能:

//扫描键盘,返回键值(高四位代表行,低四位代表列)

//说明:

scancode扫描码,keycode键值,keycode_line行,keycode_row列

//过程:

先扫描行,确定那行的按键被按下。

再扫描列,确定那列的按键被按下,从而确定那个按键被按下。

//--------------------------------------------------------------------------------------------------

unsignedcharscan_key()//扫描键盘,返回键值(高四位代表行,低四位代表列)

{

unsignedcharscancode,keycode,keycode_line,keycode_row;

scancode=0xF0;//列置低,行置高

KEY=scancode;//输入扫描码,扫描行

keycode_line=KEY;//KEY的值是与键盘相连的P的状态值。

若没有按键按下KEY的值为0xF0,若有按键按下则KEY的值就不是0xF0

scancode=0x0F;//列置高,行置低

KEY=scancode;//输入扫描码,扫描列

keycode_row=KEY;//KEY的值是与键盘相连的P的状态值。

若没有按键按下KEY的值为0x0F,若有按键按下则KEY的值就不是0x0F

keycode=((keycode_line&0xF0)|(keycode_row&0x0F));

return(keycode);

}

2、按键扫描(逐行扫描)

//--------------------------------------------------------------------------------------------------

//函数名称:

kbscan键盘扫描子程序

//函数功能:

判断是否有键按下,有返回键值,没有返回0

//p1的高四位为列,低四位为行P1.7P1.6P1.5P1.4P1.3P1.2P1.1P1.0

//列4列3列2列1行4行3行2行1

//过程:

先根据列判断是否有键按下,没有返回0,有,则逐行扫描以确定按键所在的行,再确定按键所在列

//从而最终确定该按键。

//--------------------------------------------------------------------------------------------------

ucharkbscan(void)

{

ucharsccode,recode;

P1=0xf0;//置所有行为低电平,行扫描,列线输入(此时)

if((P1&0xf0)!

=0xf0)//判断是否有有键按下(读取列的真实状态,若第4列有键按下则P1的值会变成01110000),有往下执行

{

delays();//延时去抖动(10ms)

if((P1&0xf0)!

=0xf0)//再次判断列中是否是干扰信号,不是则向下执行

{

sccode=0xFE;//逐行扫描初值(即先扫描第1行)

while((sccode&0x10)!

=0)//行扫描完成时(即4行已经全部扫描完成)sccode为11101111停止while程序

{

P1=sccode;//输出行扫描码

if((P1&0xf0)!

=0xf0)//本行有键按下(即P1(真实的状态)的高四位不全为1)

{

recode=(P1&0xf0)|0x0f;//列

return(sccode&recode);//返回行和列

}

else//所扫描的行没有键按下,则扫描下一行,直到4行都扫描,此时sccode值为11101111退出while程序

{

sccode=(sccode<<1)|0x01;//行扫描码左移一位

}

}

}

}

else

{

return0;//无键按下,返回0

}

}

--------------------------------------------------------------------------------------------------------------------------

/*Main.c*/

#include"global.c"

voidSystemInit();

voidTimer1Init();

voidKickDog();

voiddelay();

unsignedintjudge_key();

unsignedintscan_key();

unsignedcharnumkey=0;

unsignedcharDATX,DATY;

main()

{

SystemInit();//系统初始化

MCRA=MCRA&0x80FF;//IOPB0-6设为IO口模式

PBDATDIR=0xBFC2;//所有LED=0,并置IOPB6为输入口

Timer1Init();//定时器初始化

asm("CLRCINTM");

while

(1)

{

//KeyLed();

if(judge_key()==1)

numkey++;

}

}

voidSystemInit()

{

asm("SETCINTM");/*关闭总中断*/

asm("CLRCSXM");/*禁止符号位扩展*/

asm("CLRCCNF");/*B0块映射为on-chipDARAM*/

asm("CLRCOVM");/*累加器结果正常溢出*/

SCSR1=0x83FE;/*系统时钟CLKOUT=20*2=40M*/

WDCR=0x006F;/*禁止看门狗,看门狗时钟64分频*/

KickDog();/*初始化看门狗*/

IFR=0xFFFF;/*清除中断标志*/

IMR=0x0002;/*打开中断2*/

}

voidTimer1Init()

{

EVAIMRA=0x0080;//定时器1周期中断使能

EVAIFRA=0xFFFF;//清除中断标志

GPTCONA=0x0000;

T1PR=2500;//定时器1初值,定时0.4us*2500=1ms

T1CNT=0;

T1CON=0x144E;//增模式,TPS系数40M/16=2.5M,T1使能

}

unsignedintjudge_key()

{

MCRC=MCRC&0x81FF;//

PFDATDIR=PFDATDIR|0x0070;

PFDATDIR=PFDATDIR&0x8FFF;//设置456输入高

PFDATDIR=PFDATDIR&0xFFF1;

PFDATDIR=PFDATDIR|0x0E00;//设置123输出低

if((PFDATDIR&0x0070)==0x0070)

return(0);

else

return

(1);

}

unsignedintscan_key()

{

if(judge_key()==1)

delay();

if(judge_key()==1)

{

MCRC=MCRC&0x81FF;//

PFDATDIR=PFDATDIR|0x0070;

PFDATDIR=PFDATDIR&0x8FFF;//设置456输入高

PFDATDIR=PFDATDIR&0xFFF1;

PFDATDIR=PFDATDIR|0x0E00;//设置123输出低

delay();

numkey=((PFDATDIR&0x0070)|(PFDATDIR&0x000E));

//delay();

//MCRC=MCRC&0x81FF;//

PFDATDIR=PFDATDIR&0xFF8F;//设置456输出低

PFDATDIR=PFDATDIR|0xE000;

PFDATDIR=PFDATDIR|0x000E;//设置123输入高

PFDATDIR=PFDATDIR&0xF1FF;

delay();

//numkey=((PFDATDIR&0x0070)|(PFDATDIR&0x000E));

numkey=numkey|(PFDATDIR&0x000E);

return(numkey);

}

}

voidc_int2()/*定时器1中断服务程序*/

{

if(PIVR!

=0x27)

{asm("CLRCINTM");

return;

}

scan_key();

EVAIFRA=EVAIFRA&0x80;

asm("CLRCINTM");

}

voiddelay()

{

inti;

for(i=0;i<10000;i++);

}

voidKickDog()/*踢除看门狗*/

{

WDKEY=0x5555;

WDKEY=0xAAAA;

}

矩阵键盘扫描程序集锦

2009-08-1811:

24

初学者写的最简单矩阵键盘扫描程序 

 这是站长初学者写的最简单、最详细、效率最高的矩阵键盘扫描程序,只用了四条常用命令(MOV/送数、JB/高电平转移、JMP/直接转移、RET/子程序返回),保证初学者一看就懂!

本程序已经在本站电子实验板上验证通过,占用CPU时间少,效率高,被选作单片机的测试程序!

  矩阵按键扫描程序是一种节省IO口的方法,按键数目越多节省IO口就越可观,本程序的思路跟书上一样:

先判断某一列(行)是否有按键按下,再判断该行(列)是那一只键按下。

但是,在程序的写法上,站长采用了最简单的方法,使得程序效率最高。

  本程序中,如果检测到某键按下了,就不再检测其它的按键,这完全能满足绝大多数需要,又能节省大量的CPU时间。

另外,本人认为键盘用延时程序来消除抖动,完全是浪费时间。

试想,如果不用中断执行(用中断执行需要更多的硬件资源)的方法来扫描键盘,每秒钟扫描20-100次,每次都要延时10-20MS的话,我们的单片机还有多少时间做正事呢?

  其实,延时的这段时间,CPU可以做其它的事呀。

所以,本键盘扫描程序的前面后面都可以加入少少代码,既可以达到完美的消抖动效果,又可以扩展其它的功能(例如按键封锁、按键长按等按键功能复用!

  本键盘扫描子程序名叫key,每次要扫描时用callkey调用即可。

以下子程序内容:

key:

movp0,#00001111b;上四位和下四位分别为行和列,所以送出高低电压检查有没有按键按下

jmpk10;跳到K10处开始扫描,这里可以改成其它条件转移指令来决定本次扫描是否要继续,例如减1为0转移或者位为1或0才转移,这主要用来增加功能,确认上一按键功能是否完成?

是否相当于经过了延时?

是否要封锁键盘?

goend:

jmpkend;如果上面判断本次不执行键盘扫描程序,则立即转到程序尾部,不要浪费CPU的时间

k10:

jbp0.0,k20;扫描正式开始,先检查列1四个键是否有键按下,如果没有,则跳到K20检查列2

k11:

movp0,#11101111b;列1有键按下时,P0.0变低,到底是那一个键按下?

现在分别输出各行低电平

jbp0.0,k12;该行的键不按下时,p0.0为高电平,跳到到K12,检查其它的行

movr1,#1;如果正好是这行的键按下,将寄存器R0写下1,表示1号键按下了

k12:

movp0,#11011111b

jbp0.0,k13

movr1,#2;如果正好是这行的键按下,将寄存器R0写下2,表示2号键按下了

k13:

movp0,#10111111b

jbp0.0,k14

movr1,#3;如果正好是这行的键按下,将寄存器R0写下3,表示3号键按下了

k14:

movp0,#01111111b

jbp0.0,kend;如果现在四个键都没有按下,可能按键松开或干扰,退出扫描(以后相同)

movr1,#4如果正好是这行的键按下,将寄存器R0写下4,表示4号键按下了

jmpkend;已经找到按下的键,跳到结尾吧

k20:

jbp0.1,k30;列2检查为高电平再检查列3、4

k21:

movp0,#11101111b;列2有健按下时,P0.0会变低,到底是那一行的键按下呢?

分别输出行的低电平

jbp0.1,k22;该行的键不按下时p0.0为高电平,跳到到K22,检查另外三行

movr1,#5;如果正好是这行的键按下,将寄存器R0写下5,表示5号键按下了(以后相同,不再重复了)

k22:

movp0,#11011111b

jbp0.1,k23

movr1,#6

k23:

movp0,#10111111b

jbp0.1,k24

movr1,#7

k24:

movp0,#01111111b

jbp0.1,kend

movr1,#8

jmpkend;已经找到按下的键,跳到结尾吧(以后相同,不要重复了)

k30:

jbp0.2,k40

k31:

movp0,#11101111b

jbp0.2,k32

movr1,#9

k32:

movp0,#11011111b

jbp0.2,k33

movr1,#10

k33:

movp0,#10111111b

jbp0.2,k34

movr1,#11

k34:

movp0,#01111111b

jbp0.2,kend

movr1,#12

jmpkend

k40:

jbp0.3,kend

k41:

movp0,#11101111b

jbp0.3,k42

movr1,#13

k42:

movp0,#11011111b

jbp0.3,k43

movr1,#14

k43:

movp0,#10111111b

jbp0.3,k44

movr1,#15

k44:

movp0,#01111111b

jbp0.3,kend

movr1,#16

kend:

ret

  键盘扫描结束了,寄存器R1的值就直接表示了是那个键按下的,根据不同的键值去执行不同的程序,从而实现了十六个矩阵键盘扫描,同样原理,最多可以识别255个按键的矩阵扫描。

  我们可以每次键盘扫描开始时检查R0的值是否为0,只有在为0才扫描键盘,不为0就证明刚刚扫描过键值,相应的按键工作还没有完成。

但是必须记得,每个按键命令执行完成后,要给R0写上0,表示可以扫描键盘。

  本键盘扫描程序的优点在于:

不用专门的按键延时程序,提高了CPU效率,也不用中断来扫描键盘,节省了硬件资源。

另外,本键盘扫描程序,每次扫描占用CPU时最短,不论有键按下或者无键按下都可以在很短的时间完成一次扫描。

  还有,本程序只使用几条最常用的汇编命令,MOV/JB/JMP/RET,而这几条命令是最常用、最易懂、最好学的命令!

有的键盘扫描程序还用与呀、或呀、移位呀、查表呀,我都还没有看懂。

  当然,以上只是站长初学单片机的一点个人见解,欢迎广大单片机爱好者指正,希望大家将自己最认可的键盘扫描程序公布出来,让大家一起分享!

最后,五一电子祝愿大家学习进步!

工作顺利!

  说明:

本站数显FM无线发射板中虽然不是用矩阵扫描,但是按键消抖动原理和上面相同,按键功能复用原理也和上面相同,用起来感觉很好!

在键盘的10MS延时过程中,CPU刚好可以去做几件事并在10MS左右做完。

所以,产品中凡是要用到按键扫描的,都可以让CPU去做别的事情,键盘延时消抖动唯一的好处就是,程序写起来会方便一点。

来自---------

4*4矩阵键盘扫描汇编程序(基于51单片机)

                                  

;//======================================================================

;//

;//    程序名称:

4-4keyscan.asm

;//    程序用途:

4*4矩阵键盘扫描检测

;//    功能描述:

扫描键盘,确定按键值。

程序不支持双键同时按下,

;//              如果发生双键同时按下时,程序将只识别其中先扫描的按键

;//    程序入口:

void

;//    程序出口:

KEYNAME,包含按键信息、按键有效信息、当前按键状态

;//    编写人:

黄伟,2007-12-11

;//    最后修改:

黄伟,2007-12-12

;//

;//======================================================================

PROC   KEYCHK

KEYNAME        DATA   40H            ;按键名称存储单元

                                       ;(b7-b5纪录按键状态,b4位为有效位,

                                       ;b3-b0纪录按键)

KEYRTIME       DATA   43H            ;重复按键时间间隔

SIGNAL         DATA   50H            ;提示信号时间存储单元

KEY            EQU    P3             ;键盘接口(必须完整I/O口)

KEYPL          EQU    P0.6           ;指示灯接口

RTIME          EQU    30             ;重复按键输入等待时间

KEYCHK:

;//=============按键检测程序=============================================

       MOV    KEY,#0FH               ;送扫描信号

       MOV    A,KEY                  ;读按键状态

       CJNE   A,#0FH,NEXT1           ;ACC<=0FH

;      CLR    C                      ;Acc等于0FH,则CY为0,无须置0

NEXT1:

;      SETB   C                      ;Acc不等于0FH,则ACC必小于0FH,

                                       ;CY为1,无须置1

       MOV    A,KEYNAME

       ANL    KEYNAME,#1FH           ;按键名称屏蔽高三位

       RRC    A                      ;ACC带CY右移一位,纪录当前按键状态

       ANL    A,#0E0H                ;屏蔽低五位

       ORL    KEYNAME,A              ;保留按键状态

;//=============判别按键状态,决定是否执行按键扫描========================

       CJNE   A,#0C0H,NEXT2          ;110按键稳定闭合,调用按键检测子程序

       SJMP   KEYSCAN

NEXT2:

       CJNE   A,#0E0H,NEXT3          ;111按键长闭合,重复输入允许判断

       SJMP   WAIT   

NEXT3:

       CJNE   A,#0A0H,EXIT  

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 高等教育 > 艺术

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2