C51 4*4键盘扫描程序(c语言)

C51 4*4键盘扫描程序(c语言),第1张

键盘为4*4矩阵式连接,一共有16个按键。 工作原理为。P1端的低四位为列,高四位行。所先置低四位为低,高四位为高,当有按键按下时高四位就会有某位被拉低。只要判断高四位不为全高就说明有按键按下。判断有按键按下后就要判断是某位按下的,方法为,选将高四位的某一位置低。判断低四位是否有低电平出现。依次对高四位的每位置低并判断低四位出现的低电平。如高四位某位置低后判圆低四某也有出现低电平。这样就能判断出低四位与高四位相连的位某位按键被按下了。通过定义好的编码就可以查出是某个按键被按下了,程序将按键值通过查表并发送到LED上显示。 6位LED为动态扫描方式 。先显示第一位,延时一定时间后在显示第二位依次类推。。。 共有17个按键汪陆。按下按键后数码管显示相应的数字,并左移一位。uchar kbscan(void) /*键扫描函数*/{uchar j uchar sccode,recode P2=0x0f /*发0行扫描码*/ if((P2 &0x0f)!= 0x0f) /*若有键按下*/ { dlms() if((P2&0x0f)!= 0x0f) /*逐行扫描初值*/ { sccode=0xfe for(j=4j>0j--){ while((sccode&0x10)!=0){ P2=sccode /*输出行扫描码*/ if((P2&0xf0)!=0xf0) /*本行有键按下*/ { recode=(P2&0xf0)|0x0freturn((~sccode)+(~recode)) /*返回特征字节码*/ } elsesccode=(sccode<<掘陵塌1)|0x01 /*行扫描码做移一位*/ } } } }return(0) /*无键按下,返回0值*/}参考链接: http://www.picavr.com/news/2008-07/6869.htm

KEYBUF EQU 40H 键号存放单元

ORG 0000H

LJMP MAIN

ORG 0030H

MAIN:MOV KEYBUF,#0初始键号设位0,也可以为任意值

MOV R0,#30H 显示首地址

MOV R2,#0CH 计算数据存放单元个数

CLR A

QING:MOV @R0,A将数据存放单元清零

INC R0

DJNZ R2,QING

MOV P0,#8FH 关闭显示

MOV R1,#30H 将显示首地址存放R1里

===============================================

五位无符号显示子程序

DIS1:MOV R0,#30H 把显示数据第一位放在R0里

MOV R2,#04H 把显示的位码轿塌放在R2里

MOV R3,#05H 把显示的长度放在R3里

DIS2:MOV A,@R0

ANL A,#0FH 屏蔽显示数据的高闭悉圆四位

MOV B,A

MOV A,R2

ANL A,#0FH 屏蔽位码的高四位

SWAP A

ORL A,B

MOV P0,A 送总显示数据到P0显示

LCALL DELY4ms调用延时4ms

INC R0 取下一个显示数据

DEC R2

DJNZ R3,DIS2 四位显示晚后重新开始显示

===================================================

键盘扫描子程序

WAIT:MOV P1,#0FFHP1口送高电平

CLR P1.0第一行清零

MOV A,P1读P1口

ANL A,#0F0H 低位屏蔽

XRL A,#0F0H 判断低位是否有低电平 ,即判断是否有按键按下

JZ NOKEY1 地位有低电平继续扫描,否者跳到第而行去扫描

LCALL DELY10ms 延时10ms去抖在进行判断是否有按键按下

MOV A,P1继续读P1口

ANL A,#0F0H 判断低位是否有低电平

CJNE A,#0E0H,NK1如果扫描数据不为0E0H就转到NK1

MOV KEYBUF,#0 否者判断为0号键

AJMP DK 转DK1查表程序

NK1: CJNE A,#0D0H,NK2如果扫描数据不为0D0H就转到NK2

MOV KEYBUF,#1 否者判断为1号键

AJMP DK 转DK2查表程序

NK2: CJNE A,#0B0H,NK3如果扫描数据不为0B0H就转到NK3

MOV KEYBUF,#2 否者判断为2号键

AJMP DK 转DK3查表程序

NK3: CJNE A,#70H,NK4 如果扫描数据不为70H就陆禅转到NK4

LJMP SAN_CHU

NK4: NOP

NOKEY1: MOV P1,#0FFH和上面相同

CLR P1.1

MOV A,P1

ANL A,#0F0H

XRL A,#0F0H

JZ NOKEY2

LCALL DELY10MS

MOV A,p1

ANL A,#0F0H

XRL A,#0F0H

JZ NOKEY2

MOV A,P1

ANL A,#0F0H

CJNE A,#0E0H,NK5

MOV KEYBUF,#3

AJMP DK

NK5: CJNE A,#0D0H,NK6

MOV KEYBUF,#4

AJMP DK

NK6: CJNE A,#0B0H,NK7

MOV KEYBUF,#5

AJMP DK

NK7: CJNE A,#70H,NK8

MOV KEYBUF,#10 否者判断为3号键

AJMP DK 转DK4查表程序

NK8: NOP

NOKEY2: MOV P1,#0FFH

CLR P1.2

MOV A,P1

ANL A,#0F0H

XRL A,#0F0H

JZ NOKEY3

LCALL DELY10MS

MOV A,P1

ANL A,#0F0H

XRL A,#0F0H

JZ NOKEY3

MOV A,P1

ANL A,#0F0H

CJNE A,#0E0H,NK9

MOV KEYBUF,#6

AJMP DK

NK9: CJNE A,#0D0H,NK10

MOV KEYBUF,#7

AJMP DK

NK10:CJNE A,#0B0H,NK11

MOV KEYBUF,#8

AJMP DK

NK11:CJNE A,#70H,NK12

LJMP DENG_HAO

NK12:NOP

NOKEY3: MOV P1,#0FFH

CLR P1.3

MOV A,P1

ANL A,#0F0H

XRL A,#0F0H

JZ NOKEY4

LCALL DELY10MS

MOV A,P1

ANL A,#0F0H

XRL A,#0F0H

JZ NOKEY4

MOV A,P1

ANL A,#0F0H

CJNE A,#0E0H,NK13

LJMP CHU

NK13:CJNE A,#0D0H,NK14

LJMP CHENG

NK14:CJNE A,#0B0H,NK15

LJMP JIAN

NK15:CJNE A,#70H,NK16

LJMP JIA

NK16:NOP

=======================================================

查表求键值程序

DK: MOV B,#00H

MOV A,KEYBUF 查表程序 查对应的键号数据

MOV DPTR,#TABLE 把表头地址放入DPTR

MOVC A,@A+DPTR A里面存放的为键号,利用A和表头地址找到对应的键号数据

MOV B,A 把查到的数据送往显示单元

INC R1 取下一个显示单元

MOV A,R1

CJNE A,#36H,DKA1 判断显示单元是否已满

MOV R1,#35H 35H,36H单元用于更好的控制五位显示

AJMP DKA

DKA1:MOV 34H,33H 按键代码按左移显示,先按先显示

MOV 33H,32H

MOV 32H,31H

MOV 31H,30H

MOV 30H,B

DKA: MOV A,P1 读P1口

ANL A,#0F0H 屏蔽高四位

XRL A,#0F0H 地位是有低电平

JNZ DKA 如果有低电平继续读P1口,否者向下执行,查找第二行

NOKEY4: LJMP DIS1

===================================

功能按键功能设定

DENG_HAO:MOV DPTR,#JI_SUAN等号键功能通过加、减、乘、除设定的偏移量来调用子程序

MOV A,3CH3CH存放的为功能程序入口地址偏移量

JMP @A+DPTR 转移到按键功能程序

JI_SUAN: AJMP JIA1加计算子程序

AJMP JIAN1 减计算子程序

AJMP CHENG1 乘计算子程序

AJMP CHU 除计算子程序

=======删除键功能

SAN_CHU: ACALL QING_DIS

AJMP DKA

=======加键功能

JIA: MOV 3CH,#00H

ACALL CUN_SHU

ACALL QING_DIS

AJMP DKA

=======减键功能

JIAN:MOV 3CH,#02H

ACALL CUN_SHU

ACALL QING_DIS

AJMP DKA

=======乘键功能

CHENG: MOV 3CH,#04H

ACALL CUN_SHU

ACALL QING_DIS

AJMP DKA

=======除键功能

CHU: MOV 3DH,#06H

ACALL CUN_SHU

ACALL QING_DIS

AJMP DKA

=================================

存被加(减、乘、除)数,存放在37H~3BH里

CUN_SHU: MOV 37H,30H36H存放的为最低位

MOV 38H,31H

MOV 39H,32H

MOV 3AH,33H

MOV 3BH,34H3AH存放的为最高位

RET

================================

清除显示单元

QING_DIS: MOV R1,#30H

QING1:MOV @R1,#00H

INC R1

MOV A,R1

CJNE A,#36H,QING1

MOV R1,#30H

LOP1: RET

================================

十进制加法子程序

JIA1:

MOV A,37H 个位被加数

ADD A,30H 个位被加数+加数

MOV B,#10 十六进制除10转换成BCD码

DIV AB

MOV 30H,B 余数即个位存放在30H

MOV 37H,A 商存放在37H

MOV A,38H 十位被加数

ADD A,31H 十位被加数+加数

ADD A,37H 加上个位之和的进位

MOV 37H,#00H 清除37H

MOV B,#10 十六进制除10转换成BCD码

DIV AB

MOV 31H,B 余数即十位存放在31H

MOV 38H,A 商存放在38H

MOV A,39H 百位计算同十位

ADD A,32H

ADD A,38H

MOV 38H,#00H

MOV B,#10

DIV AB

MOV 32H,B

MOV 39H,A

MOV A,3AH 千位计算同十位

ADD A,33H

ADD A,39H

MOV 39H,#00H

MOV B,#10

DIV AB

MOV 33H,B

MOV 3AH,A

MOV A,3BH 万位计算同十位

ADD A,34H

ADD A,3AH

MOV 3AH,#00H

MOV B,#10

DIV AB

MOV 34H,B

MOV 3BH,#00H

AJMP DKA

=====================

JIAN1: AJMP DKA

CHENG1: AJMP DKA

CHU1:AJMP DKA

=============================================

延时程序和查表表格

DELY4ms: MOV R6,#8延时4毫秒

D1: MOV R7,#248

DJNZ R7,$

DJNZ R6,D1

RET

DELY10ms:MOV R6,#20 延时10毫秒

D2: MOV R7,#248

DJNZ R7,$

DJNZ R6,D2

RET

TABLE: DB 07H, 04H, 01H / 本表格是以键盘为参考 7 8 9 /

DB 08H, 05H, 02H * 4 5 6 *

DB 09H, 06H, 03H - 1 2 3 -

DB 00H, 00H = + 清除 0 = +

END

//这是51hei单片机开发板让纯冲附带的一个程序,矩阵键盘接p3口,其中p3.0-p3.4为行,P3.5->p3.7为列

//每按一下键数字便可显示在1602液晶上面,并且蜂鸣器会发出响声.

//全部源代码下载: http://www.51hei.com/f/jz1602.rar

#include<reg52.h>裤庆

#include <Intrins.h>

#define uchar unsigned char

#define uint unsigned int

sbit dula=P2^6

sbit wela=P2^7

sbit rs=P2^2

sbit lcden=P2^0

sbit rw=P2^1

sbit BEEP=P2^3

uchar num,temp,date,i

uchar code table_1[]=" shu ru tiao ma "

uchar code table_2[]=" Pro_8888 "

uchar code dis_tab[17]=

{

0x30, //0在1602中的十六进制码

0x31, //1在1602中的十六进制码

0x32, //2在1602中的十六进制码

0x33, //3在1602中的十六进制码

0x34, //4在1602中的十六进制码

0x35, //5在1602中的十六进制码

0x36, //6在1602中的十六进制码

0x37, //7在1602中的十六进制码

0x38, //8在1602中的十六进制码

0x39, //9在1602中的十六进制码

0x41, //A在1602中的十六进制码

0x42, //B在1602中的十六进制码

0x43, //C在1602中的十六进制码

0x44, //D在1602中的十六进制码

0x2A, //*在1602中的十六进制码

0x23, //#在1602中的十六进制码

0x20, // 在1602中的十六进制码

}

void delay(uint z)

{

uint x,y

for(x=zx>0x--)

for(y=110y>0y--)

}

void beep()

{

uchar i

for (i=0i<50i++)

{

delay(4)

BEEP=0 //BEEP取反

}

BEEP=1 //关闭蜂鸣器

delay(100) //延时

}

void lcd_wait_busy() //1602忙检测函数

{

P0=0xff //数据口全部置1,为读状态做准备

rs=0 //选择指令寄存器

rw=1 //选择读

lcden=1 //使能线电平变化

while((P0&0x80)==0x80)//读忙状态,不忙时退出

lcden=0 //恢复使能线电平

}

// 1602写命令函数

void lcd_write_com(unsigned char combuf)

{

rs=0 //选择指令寄存器

rw=0 //选择写

P0=combuf //把命令字送入P2

lcden=1 //使能线电平变化,命令送入1602的8位数据口

_nop_()

lcden=0 //恢复使能线坦歼电平

}

// 1602写命令函数(带忙检测)

void lcd_write_com_busy(unsigned char combuf)

{

lcd_wait_busy() //调用忙检测函数

lcd_write_com(combuf) //调用写命令函数

}

// 1602写数据函数(带忙检测)

void lcd_write_data(unsigned char databuf)

{

lcd_wait_busy() //调用忙检测函数

rs=1 //选择数据寄存器

rw=0 //选择写

P0=databuf //把数据字送入P2

lcden=1 //使能线电平变化,命令送入1602的8位数据口

_nop_()

lcden=0 //恢复使能线电平

}

// 1602显示地址写函数

void lcd_write_address(unsigned char x,unsigned char y)

{

y&=0x01 //行地址限制在0-1

if(y==0x00)

lcd_write_com_busy(x|0x80) //第一行的列地址写入

else

lcd_write_com_busy((x+0x40)|0x80) //第二行的列地址写入

}

// 指定地址写入函数

void lcd_write_char(unsigned char x,unsigned char y,unsigned char buf)

{

lcd_write_address(x,y)//写入地址

lcd_write_data(buf) //写入显示数据

}

// 液晶初始化指令

void lcd_init()

{

uchar num

dula=0

wela=0

lcden=0

lcd_write_com_busy(0x38)//设置16*2显示,5*7点阵,8位数据接口

lcd_write_com_busy(0x0d)//关显示 显示光标 光标闪烁

lcd_write_com_busy(0x06)//当读或写一个字符后地址指针加一,且光标加一,写一个字符,整屏显示移动

lcd_write_com_busy(0x01)//显示清屏:1,数据指针清零 2,所有显示清零

lcd_write_com_busy(0x80)//80h+地址码(0-27h,40h-67h) 设置数据地址指针

for(num=0num<16num++)

{

lcd_write_data(table_1[num])

delay(5)

}

lcd_write_com_busy(0x80+0x40)

}

void key_wdat(uchar i) //按键写数据

{

// dula=0

// wela=0

// lcden=0

//液晶初始化指令

// write_com(0x38)//设置16*2显示,5*7点阵,8位数据接口

// write_com(0x0d)//关显示 显示光标 光标闪烁

// write_com(0x06)//当读或写一个字符后地址指针加一,且光标加一,写一个字符,整屏显示移动

// write_com(0x01)//显示清屏:1,数据指针清零 2,所有显示清零

// write_com(0x80+0x40)//80h+地址码(0-27h,40h-67h) 设置数据地址指针

lcd_wait_busy()

lcd_write_data(i)

delay(100)

}

// 删除液晶第1或2行全部数据

void clear(uchar t)

{

if(t==1)

{

lcd_write_com_busy(0x80)

}

if(t==2)

{

lcd_write_com_busy(0x80+0x40)

}

for(i=0i<15i++)

{

lcd_write_data(dis_tab[16])

}

lcd_write_com_busy(0x80+0x40)

}

// 产品显示函数 待写 如何从键盘输入中提取出三位的产品号码???????????????????

/*

void display_product()

{

}

*/

// 4*4矩阵键盘检测

void keyscan()

{

lcden=1//???

//

P3=0xfe

temp=P3

temp=temp&0xf0

while(temp!=0xf0)

{

delay(5)

temp=P3

temp=temp&0xf0

while(temp!=0xf0)

{

temp=P3

switch(temp)

{

case 0xee:key_wdat(dis_tab[7])beep() // 7

break

case 0xde:key_wdat(dis_tab[8])beep() // 8

break

case 0xbe:key_wdat(dis_tab[9])beep() // 9

break

case 0x7e:key_wdat(dis_tab[17])beep() //

break

}

while(temp!=0xf0)

{

temp=P3

temp=temp&0xf0

}

}

}

//

P3=0xfd

temp=P3

temp=temp&0xf0

while(temp!=0xf0)

{

delay(5)

temp=P3

temp=temp&0xf0

while(temp!=0xf0)

{

temp=P3

switch(temp)

{

case 0xed:key_wdat(dis_tab[4])beep() // 4

break

case 0xdd:key_wdat(dis_tab[5])beep() // 5

break

case 0xbd:key_wdat(dis_tab[6])beep() // 6

break

case 0x7d:key_wdat(dis_tab[17])beep() //

break

}

while(temp!=0xf0)

{

temp=P3

temp=temp&0xf0

}

}

}

//

P3=0xfb

temp=P3

temp=temp&0xf0

while(temp!=0xf0)

{

delay(5)

temp=P3

temp=temp&0xf0

while(temp!=0xf0)

{

temp=P3

switch(temp)

{

case 0xeb:key_wdat(dis_tab[1])beep() // 1

break

case 0xdb:key_wdat(dis_tab[2])beep() // 2

break

case 0xbb:key_wdat(dis_tab[3])beep() // 3

break

case 0x7b:key_wdat(dis_tab[17])beep() //

break

}

while(temp!=0xf0)

{

temp=P3

temp=temp&0xf0

}

}

}

//

P3=0xf7

temp=P3

temp=temp&0xf0

while(temp!=0xf0)

{

delay(5)

temp=P3

temp=temp&0xf0

while(temp!=0xf0)

{

temp=P3

switch(temp)

{

case 0xe7:key_wdat(dis_tab[0])beep() // 0

break

case 0xd7:key_wdat(dis_tab[17])beep() //

break

case 0xb7:clear(2)beep() // 删除液晶第二行

break

case 0x77:beep() // enter

break

}

while(temp!=0xf0)

{

temp=P3

temp=temp&0xf0

}

}

}

}

//

void main()

{

lcd_init()

while(1)

{

keyscan()

}

while(1)

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12456731.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-25
下一篇 2023-05-25

发表评论

登录后才能评论

评论列表(0条)

保存