最新51单片机键盘设置汇总

最新51单片机键盘设置汇总
最新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.0

S2 P1.1

……………………….

S8 P1.7

软件:

START: MOV P1,#0FFH ;置P1口为高电平

JNB P1.0, RS1 ; S1按下,程序去执行RS1

JNB P1.1, RS2 ; S2按下,程序去执行RS2

JNB P1.2, RS3 ; S3按下,程序去执行RS3

JNB P1.3, RS4 ; S4按下,程序去执行RS4

JNB P1.4, RS5 ; S5按下,程序去执行RS5

JNB P1.5, RS6 ; S6按下,程序去执行RS6

JNB P1.6, RS7 ; S7按下,程序去执行RS7

JNB P1.7, RS8 ; S8按下,程序去执行RS8

AJMP 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口空闲的场合。

三、行列式非编码键盘接口方法

按键较多时,一般采用行列式键盘.

采用扫描方式,软件扫描方式有三种:

程序扫描方式: 当CPU空闲时,扫描键盘,判断有无键按下.

定时扫描方式: 利用CPU的定时器,每隔一定时间扫描一次键盘.

中断扫描方式: 在硬件上采用中断,有键按下时,产生中断,

由中断服务程序来处理.

下面是16个按键,构成的4×4键盘

行线: 四根,接P1.0---P1.3

列线: 四根,接P1.4---P1.7

程序扫描法原理:

P1.0---P1.3输出低电平,读P1.4—P1.7,

若全为1,无键按下

若不全为1,有键按下

②在有键按下的情况下,进一步判断是那个键按下

使P1.0---P1.3依次输出低电平,读P1.4----P1.7

判断有无键按下子程序, 程序名: KAP键盘查询子程序

KAP: MOV P1,#0F0H ;行线输出低电平,列线输出高电平MOV A,P1 ;P1口读入A

CPL A ;取反

ANL A,#0F0H ;取高四位,即P1.4---P1.7

RET

程序出口: A=0, 则无键按下.

A≠0 则有键按下.

去抖动-----------延时10ms子程序: 程序名D10MS

D10MS: MOV R6, #14H;

DL: MOV R7,#0FFH;

DJNZ R7,$

DJNZ R6,DL

RET

KINP: LCALL KAP ; 调键盘查询子程序,

JNZ KP1 ; A≠0,有键按下

SJMP END_KINP ; A=0,无键按下,退出按键查询程序

KP1: LCALL D10MS ;延时10MS,去抖动

LCALL KAP ;再次查询键盘,

JNZ KP2 ; A≠0,确认有键按下

SJMP END_KINP ; A=0,误操作,重新查询

KP2为取键值子程序

KP2: MOV R2, #0FEH ; R2为行扫描值

MOV R4, #00H ; R4初值为第0行行首键号

CLR F0 ; F0=0表示正在扫描键盘

KP4: MOV P1, R2 ; 扫描行为低

MOV A, P1 ;读P1

JB ACC.4, L1 ;第0列不为低,则检查第1列

MOV A, #00H ; 为低,则行首键值送入A

AJMP KP5 ; KP5 L1: JB ACC.5, L2 ; 检查第一列

MOV A, #04H ;第一列行首键值送入A

AJMP KP5

L2: JB ACC.6 , L3 ; 检查第二列

MOV A, #08H ;第二列行首键值送入A

AJMP KP5

L3: JB ACC.7 , NEXT ;检查第三列,若为1,则检查下一行

MOV A, #0CH ; 第三列行首键值送入A

KP5: ADD A , R4 ; A A+R4,键值调整

PUSH A ; KP3: LCALL D10MS ; 后沿去抖动

LCALL KAP ;查询按键是否释放

JNZ KP3 ; A≠0 未释放,继续查询

POP A ;键已释放,弹出键值

RET

NEXT: INC R4 ; 下一列,行键值加1

MOV A , R2 ; 取扫描值

JNB ACC.3, END_KINP ; 判断扫描是否结束?

RL A ; 下一个扫描值

MOV R2, A ;

AJMP KP4 ;

END_KINP: SETB F0

RET

51单片机电子日历(电子时钟)程序

2007-08-03 21:01:05| 分类:默认分类|字号订阅

程序代码:

/****************************************************************************/

/* 电子日历,有时间显示、闹铃、日期、秒表及键盘设置功能 */

/* 功能键A: 设置位数字+1 闹钟模式下为闹钟开关秒表模式下为记时开关 */

/* 功能键B: 设置位数字-1 闹钟模式下为闹钟开关 */

/* 功能键C:设置模式及设置位选择秒表模式下为清零

键 */

/* 功能键D:在四种工作模式下切换设置闹钟开关 */

/****************************************************************************/

#include

#include

/***************这里设置程序初始化时显示的时间****************/

#define SET_HOUR 12 /*设置初始化小时*/

#define SET_MINUTE 00 /*设置初始化分钟*/

#define SET_SECOND 00 /*设置初始化秒数*/

/*************************系统地址****************************/

#define BASE_PORT 0x8000 /*选通基地址*/

#define KEY_LINE BASE_PORT+1 /*键盘行线地址*/

#define KEY_COLUMN BASE_PORT+2 /*键盘列线地址*/

#define LED_SEG BASE_PORT+4 /*数码管段选地址*/

#define LED_BIT BASE_PORT+2 /*数码管位选地址*/

#define LED_ON(x) XBYTE[LED_BIT]=(0x01< #define LED_OFF XBYTE[LED_SEG]=0x00 /*LED显示空*/

/**************在设置模式下对秒分时的宏定义*****************/

#define SECOND 0 /*对应数码管右边两位*/

#define MINUTE 1 /*对应数码管中间两位*/

#define HOUR 2 /*对应数码管左边两位*/

/********************定义四种工作模式***********************/

#define CLOCK clockstr /*时钟模式*/

#define ALART alartstr /*闹钟模式*/

#define DATE datestr /*日期模式*/

#define TIMER timerstr /*秒表模式*/

/****************以下是所有子函数的声明*********************/

void sys_init(void); /*系统的初始化程序*/

void display(void); /*动态刷新一次数码管子程序*/

void clockplus(void); /*时间加1S的子程序*/

void update_clockstr(void); /*更新时间显示编码*/

void update_alartstr(void); /*更新闹钟时间的显示编码*/

void update_datestr(void); /*更新日期显示编码*/

void update_timerstr(void); /*更新秒表时间的显示编码*/

void deley(int); /*延时子程序*/

void update_dispbuf(unsigned char *); /*更新显示缓冲区*/

unsigned char getkeycode(void); /*获取键值子程序*/

void keyprocess(unsigned char); /*键值处理子程序*/

unsigned char getmonthdays(unsigned int,unsigned char);/*计算某月的天数子程序*/ /*功能键功能子函数*/

void Akey(void); /*当前设置位+1 开关闹钟开关秒表*/

void Bkey(void); /*当前设置位-1 开关闹钟 */

void Ckey(void); /*设置位选择秒表清零*/

void Dkey(void); /*切换四种工作模式*/

/**********************全局变量声明部分*********************/

unsigned char led[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};/*从0~9的LED编码*/

unsigned char ledchar[3]={0x5c,0x54,0x71};/*o n f*/

//unsigned char key[24]={ /* 键值代码数组对应键位:*/

// 0x70,0x71,0x72,0x73,0x74,0x75, /* 7 8 9 A TRACE RESET*/

// 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5, /* 4 5 6 B STEP MON */

// 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5, /* 1 2 3 C HERE LAST */

// 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5}; /* 0 F E D EXEC NEXT */

struct{ /*时间结构体变量*/

unsigned char s;

unsigned char m;

unsigned char h;

}clock={SET_SECOND,SET_MINUTE,SET_HOUR};

struct{ /*闹铃时间结构体变量*/

unsigned char m;

unsigned char h;

}alart={SET_MINUTE,SET_HOUR};

struct{ /*日期结构体变量*/

unsigned int year;

unsigned char month;

unsigned char day;

}date={6,1,1};

struct{ /*秒表时间结构体变量*/

unsigned char ms;

unsigned char s;

unsigned char m;

}timer={0,0,0};

unsigned char dispbuf[6]; /*显示缓冲区数组*/

unsigned char clockstr[6]; /*时间显示的数码管编码数组*/

unsigned char alartstr[6]; /*闹钟显示的数码管编码数组*/

unsigned char datestr[6]; /*日期显示的数码管编码数组*/

unsigned char timerstr[6]; /*秒表显示的数码管编码数组*/

unsigned int itime=0,idot; /*定时器0中断计数*/

unsigned char itime1=0; /*定时器1中断计数*/

sbit P3_1=P3^1; /*外接蜂鸣器的管脚*/

bdata bit IsSet=0; /*设置模式标志位0:正常走时1:设置模式*/

bdata bit Alart_EN=0; /*闹铃功能允许位0:禁止闹铃1:允许闹铃*/

bdata bit IsBeep=0; /*响铃标志位0:未响铃1:正在响铃*/

unsigned char SetSelect=0; /*在设置模式IsSet=1时,正在被设置的位,对应上面的宏*/

unsigned char *CurrentMode; /*标志当前正设置的功能,如CurrentMode=CLOCK或CurrentMode=ALART等*/

void timerplus(void);

/**************************函数部分*************************/

void main(void)

{

sys_init();

while(1)

{

XBYTE[KEY_COLUMN,0x00]; /*给键盘列线赋全零扫描码,判断是否有键按下 */

while((XBYTE[KEY_LINE]&0x0f)==0x0f) /*检测是否有键按下,无则一直进行LED 的刷新显示*/

{

if(Alart_EN&&(clock.h==alart.h)&&(clock.m==alart.m)) {IsBeep=1;}

else

{ IsBeep=0;

P3_1=0;}

display();

}

keyprocess(getkeycode()); /*有键按下时得到键值,并送入键值处理程序*/

display(); /*可要可不要*/

}

}

void sys_init(void)

{

TMOD=0x22; /*定时器0和1都设置为工作方式2,基准定时250×2=

500us=0.5ms*/

TH0=6; /*定时器0中断服务用来产生1秒时钟定时及闹钟蜂鸣器蜂鸣脉冲*/ TL0=6; /*定时器1中断服务留给秒表使用,产生1/100秒定时*/

TH1=6;

TL1=6;

ET0=1;

ET1=1;

EA=1;

TR0=1;

update_clockstr(); /*初始化时钟显示编码数组*/

update_alartstr(); /*初始化闹钟显示编码数组*/

update_datestr(); /*初始化日期显示编码数组*/

update_timerstr(); /*初始化秒表显示编码数组*/

update_dispbuf(clockstr);/*初始化显示缓冲数组*/

CurrentMode=CLOCK; /*默认的显示摸式为时钟*/

P3_1=0; /*蜂鸣器接线引脚复位*/

}

void timer0(void) interrupt 1 using 1 /*定时器0中断服务器,用来产生1秒定时*/

{

itime++;

if(itime==1000)

{

if(IsSet) /*在设置模式下,对正在设置的位闪烁显示*/

{

dispbuf[SetSelect*2]=0; /*对正在设置的位所对应的显示缓冲区元素赋0,使LED灭*/

dispbuf[SetSelect*2+1]=0;

}

if(IsBeep) P3_1=!P3_1; /*闹钟模式时,产生峰鸣器响脉冲*/

if(CurrentMode==CLOCK)

相关主题
相关文档
最新文档