51单片机使用状态机的键盘程序

合集下载

基于51单片机的PS2键盘的单片机编程

基于51单片机的PS2键盘的单片机编程

PS2键盘的单片机编程在单片机系统中,经常使用的键盘都是专用键盘.此类键盘为单独设计制作的,成本高、使用硬件连接线多,且可靠性不高,这一状况在那些要求键盘按键较多的应用系统中更为突出.与此相比,在PC系统中广泛使用PS/2键盘具有价格低、通用可靠,且使用连接线少(仅使用2根信号线)的特点,并可满足多种系统的要求.因此在单片机系统中应用PS/2键盘是一种很好的选择.文中在介绍PS/2协议和PS/2键盘工作原理与特点的基础上,给出了一个在单片机上实现对PS/2键盘支持的硬件连接与驱动程序设计实现.该设计实现了在单片机系统中对PS/2标准104键盘按键输入的支持.使用Keil C51开发的驱动程序接口和库函数可以方便地移植到其他单片机或嵌入式系统中.所有程序在Keil uVision2上编译通过,在单片机AT89C51上测试通过.1 PS/2协议目前,PC机广泛采用的PS/2接口为mini-DIN 6pin的连接器,如图1所示.PS/2设备有主从之分,主设备采用Female插座,从设备采用Male插头.现在广泛使用的PS/2键盘鼠标均在从设备方式下工作.PS/2接口的时钟与数据线都是集电极开路结构,必须外接上拉电阻(一般上拉电阻设置在主设备中).主从设备之间数据通信采用双向同步串行方式传输,时钟信号由从设备产生.1.1 从设备到主设备的通信当从设备向主设备发送数据时,首先检查时钟线,以确认时钟线是否为高电平.如果是高电平,从设备就可以开始传输数据;反之,从设备要等待获得总线的控制权,才能开始传输数据.传输的每一帧由11位组成,发送时序及每一位的含义如图2所示.每一帧数据中开始位总是为0,数据校验采用奇校验方式,停止位始终为1.从设备到主设备通信时,从设备总是在时钟线为高时改变数据线状态,主设备在时钟下降沿读人数据线状态.1.2 主设备到从设备的通信主设备与从设备进行通信时,主设备首先将时钟线和数据线设置为“请求发送”状态,具体方式为:首先下拉时钟线至少100us抑制通信,然后下拉数据线“请求发送”,最后释放时钟线.在此过程中,从设备在不超过10us的间隔内必须检查这个状态,当设备检测到这个状态时,它将开始产生时钟信号.此时数据传输的每一帧由12位构成,其时序和每一位含义如图3所示.与从设备到主设备通信相比,其每帧数据多了一个ACK位.这是从设备应答接收到字节的应答位,由从设备通过拉低数据线产生,应答位ACK总是为0.主设备到从设备通信过程中,主设备总是在时钟线为低电平时改变数据线的状态,从设备在时钟上升沿读人数据线状态.2 PS/2键盘的编码与命令集2.1 PS/2键盘的编码目前,PC机使用的PS/2键盘都默认采用第2套扫描码集.扫描码有两种不同的类型:“通码(make code)”和“断码(break code)”.当一个键被按下或持续按住时,键盘会将该键的通码发送给主机;而当一个键被释放时,键盘会将该键的断码发送给主机.根据键盘按键扫描码的不同,可将按键分为3类:第1类按键通码为一个字节,断码为0xF0+通码形式.如A键,其通码为0x1C;断码为0xF0 0x1C.第2类按键通码为两字节0xE0+0xXX形式,断码为0xE0+0xF0+0xXX形式.如Right Ctrl键,其通码为0xE0 0x14;断码为0xE0 0xF0 0x14.第3类特殊按键有两个,Print Screen键,其通码为0xE0 0x12 0xE0 0x7C;断码为0xE0 0xF0 0x7C 0xE0 0xF0 0x12.Pause键,其通码为0xE1 0x14 0x77 0xE1 0xF0 0xl4 0xF0 0x77;断码为空.组合按键扫描码的发送是按照按键发生的次序,如按下面顺序按左Shift十A 键:① 按下左Shift键;② 按下A键;③ 释放A键;④ 释放左Shift键,那么计算机上接收到的一串数据为0x12 0x1C 0xF0 0x1C 0xF0 0x12.在文中的驱动程序设计中,就是根据按键的分类对其分别进行处理.2.2 PS/2键盘的命令集主机可通过向PS/2键盘发送命令对键盘进行设置或者获得键盘的状态等操作.每发送一个字节,主机都会从键盘获得一个应答0xFA(“重发resend”和“回应echo”命令例外).驱动程序在键盘初始化过程中所用的指令:0xED,主机在该命令后跟随发送一个参数字节,用于指示键盘上Num Lock,Caps Lock,Scroll Lock Led的状态;0xF3,主机在这条命令后跟随发送一个字节参数定义键盘机打的速率和延时;0xF4,用于当主机发送0xF5禁止键盘后,重新使能键盘.3 PS/2键盘与单片机的连接电路PS/2键盘与AT89C51单片机的连接方式如图4所示.P1.0接PS/2数据线;P3.2(INT0)接PS/2时钟线.因为单片机的P1,P3口内部是带上拉电阻的,所以PS/2的时钟线和数据线可以直接与单片机的P1,P3相连接.4 驱动程序设计驱动程序的开发使用Keil C51语言以及KeiluVision2编程环境.PS/2 104键盘驱动程序主要任务是实现单片机与键盘间PS/2通信,同时将接收到的按键扫描码转换为该按键的键值KeyVal,提供给系统上层软件使用.4.1 单片机与键盘间PS/2通信的程序设计在PS/2通信过程中,主设备(文中是单片机)是在时钟信号为低时发送和接收数据信号.因为单片机向键盘发送的是指令,需要键盘回应,所以这部分程序采用查询方式;而单片机接收键盘数据时,数据线上的信号在时钟为低时已经稳定,所以这部分程序采用中断方式,且不需要在程序中加入延时程序.单片机向PS/2键盘发送数据程序代码为:void ps2_sentchar(unsigned char sentchar){//ps2主设备向从设备发送数据unsigned char sentbit_cnt= 0x00;unsigned char sentchar_chk = 0x00;EX0=0; //关外部中断0//发起一个传送,发起始位PS2_SGN_CLOCK = 0; //将时钟线拉低并保持100 usdelay100us();PS2_SGN_DATA= 0; //起始位PS2_SGN_CLOCK = 1;//发送DATA0-7for(sentbit_cnt=0;sentbit_cnt< 8;sentbit_cnt++){while(PS2_SGN_CLOCK) _nop_(); //等待时钟线变为低PS2_SGN_DATA = sentchar& 0x01;//发送数据if(PS2_SGN_DATA) sentchar_chk++; //计算校验while(!PS2_SGN_CL0CK) _nop_(); //等待时钟线变高sentchar>>=1; //待发送数据右移一位}//发送校验位while(PS2_SGN_CLOCK) _nop_(); //等待时钟线变低switch(sentchar_chk){case 0:case 2:case 4:case 6:PS2_SGN_DATA =1;break;//奇校验case 1:case 3:case 5:case 7:PS2_SGN_DATA = 0;break;//奇校验default;break;)while(!PS2_SGN_CLOCK) _nop_(); //等待时钟线变高while(PS2_SGN_CLOCK) _nop_(); //等待时钟线变低PS2_SGN_DATA =1;//发送停止位,停止位总为1while(!PS2_SGN_CLOCK) _nop_(); //等待时钟线变高while(PS2_SGN_CLOCK) _nop_(); //等待时钟线变低//接收ACK//if(PS2_SGN_DATA) error();//ACK信号由键盘发出,总为低电平while(!PS2_SGN_CLOCK) _nop_(); //等待时钟线变高EX0= 1; //开外部中断0}单片机由PS/2键盘接收数据程序:外部中断0设置为下降沿触发void int0() interrupt 0 using 0 {//EX0=0; //关外部中断0switch(ps2_revchar_cnt){case 1:……case 8:mcu_revchar<<=1;if(PS2_SGN_DATA) mcu_revchar |= 0x01;ps2_revchar_cnt++;break;case 0:ps2_revchar_cnt++;break; //开始位,case 9:ps2_revchar_cnt++;break; //校验位,可添加校验程序case 10: _nop_();//停止位ps2_revchar_cnt= 0;revchar_flag=1;//置接收到数据标识位break;default:break;}EX0=1;//开外部中断0}4.2 键盘扫描码转换程序设计由于键盘扫描码无规律可循,因此由键盘扫描码获得相应按键的键值(字符键为其ASCII值,控制键如F1,Ctrl等为自定义值),只能通过查表的方式获得.由于按键的3种类型及部分按键对应着两个键值(如A键的键值根据Caps和Shift键状态有0x41(A)和0x61(a)两种),因此综合考虑查表转换速度和资源消耗,设计中使用4个键盘表:键盘扫描码转换基本集和切换集(kb_plain_map[NR_KEYS]与kb_shift_map[NR_KEYS]);包含E0前缀的键盘扫描码转换基本集和切换集(kbeO_plain_map[NR_KEYS]与kbe0_shiftmap[NR_KEYS]).PS/2 104键盘按键扫描码最大值为0x83,所以设置NR_KEYS为132.所有4个键盘表的定义均为如下形式:KB_MAP[MAKE CODE]=KEYVAL,如果扫描码对应的按键为空(如KB_MAP[0x00]),则定义相应键值为NULL_KEY(0x00).以下是键盘扫描码基本集的部分代码实例: kb_plain_map[NR_KEYS]={……NULL_KEY;0x2C;0x6B;0x69;0x6F;0x30;0x39;NULL_KEY; //扫描码0x40~0x47//对应按键空,逗号,K,I,O,0,9,空//对应键值0x00,',','k','i','o','O','9',0x00…… };如此设计键盘转换表的另一个好处在于,以后如需扩展支持有ACPI、Windows多媒体按键键盘时,只需要将键表中相应处修改即可,如ACPIPower按键通码为0xE0 0x37,修改kbe0_plain_map[0x37]=KB_ACPI_PWR即可. 特殊按键Pause使用单独程序处理,如果接收到0xE1就转入这段程序.而Print Screen键则将其看作是两个通码分别为0xE0 0x12和0xE0 0x7C的“虚键”的组合键处理.在驱动程序中设定如下全局变量:led_status记录Scroll Lock Led,Num Lock Led和Caps Lock Led的状态(关为0,开为1);agcs_status记录左右Shift Ctrl Gui Alt状态,相应键按下则对应位为1,释放为0.E0_FLAG接到0xE0置1;E1_FLAG接收到0xE1置1;F0_FLAG接收到0xF0置1.按键键值通过KeyVal提供上层程序使用.PS/2键盘扫描码键值转换程序ps2_codetrans()流程框架如图5所示.第1类按键的扫描码键值转换程序代码。

独立式键盘程序

独立式键盘程序

51单片机:键盘控制程序2009-11-14 16:12键盘控制1.功能说明:用八位指拨开关(DIP)作单片机的输入,控制输出端口连接的八只LED发光二极管。

如若DIP1开关为 ON(向右拨动)则LED1亮,其它开关作用同。

程序:LOOP: MOV A, P3 ; 从P3读入DIP开关值MOV P1, A ; 从P1输出03: JMP LOOP ; 无穷循环04: END ;程序结束2.功能说明:用DIP开关中的低4位作二进制的输入,控制输出端数码管显示器的输出。

程序:01: MOV DPTR,#TABLE ; 存表02: MOV P0, #0FFH ; LED全灭03: LOOP: MOV A, P3 ; 从P3口读入DIP开关值04: ANL A, #0FH ; 高4位清0,取低四位05: ACALL CHANG ; 转成七段显示码06: MOV P0, A ; 从P0输出07: JMP LOOP ; 转移LOOP处,循环08: CHANG: MOVC A,@A+DPTR ; 取码09: RET ; 返回转换显示码子程序10: TABLE: DB 0C0H, 0F9H, 0A4H, 0B0H ;11: DB 99H, 92H, 82H, 0F8H ;12: DB 80H, 90H, 88H, 83H ;13: DB 0C6H, 0A1H, 86H, 8EH ; 显示码表14: END ;程序结束3.功能说明:用两个按键开关K1和K2作输入,K1为电源指示灯开关,K2为工作指示灯开关。

分别控制电源指示灯(P1.0接的LED)和工作指示灯(P1.7接的LED)的接通和关闭。

接通电源时,电源指示灯是在亮的状态。

当按K2时,工作指示灯亮,电源指示灯灭。

按K1时,电源指示灯亮,工作指示灯灭。

程序:01: START: MOV P1, #11111110B ; P1.0所接LED亮02: JB P2.5 , $ ; 判断P2.5(K2键)是否为103: ON: MOV P1, #01111111B ; P1.7所接LED亮04: JNB P2.4, START ; 判断P2.4(K1键)是是否为005: JMP ON ; 未按K1键,则跳至ON06: END ;程序结束4.功能说明:由四个按键开关组成独立式键盘,控制灯左移、右移和闪烁。

51单片机44矩阵键盘源程序

51单片机44矩阵键盘源程序

51单片机4*4矩阵键盘源程序;P3口接键盘;P0口接数码管段码端控位,再将任一数码管的位码接地AD EQU 30H org 0000hLJMP MAINORG 0030HMAIN: mov p3,#0Fh ;p0-3输出1,作为输入位mov a ,p3ANL A,#0FHCJNE A,#0FH,DELAYSJMP MAINDELAY: ACALL DELAY1 ; 延时去键抖mov a ,p3ANL A,#0FHCJNE A,#0FH,HA VESJMP MAINHA VE:MOV A,#0EFH ;行扫描码NEXT:MOV B,AMOV P3,AMOV A,p3ANL A,#0FH ;检测列CJNE A,#0FH,YESMOV A,BRL ACJNE A,#0FEH,NEXTYES: orl a,#0f0h ;高四位置1CPL Amov r2,#00hMOV R2,A ;存列码MOV A,B ;取行码,CPL AORL A,R2 ;列码+行码=键植MOV P2,A ; 用P2口接发光二极管查看结果MOV AD,#00H ACALL DISPKEYVJMP MAINDISPKEYV:KEY0:CJNE A,#11H,KEY1AJMP WORD0KEY1:CJNE A,#12H,KEY2AJMP WORD1KEY2:CJNE A,#14H,KEY3AJMP WORD2KEY3:CJNE A,#18H,KEY4AJMP WORD3KEY4:CJNE A,#21H,KEY5AJMP WORD4KEY5:CJNE A,#22H,KEY6AJMP WORD5KEY6:CJNE A,#24H,KEY7AJMP WORD6KEY7:CJNE A,#28H,KEY8AJMP WORD7KEY8:CJNE A,#41H,KEY9AJMP WORD8KEY9:CJNE A,#42H,KEY10 AJMP WORD9KEY10:CJNE A,#44H,KEY11 AJMP WORD10KEY11:CJNE A,#48H,KEY12 AJMP WORD11KEY12:CJNE A,#81H,KEY13 AJMP WORD12KEY13:CJNE A,#82H,KEY14 AJMP WORD13KEY14:CJNE A,#84H,KEY15 AJMP WORD14KEY15:CJNE A,#88H,PASSAJMP WORD15 WORD0:MOV AD,#00ACALL DISPAjmp PASSWORD1:MOV AD,#01ACALL DISPAjmp PASSWORD2:MOV AD,#02ACALL DISPAjmp PASSWORD3:MOV AD,#03ACALL DISPAjmp PASSWORD4:MOV AD,#04ACALL DISPAjmp PASSWORD5:MOV AD,#05 ACALL DISPAjmp PASSWORD6:MOV AD,#06 ACALL DISPAjmp PASSWORD7:MOV AD,#07ACALL DISPAjmp PASSWORD8:MOV AD,#08 ACALL DISPAjmp PASSWORD9:MOV AD,#9ACALL DISPAjmp PASSWORD10:MOV AD,#10 ACALL DISPAjmp PASSWORD11:MOV AD,#11 ACALL DISPAjmp PASSWORD12:MOV AD,#12 ACALL DISPAjmp PASS WORD13:MOV AD,#13 ACALL DISPAjmp PASSWORD14:MOV AD,#14 ACALL DISPAjmp PASSWORD15:MOV AD,#15ACALL DISPPASS: retDISP: MOV A,ADMOV DPTR,#numtabMOVC A,@A+DPTRMOV P0,ARETnumtab: DB 0c0H,0f9H,0a4H,0b0H,99H,92H,82H,0f8H,80H,90H,88H,83H,0C6H,0A1H,86H,8EHDELAY1:MOV R5,#10D1: MOV R6,#250DJNZ R7, $DJNZ R5,D1RETEND。

51单片机键盘扫描程序7294详细介绍

51单片机键盘扫描程序7294详细介绍

51单片机键盘扫描程序7294详细介绍1. 前言随着人们对电子产品的需求不断增加,微处理器成为现代电子设备中必不可少的一个组成部分。

其中,单片机作为一种嵌入式微处理器,由于其功能强大、价格低廉和易于编程等优点,被广泛应用于各个领域。

在单片机应用中,键盘扫描技术是常见的一种应用技术。

它既可以用于普通键盘,也可以用于定制键盘或遥控器等输入设备。

在51单片机中,键盘扫描程序7294是最为常用和经典的键盘扫描程序之一。

本文将详细介绍7294程序的原理、功能和实现方法。

2. 概述7294程序是一种基于矩阵扫描的键盘输入程序,也称为键盘扫描程序。

该程序主要由两个部分组成,即扫描部分和解码部分。

扫描部分是通过读取每个行端口和列端口的状态,得出当前按下的键位信息。

在实现过程中,通常采用交错式扫描,即先扫描行端口再扫描列端口。

这种方式可以避免多个键同时按下时无法识别的情况。

解码部分负责将扫描部分得到的行列矩阵转换成对应的键位信息。

这里我们可以采用查表法或者位运算法来实现。

3. 原理主要原理7294程序的主要工作原理如下:(1)行列扫描首先,程序将所有行端口设为输出,所有列端口设为输入。

接着,程序对每个行端口进行扫描,每次只将一个行端口输出高电平,同时读取所有列端口的状态。

如果任意一个列端口检测到低电平,说明该列与当前行对应的键被按下,程序将该键位信息保存下来。

反之,如果所有列端口均输出高电平,说明该行无按键按下。

(2)解码当扫描部分输出一个键位矩阵后,解码部分即开始工作。

首先,程序将每个键位的状态 (按下或放开)保存到一个矩阵中。

接着,程序通过查表法或者位运算法将该矩阵转换成对应的键位信息,然后提交给主程序进行后续处理。

4. 具体实现为了更好地理解7294程序的实现步骤,我们这里以4x4矩阵键盘为例展示其具体实现过程。

(1)硬件连接首先,将4个行端口 (行1~行4)和4个列端口 (列1~列4)分别连接到51单片机的IO口,如图所示:(2)扫描过程接着,通过编写程序实现键盘的扫描过程。

51单片机键盘接口电路(含源程序)

51单片机键盘接口电路(含源程序)

51单片机键盘接口电路(含源程序)键盘是由若干按钮组成的开关矩阵,它是单片机系统中最常用的输入设备,用户能通过键盘向计算机输入指令、地址和数据。

一般单片机系统中采和非编码键盘,非编码键盘是由软件来识别键盘上的闭合键,它具有结构简单,使用灵活等特点,因此被广泛应用于单片机系统。

按钮开关的抖动问题组成键盘的按钮有触点式和非触点式两种,单片机中应用的一般是由机械触点组成的。

在下图中,当开<键盘结构图>< P> 图1 < P> 图2关S未被按下时,P1。

0输入为高电平,S闭合后,P1。

0输入为低电平。

由于按钮是机械触点,当机械触点断开、闭合时,会有抖动动,P1。

0输入端的波形如图2所示。

这种抖动对于人来说是感觉不到的,但对计算机来说,则是完全能感应到的,因为计算机处理的速度是在微秒级,而机械抖动的时间至少是毫秒级,对计算机而言,这已是一个“漫长”的时间了。

前面我们讲到中断时曾有个问题,就是说按钮有时灵,有时不灵,其实就是这个原因,你只按了一次按钮,可是计算机却已执行了多次中断的过程,如果执行的次数正好是奇数次,那么结果正如你所料,如果执行的次数是偶数次,那就不对了。

为使CPU能正确地读出P1口的状态,对每一次按钮只作一次响应,就必须考虑如何去除抖动,常用的去抖动的办法有两种:硬件办法和软件办法。

单片机中常用软件法,因此,对于硬件办法我们不介绍。

软件法其实很简单,就是在单片机获得P1。

0口为低的信息后,不是立即认定S1已被按下,而是延时10毫秒或更长一些时间后再次检测P1。

0口,如果仍为低,说明S1的确按下了,这实际上是避开了按钮按下时的抖动时间。

而在检测到按钮释放后(P1。

0为高)再延时5-10个毫秒,消除后沿的抖动,然后再对键值处理。

不过一般情况下,我们常常不对按钮释放的后沿进行处理,实践证明,也能满足一定的要求。

当然,实际应用中,对按钮的要求也是千差万别,要根据不一样的需要来编制处理程序,但以上是消除键抖动的原则。

51单片机讲稿第九章键盘使用

51单片机讲稿第九章键盘使用

;0号键功能程序
;0号键功能程序执行完返回 ;0号键功能程序
JMP START
……………………… PROM7: ……………………… JMP START …
;1号键功能程序执行完返回
;7号键功能程序 ;7号键功能程序执行完返回
键盘的使用
7.2.4 行列式键盘
行列式键盘又叫矩阵式键盘。用I/O口线组成行、列结构, 按键设置在行列的交点上。例如4×4的行列结构可组成16个键 的键盘。因此,在按键数量较多时,可以节省I/O口线。 1.行列式键盘的接口 行列式键盘的接口方法有许多,例如直接接口于单片机的 I/O口上;利用扩展的并行I/O接口;用串行口扩展并行I/O口接 口;利用一种可编程的键盘、显示接口芯片8279进行接口等。 其中,利用扩展的并行I/O接口方法方便灵活,在单片机应用系
统中比较常用。
键盘的使用
图7.2.6 8255扩展I/O口组成的行列式键盘
键盘的使用 2.键盘工作原理 按键设置在行、列线的交点上,行、列线分别连接到按键 开关的两端。行线通过上拉电阻接+5 V,被箝位在高电平状态。 对键盘的工作过程可分两步:第一步是CPU首先检测键盘 上是否有键按下;第二步是再识别是哪一个键按下。 检测键盘上有无键按下可采用查询工作方式、定时扫描工 作方式和中断工作方式。
键盘的使用
7.2.2 键盘接口和键输入软件中应解决的几个问题
1.消除键抖动
键按下
键稳定
前沿抖动 前沿抖动
图7.2.2 键合断时的电压抖动
键盘的使用
图7.2.3 消除键抖动电路
键盘的使用 2.键编码及键值
(1) 用键盘连接的I/O线的二进制组合表示键码。例如用4行、
4列线构成的16个键的键盘,可使用一个8位I/O口线的高、低4 位口线的二进制数的组合表示16个键的编码,如图5.4(a)所示。 各键相应的键值为88H、84H、82H、81H、48H、44H、42H、 41H、28H、24H、22H、21H、18H、14H、12H、11H。这种键 值编码软件较为简单直观,但离散性大,不便安排散转程序的 入口地址。

基于51单片机的利用8155实现阵列式键盘程序

基于51单片机的利用8155实现阵列式键盘程序

//-----------------------函数声明,变量定义---------------------------#include <reg51.h> //头文件#include <absacc.h> //XBYTE 宏定义#define uchar unsigned char//类型定义#define uint unsigned int //类型定义#define com XBYTE[0x7f00] //8155命令状态寄存器地址#define pa XBYTE[0x7f01] //8155的A口地址#define pb XBYTE[0x7f02] //8155的B口地址#define pc XBYTE[0x7f03] //8155的C口地址#define LED1 P1 //键号十位显示数码管驱动口#define LED2 P2 //键号个位显示数码管驱动口sbit iom=P1^7; //8155的I/O与RAM选择端口const uchar tab[]={ //7段共阳极数码管的段选码表0xc0,0xf9,0x24,0x30, //0~30x19,0x12,0x02,0x78, //4~70x00,0x18,0x08,0x03, //8~b0x46,0x21,0x06,0x0e, //c~f0x7f // 数码管灭};//-----------------------函数声明------------------------------------bit press(void); //判断是否有键按下,有返回1,没有返回0 uchar read(void); //扫描键盘,返回键值uchar show(uchar row); //显示键号void delay_50us(uint m); //延时子程序//****************************//main(){uchar row3;iom=1; //8155的IO定义com=0x0c; //8155 C口设置为输出口,A口设置为输入口while(1){row3=read(); //读按键号show(row3); //显示键号while(press()); //等待键释放delay_50us(50); //延时,防止数码管闪烁}}bit press(void){uchar hang;pc=0x00; //4行输出全‘0’hang=pa; //读A口数据列号if(hang!=0xff) //看是否不全为高电平return(1); //有低电平时,表示有键按下,返回1elsereturn(0); //全为高电平时,表示无键按下,返回0}uchar read(void){uint t;uchar hang,lie,keyscan,j,value;value=0x00;if(press()==1){delay_50us(200); //延时去抖if(press()==1){hang=0xfe; //输出监测行号赋初值,监测第1行//****************逐行扫描开始****************//for(t=0;t<4;t++) //逐行监测循环{pc=hang; //输出行监测码lie=pa; //读列号段码,有键按下的位为0if(lie!=0xff) //如果不为全1,表示该行有键按下//****************计算键号开始****************//for(j=0;j<8;j++) //看是8列中的哪列有键按下{if((lie&0x01)!=0x01) //是第j列吗{ //是keyscan=j+value; //列号+行号×8=键号return(keyscan); //返回键号}else //不是{lie>>=1; //列段码右移,继续监测最低位}}//****************计算键号结束****************//else //否则,该行无键按下准备监测下一行{hang=(hang<<1)|0x01; //行监测码左移value+=0x08; //每监测一行无键按下时,键号加8}}//****************逐行扫描结束****************//}return(0xff);}return(0xff); //无键按下时,返回FFH }uchar show(uchar row){uchar row1,row2;if(row==0xff) //无键按下时{LED1=tab[16]; //2个数码管灭LED2=tab[16];}else{ //有键按下row1=row/10; // 16进制键号除以10,得十位row2=row%10; // 16进制键号对10求余数,得个位LED1=tab[row1]; //显示十位LED2=tab[row2]; //显示个位}}void delay_50us(uint t){uchar j;for(;t>0;t--)for(j=19;j>0;j--);}。

51单片机keil下键盘驱动程序设计

51单片机keil下键盘驱动程序设计
K1: CJNE A,#1,K2 MOV P1,#11111110B LJMP LOOP
K2: CJNE A,#2,K3 MOV P1,#11111100B LJMP LOOP
K3: CJNE A,#3,K4 MOV P1,#11111000B LJMP LOOP
K4: CJNE A,#4,K5 MOV P1,#11110000B
Y
KEY3按下? N
延时10ms KEY3按下? N
(A)=3 KEY3抬起? N
Y
KEY4按下? 延时10ms KEY4按下?
(A)=3 KEY4抬起? N
Y
独立式键盘驱动程序参考
;在A中返回键码:01234,0表示没有按键按 下
KEY1 EQU P3.2 KEY2 EQU P3.3 KEY3 EQU P3.4 KEY4 EQU P3.5 ;---------------------------RDKEY: MOV A,#0 RDKEY1: JB KEY1,RDKEY2
;是key1? ;显示键码
练习3:用动态显示数码管显示键码
;用6位数码管的最右面一位显示键码,按KEY1显示1,按KEY2显示2, 按KEY3显示3,按KEY4显示4。
键盘接口方式
独立式键盘接口
每个按键占用一个端口 优点:接口简单,编程简单 缺点:占用端口多,适应与按键少的场合
矩阵式键盘接口
按键排列成行列矩阵形式 优点:占用端口少,适应与按键多的场合 缺点:编程复杂
独立式键盘接口电路
AT89S51 P3.2 P3.3 P3.4 P3.5
DJNZ R7,DELAY2 DJNZ R6,DELAY1 RET
练习2:用P1口的发光管显示键码

例说51单片机8-学习使用键盘

例说51单片机8-学习使用键盘

pzq@/csh@sparkcn8. 学习使用键盘前面章节我们主要了LED 、点阵、数码管等,这些我们都称之为输出设备,这一章我们就一起来看嵌入式中最常用的输入设备—按键和键盘。

8.1 简介说到按键大家都很熟悉,这个东西随处可见,其原理也比较简单,就是平时处于断路状态,一按下,就是短路状态了,达到一个状态切换的目的。

如下图8-1所示图 8-1在嵌入式中常见的键盘有三种1 独立键盘所谓独立按键就是每个按键单独连接在CPU 的一个I/O 口上,每个按键之间是独立的。

如图8-2的连接方式pzq@/csh@sparkcn图 8-2这种连接方式,每增加一个按键就要多使用一个I/O 口,所以在按键比较多的情况下,就不适合使用这种按键连接方式。

否则整个CPU 都被按键给占用。

这种按键的操作方式也比较简单,学完本章后面的内容,代码留给大家做动手题。

2 矩阵键盘当使用的键盘比较多时,使用这种方式连接可以节约很多IO 口,因为在原图图上排列成矩形,所以一般叫矩阵键盘,有时也叫行列键盘。

上图图 8-3这种方式方式使用n 行n 列可以扩展出n*n 个键盘,比使用独立按键大大减pzq@/csh@sparkcn少IO 口的使用。

适合于按键比较多的情况,这个也是这章主要负责消灭的问题。

3使用专用芯片来管理键盘,当单片机的I/O 口已经不够添加需要的按键数或单片机的程序本身很繁忙,没有功夫应付按键的计算时,就得考虑使用专用芯片了。

如周立功的zlg7289(请童鞋们自己上网搜索这个芯片的使用手册并了解其使用方法)。

抖动注意了,这里的抖动可不是说你按键时手的抖动。

这里的抖动指的是因为按键机械特性,固有的抖动。

当我们按下按键时,我们认为他的状态就是由开路直接变为短路了,从CPU 端看到就是0变1,或1变0了。

这是我们想的理想情况,实际情况并没有这么干脆利索,如果你手头有示波器的话,可以自己动手测量一下按下时的波形,这样印象会更深刻,如果没有,就看看前人的经验吧,也是一样的,看下图8-4。

51单片机键盘设置

51单片机键盘设置

\\\§8.3 键盘接口技术一、键盘输入应解决的问题键盘是一组按键的集合,它是最常用的单片机输入设备.操作人员可以通过键盘输入数据或命令,实现简单的人机通讯。

键是一种常开型按钮开关,平时(常态)键的二个触点处于断开状态,按下键时它们才闭合(短路)。

键盘分编码键盘和非编码键盘。

键盘上闭合键的识别由专用的硬件译码器实现并产生编号或键值的称为编码键盘,如:ASCⅡ码键盘、BCD码键盘等;靠软件识别的称为非编码键盘。

在单片机组成的测控系统及智能化仪器中用得最多的是非编码键盘。

本节着重讨论非编码键盘的原理、接口技术和程序设计。

键盘中每个按键都是—个常开关电路,如图所示。

1.按键的确认:P1.7=1 无按键;P1.7=0 有按键;2.去抖动去抖动的方法:①硬件去抖动采用RS触发器:优点: 速度快,实时,缺点: 增加了硬件成本②软件去抖动采用延时方法延时5—10ms 延时5—10ms P1.7=0 确认P1.7=0 P1.7=1 (去前沿抖动) (去后沿抖动)二、独立式键盘每个I/O口连接一个按,S1 P1.0S2 P1.1……………………….S8 P1.7软件:START:MOV P1,#0FFH ;置P1口为高电平JNB P1.0, RS1 ; S1按下,程序去执行RS1JNB P1.1, RS2 ; S2按下,程序去执行RS2JNB P1.2, RS3 ; S3按下,程序去执行RS3JNB P1.3, RS4 ; S4按下,程序去执行RS4JNB P1.4, RS5 ; S5按下,程序去执行RS5JNB P1.5, RS6 ; S6按下,程序去执行RS6JNB P1.6, RS7 ; S7按下,程序去执行RS7JNB P1.7, RS8 ; S8按下,程序去执行RS8AJMP START ; 继续扫描按键………….RS1: AJMP PK1 ;RS2: AJMP PK2 ;RS3: AJMP PK3 ;RS4: AJMP PK4 ;RS5: AJMP PK5 ;RS6: AJMP PK6 ;RS7: AJMP PK7 ;RS8: AJMP PK8 ;AJMP START ; 无键按下,继续扫描…………………PK1: ……….. ;按键S1功能处理程序AJMP START ;处理S1按键后, 继续扫描PK2: ……….. ;按键S2功能处理程序AJMP START………………….PK8: ………………;按键S8功能处理程序AJMP START ; 处理S8按键后, 继续扫描优点: 连线简单,程序容易.缺点: 太浪费资源适用于按键较少、I/O口空闲的场合。

51单片机键盘数码管显示(带程序)

51单片机键盘数码管显示(带程序)

期中大作业学院:物理与电子信息工程学院课题:【利用8255和51单片机实现数码管显示按键数值的程序】要求:【4*4矩阵键盘,按0到15,数码管上分别显示0~9,A~F】芯片资料:8255:8255是Intel公司生产的可编程并行I/O接口芯片,有3个8位并行I/O口。

具有3个通道3种工作方式的可编程并行接口芯片(40引脚)。

其各口功能可由软件选择,使用灵活,通用性强。

8255可作为单片机与多种外设连接时的中间接口电路。

8255作为主机与外设的连接芯片,必须提供与主机相连的3个总线接口,即数据线、地址线、控制线接口。

同时必须具有与外设连接的接口A、B、C口。

由于8255可编程,所以必须具有逻辑控制部分,因而8255内部结构分为3个部分:与CPU连接部分、与外设连接部分、控制部分。

8255特性:1.一个并行输入/输出的LSI芯片,多功能的I/O器件,可作为CPU总线与外围的接口。

2.具有24个可编程设置的I/O口,即3组8位的I/O口,分别为PA口、PB口和PC 口。

它们又可分为两组12位的I/O口:A组包括A口及C口(高4位,PC4~PC7),B组包括B口及C口(低4位,PC0~PC3)。

A组可设置为基本的I/O口,闪控(STROBE)的I/O闪控式,双向I/O三种模式;B组只能设置为基本I/O或闪控式I/O两种模式,而这些操作模式完全由控制寄存器的控制字决定.引脚说明RESET:复位输入线,当该输入端处于高电平时,所有内部寄存器(包括控制寄存器)均被清除,所有I/O口均被置成输入方式。

CS:芯片选择信号线,当这个输入引脚为低电平时,即CS=0时,表示芯片被选中,允许8255与CPU进行通讯;CS=1时,8255无法与CPU做数据传输。

RD:读信号线,当这个输入引脚为低电平时,即CS=0且RD=0时,允许8255通过数据总线向CPU发送数据或状态信息,即CPU从8255读取信息或数据。

WR:写入信号,当这个输入引脚为低电平时,即CS=0且WR=0时,允许CPU将数据或控制字写入8255。

单片机电脑键盘输入程序

单片机电脑键盘输入程序
/*说明:此程序使用标准PS2键盘输入,LCD1602液晶屏输出显示。此样例仅作测试使用
晶振使用12M或者11.0592M,本键盘使用部分字母和数字测试,其他按键不能使用,用
户可以自行扩展。由于开发板和程序的各种参数,程序中没有使用奇偶校验,不保证没有
误码,校验程序请自行添加。
*/
//注意:接上标准PS2键盘后,按下键盘后,LCD1602才会显示出相关字母
ShowChar(DisNum,Shifted[TempCyc][1]);
DisNum++;
if(DisNum==32)
{
WriteCommand(0x01);//清屏
if (Key_Data)
KeyV = KeyV | 0x80; //当键盘数据线为1时到最高位
}
IntNum++;
while (!Key_CLK); //等待PS/2CLK拉高
if (IntNum > 10)
{
IntNum = 0; //当中断11次后表示一帧数据收完,清变量准备下一次接收
void Decode(unsigned char ScanCode);//解码子程序
void main()
{

IT1 = 0; //设外部中断1为低电平触发
EA = 1; //外部中断开
EX0 = 1; //开中断
InitLcd();//初始化1602液晶屏
do
{
if (BF)
Shift = 1;
break;
case 0x59 : // 右 SHIFT
Shift = 1;

51单片机-独立按键

51单片机-独立按键
单片机对按键动作的识别有两种方式:
查询方式
单片机不断的扫描键盘判断按键是否动作 特点:硬件简单,但需要单片出中断请求,单片机响应中断请求后转按键 识别程序
特点:硬件复杂,需要中断电路,但不占用CPU资源
单片机处理按键的流程
单片机处理按键动作需要以下步骤:
按键识别
单片机在识别按键时,IO口工作在输入状态:
按键弹起,IO口电平5V
Vcc
按键按下,IO口电平0V
单片机读取IO口的状态
即可知按键的状态
单片机
按键抖动
实际的按键在被按下或抬起时,由于机械 触点的弹性作用,在闭合或断开的瞬间均伴随有 一连串的抖动现象。
理想波形
实际波形
按下抖动
稳定闭合
释放抖动
完整的按键过程包括: 1. 释放状态 2. 按下抖动阶段 3. 完全按下状态 4. 释放抖动阶段 5. 释放状态
按键防抖
防抖措施:
硬件防抖
在按键输出端加RS或施密特触发器 去抖效果好、电路复杂、成本高
软件防抖
利用软件进行延时(10ms) 电路简单、成本低、但占用CPU时间
键盘的工作方式
判断按键是否按下 按键按下时的防抖 识别哪个按键按下,判断键值 判断按键是否放开 送出键值,处理按键动作
练习:单片机按键查询操作,8个按键对应8个LED灯, K1对应D1,K2对应D2,K3对应D3,……,查询按键, 按下某一个按键后对应的LED亮起,再按一次关闭。

(word完整版)基于51单片机状态机矩阵键盘扫描数码管动态显示的时钟系统

(word完整版)基于51单片机状态机矩阵键盘扫描数码管动态显示的时钟系统

/******************************************************************************程序功能:基于状态机的线性反转扫描方法实现按键扫描数码管动态显示开发环境:KeiL4硬件环境:STC12C5A60S2,11.0592接线说明:单片机P1口接底板JP29,具体接法为:P10—L1,P11—L2,P12—L3,P13-L4,P14-L5,P15-L6,P16-L7,P17-L8单片机P20~P21接底板JP26,具体接法:P20—DS,P21—SHCP,P22-STCP跳线说明:J70实验现象:数码管动态显示时钟时间同时显示当前被按下的键值可通过矩阵键盘对时钟进行开关已经参数调试******************************************************************************/#include <REG52。

h>typedef unsigned char uint8;typedef unsigned int uint16;#define KEY_PORT P1 //定义4x4键盘使用的单片机端口sbit SEG_DS = P2^0;//74HC595芯片的数据引脚sbit SEG_SHCP = P2^1;//74HC595芯片的控制引脚,上升沿移入数据sbit SEG_STCP = P2^2; //74HC595芯片的控制引脚,上升沿更新数据//*****************************************************************************//全局变量//*****************************************************************************char hour,min,sec; // 秒分时uint8 Clock_flag; //时钟开关标志位uint8 ct_flag;//按键长按标志位 //*****************************************************************************//反转法矩阵键盘的各个按键的计算值unsigned char tabLe[]={0xee,//00xed,//10xeb,//20xe7,//30xde,//40xdd,//50xdb,//60xd7,//70xbe,//80xbd,//90xbb,//100xb7,//110x7e,//120x7d,//130x7b,//140x77 //15};//共阳数码管的编码,并将数据定义在CODE区unsigned char code Seg_Data[]={0xc0,/*0*/0xF9,/*1*/0xA4,/*2*/0xB0,/*3*/0x99,/*4*/0x92,/*5*/0x82,/*6*/0xF8,/*7*/0x80,/*8*/0x90,/*9*/0x88,/*A*/0x83,/*b*/0xC6,/*C*/0xA1,/*d*/0x86,/*E*/0x8E,/*F*/};//数码管位选编码,控制显示8位中的第几位unsigned char code Seg_Addr[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0xFF,//ALL ON0x00 //OFF};//*****************************************************************************//函数声明//*****************************************************************************void SEG_Send595OneByte(unsigned char ucData); //向74HC595写入一个8位的数据//指定数码管显示定数字void DispLayOneCharOnAddr(unsigned char Data,unsigned char Addr);unsigned char Key_Scan(void); //基于状态机的按键扫描void Parameter_Setting(uint8 key_value_get); //按键参数设置void Timer0Configuration(); //定时器初始化void CLOCK(void); //时钟运行函数//*****************************************************************************//*****************************************************************************//*****************************************************************************//定时器0中断服务函数//*****************************************************************************void Timer0() interrupt 1{uint8 key_get,j;static uint8 i=0,key_value;static uint16 count=0;TH0 = (65536-922)/256;TL0 = (65536-922)%256;/***********************用户代码************************************/count++;if(962==count) //一秒运行一次时钟{if(Clock_flag)CLOCK(); //时钟走一次count=0; //定时计数清零}switch(i){case 0:i++;DispLayOneCharOnAddr(hour/10,0) ; //数码管动态显示第一位break;case 1:i++;DispLayOneCharOnAddr(hour%10,1) ; //数码管动态显示第二位break;case 2:i++;DispLayOneCharOnAddr(min/10,2);//数码管动态显示第三位break;case 3:i++;DispLayOneCharOnAddr(min%10,3) ; //数码管动态显示第四位break;case 4:i++;DispLayOneCharOnAddr(sec/10,4); //数码管动态显示第五位break;case 5:i++;DispLayOneCharOnAddr(sec%10,5) ; //数码管动态显示第六位break;case 6:i++;DispLayOneCharOnAddr(key_value,6); //数码管动态显示第七位break;case 7:i++; //数码管动态显示第八位break;case 8: i=0;key_get=Key_Scan(); //状态机按键扫描每9ms进行一次扫描(word完整版)基于51单片机状态机矩阵键盘扫描数码管动态显示的时钟系统 if(key_get) //按键没按下返回零{for(j=0;j<16;j++){if(key_get==tabLe[j]) //通过查表得出按键的号{key_value=j;break;}}Parameter_Setting(key_value); //按键参数调试函数输入按键号}break;default:break;}}//*****************************************************************************//主函数//*****************************************************************************void main(void){EA=0; //关总中断Timer0Configuration(); //定时器0初始化 1ms中断EA=1; //开总中断while(1) //循环等待中断到来{}}//***************************************************************************** //*****************************************************************************//向HC595发送一个字节void SEG_Send595OneByte(unsigned char ucData){unsigned char i;for(i = 0;i < 8;i++) //8位数据依次写入,先写最低位{SEG_DS = (ucData & 0x80);//先读入高位 x&0x80;SEG_SHCP = 0;SEG_SHCP = 1;SEG_SHCP = 0; //SHCP引脚的上升沿移入数据ucData <〈=1; //数据左移}}(word完整版)基于51单片机状态机矩阵键盘扫描数码管动态显示的时钟系统/*******************************************************函数功能:在指定位置显示一个数据参数说明:Data是要显示的数据,Addr是在第几位显示.Addr取值范围是0~9。

单片机键盘扫描之状态机实现

单片机键盘扫描之状态机实现

PDF 文件使用 "pdfFactory Pro" 试用版本创建
************************************************************/ #ifndef _INCLUDES_H_ #define _INCLUDES_H_ //system #include #include #include #include #include #include #include header files <stdio.h> <string.h> <stdarg.h> <avr/io.h> <avr/signal.h> <avr/interrupt.h> <avr/wdt.h>
PDF 文件使用 "pdfFactory Pro" 试用版本创建
Author:原野之狼 Version :V1.0 Date: 2008.1.2 Description: History: <author> <time> <version > <desc>
************************************************************/ #ifndef _TYPE_H_ #define _TYPE_H_ //type define #define UINT8 unsigned char #define INT8 char #define UINT16 unsigned int #define INT16 signed int #define UINT32 unsigned long #define INT32 signed long #define FLP32 float #endif /************************************************************ FileName: includes.h Author:原野之狼 Version :V1.0 Date: 2008.1.2 Description: History: <author> <time> <version > <desc>

第9章_51单片机实现状态机

第9章_51单片机实现状态机
7. 上电状态机初始化 在状态机上电时,无论为何种输入条件,都应该进入到一个确定的状态,该状态称为 上电初始状态。有些状态机可以在上电时,自动进入上电初始状态,有些状态机则不能, 需要复位信号的帮助才能进入上电初始状态。
9.1.2状态图 状态图是用于小型、中型状态机设计的一种方法,该方法的特点是简单。 状态图中的状态转移是用一根弧线表示的,所以不管有多少输入变量,也只能有一个 转移条件表达式,应该使现在状态到所有次态的转移条件互斥,也就是说只能转移到一个 次态。 另外需要说明的是用于控制器的状态机大部分都是摩尔状态机,就是说这些状态机的 输出仅仅与状态有关。
由图可知,当k=0时,状态从a0转移到a1, 若是k0=1,从状态a1转移到a2,等等,若 是reset=0,则无论在什么状态,都将转移 到a0状态。
.
a0 re set= 0
r e s e t = 0
k= 0
a1
re set= 0 k= 1
a4
.
a2 k= 0 td =1 a3 定时
.
ห้องสมุดไป่ตู้置数
.
报警
第9章 51单片机实现状态机
9.1 有限状态机
有限状态机(FSM)与流程图很相似,具有一组按照一定路径排列的状态,依据于状 态中的事件和动作,一个状态可以转移到其他状态。
状态是时间中的一个点,例如,当你等火车的时候,你在等待状态。一种状态在一个 状态机中,只能出现一次。
事件是某时发生的事情,例如火车到达,火车运行。
[例题9-1] 设计一个顺序开关装置,该开关装置在按键k第一次按下时,三盏灯x、y和z同时点 亮,当k 再次按下时,x灯立刻熄灭;y灯15s后熄灭,在y灯熄灭后18s后,z灯熄灭。 转 移 条 件 k td15 td18 说明 输入按键 15秒定时到信号 18秒定时到信号 状态 z0 z1 z2 z3 z4 说明 三灯都灭 三灯都亮 三灯都亮 x灯灭,其他亮 x、y灯灭,z灯亮 输出 t15 t18 x y z 说明 15 秒 定 时 起 动 18 秒 定 时 起 动 x灯 y灯 z灯
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
break;
}
default://其它
{
step = _Key1_up;//单键抬起消抖
#define Key_Down 0x3D //下箭头
#define Key_Add 0x3B //加
#define Key_Sub 0x37 //减
#define Key_Enter 0x2F //回车
传入参数:无
返回参数:无
设 计:莫汉伟 amo73@
修改日期:2007-10-12
备 注:详细功能和处理算法请参照本文件相关的流程图和文档
**************************************************************************/
#define KeyBuffLen 8 //定义键值环形缓冲区长度为8(缓冲区大小可自由定义,只要大于0即可)
//定义一个键盘缓冲区结构体
struct Struct_KeyBoardBuff
{
u8 buff[KeyBuffLen];//键值环形缓冲区
u8 in; //写键值指示(定时器中断写)
u8 Read_Key(void)
{
u8 Value;
if(Key.out != Key.in)
{
Value=Key.buff[Key.out++];//"读"还没有追上"写",缓冲区有键值,读之
if(Key.out >= KeyBuffLen) //如果"读"跑到了队列尾部,则重新跳回原点
u8 out; //读键值指示(用户读)
}Key;
/*************************************************************************
函数原型:void Key_Board_Init(void)
函数功能:对键盘接口进行初始化,即把键值缓冲区清零
{
switch(num)
{
case 1://单键
{
if(NewKey != Key_Input)//键值改变
step = _Key1_up;//单键抬起消抖
{
step = _Key_Idle;//空闲
break;
}
}
break;
}
case _Key1_press://单键按下
凑热闹我也发个使用状态机的键盘程序,支持单键和双键
单键, 键盘, 状态, 程序, 凑热闹
1-头文件:KeyBoard.h
#ifndef _Key_Board_h_
#define _Key_Board_h_
#define Kecase 1://单键
{
if(NewKey == Key_Input)//键值不变
step = _Key1_press;//单键按下
extern void Key_Board_Test(void); //键盘接口测试函数(仅在调试阶段使用)
#endif
2-源文件:KeyBoard.c
//#include "includes.h" //公共头文件
#include "Key_Board.h"
//键盘缓冲区相关常量定义
SoundLight_ms(_TypeLcdBkLED,9000);//LCD背光亮一段时间
break;
}
default://其它
{
void Key_Board_Init(void)
{
memset(&Key,0,sizeof(Key));
}
/*************************************************************************
函数原型:u8 Read_Key(void)
}
/*************************************************************************
函数原型:void Key_In(void)
函数功能:在定时器中断里每10ms调用1次,处理按键输入,并将按键值放入键值缓冲区中。
支持单键、双键组合键
函数功能:从键值缓冲区读取一个键值
传入参数:无
返回参数:u8型按键值,如果缓冲区为空,则返回-1
设 计:莫汉伟 amo73@
修改日期:2007-9-5
备 注:供用户程序调用;用户不用关心键盘底层硬件。
**************************************************************************/
u8 JudgeKey(u8 key)
{
u8 i,count=0;
for(i=0;i<6;i++)
{
if((key & 0x01)==0)
count++;
key >>= 1;
}
return(count);
_Key2_press, //双键按下
_Key2_up, //双键抬起消抖
_Key_confirm, //按键确认成功
};
//处理扫描按键、判断按键、保存键值等。在定时器中断里(周期为10ms以上即可)调用本函数。
void Key_In(void)
Key_Input = NewKey;//保存键值
step = _Key1_down;//单键按下消抖
SoundLight_ms(_TypeLcdBkLED,9000);//LCD背光亮一段时间
break;
}
}
break;
}
case _Key1_down://单键按下消抖
{
switch(num)
{
Key.out=0;
}
}
else
{
Value=Key_NULL;//"读"追上了"写",缓冲区没有键值,返回空键值
}
return(Value);
}
//判断一个键值的键数(在本硬件里1bit对应一个按键,0表示按键按下)
extern void Key_Board_Init(void);//键盘接口初始化
extern u8 Read_Key(void); //读键函数,返回键盘缓冲区中的键值
extern void Key_In(void);//处理按键输入函数,在定时器中断里调用
#define Key_Return 0x1F //返回
#define Key_LR 0x33 //左右组合键
//可以在此定义其它组合键……
#define Key_NULL 0xFF //无任何按键
//声明几个需要在外部调用的函数
break;
}
case 2://双键
{
Key_Input = NewKey;//保存键值
step = _Key2_down;//双键按下消抖
{
static u8 Key_Input=0;
//在此添加获取键值代码(参照硬件电路图)
static u8 volatile step=0;//步骤
u8 NewKey = uPSD.DATAIN_A & 0x3F;//读取按键
//获取键值代码结束
u8 num=JudgeKey(NewKey);//判断当前有几个按键按下
传入参数:无
返回参数:无
全局变量:直接操作键盘缓冲区结构体
设 计:莫汉伟 amo73@
修改日期:2007-9-5
备 注:仅在上电初始化的时候被调用一次
**************************************************************************/
switch(step)//状态机
{
case _Key_Idle://空闲
{
switch(num)
{
case 1://单键
{
enum KeyFSM_Enum //按键状态有限状态机
{
_Key_Idle=0, //空闲
_Key1_down, //单键按下消抖
_Key1_press, //单键按下
_Key1_up, //单键抬起消抖
_Key2_down, //双键按下消抖
Key_Input = NewKey;//保存键值
step = _Key2_down;//双键按下消抖
break;
}
default://其它
break;
}
case 2://双键
{
Key_Input = NewKey;//保存键值
step = _Key2_down;//双键按下消抖
else
step = _Key_Idle;//空闲
break;
}
case 2://双键
{
相关文档
最新文档