(单片机学习 之一)
最近开始学习MCS51单片机,这是自己编的首个程序,如有什么错误,请各位大侠帮忙指正,谢谢!!!
扫描原理如下:
1. 判断是否有键按下:高四位高电平扫描,假设送端口数据0xf0,延迟一段时间,再读取该端口数据,与原数据0xf0相异或,如果不等于零则说明有键按下。
2. 通过扫描程序(列扫描)得出其键号:扫描第一列首先给出扫描信号如0xfe, 依次判断第一行,第二行,第三行,第四行是否为零;扫描完一列后继续下一列。
C语言程序:
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define LED P0
#define Key_num() (~P3)&0x0f //读入P3低四位数
void Delay(uint count); //数码管显示
uint KEY_IF(void); //判断有无键按下
uint KEY_NUM(void); //计算按键号
void LED_DIS(uint num) ; // 显示
const uchar Seg_led[]={ 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,
0x77,0x7c,0x39,0x5E,0x79,0x71,0x40};
//七段SEG位码 0~16,按键错误显示负号
void main (void)
{
uint k_num=8;
LED_DIS(k_num);
while(1)
{
if(KEY_IF())
{
Delay(2);
if(KEY_IF()) // 是否真的按下
{
k_num=KEY_NUM();
LED_DIS(k_num);
while(Key_num()!=0); // 按键是否已释放
Delay(2); // 延时消抖
}
}
}
}
uint KEY_IF(void)
{
P3=0xf0;
Delay(2);
while(1)
{
if(P3== 0xf0)
continue;
else
return 1;
}
}
uint KEY_NUM(void)
{
uchar col,row; // 行号与列号
uint scan,keyin,kcode; // kcode记录键号
scan = 0xef; // 扫描码
for(col=0;col < 4 ; col ++)
{
P3 = scan;
keyin = Key_num();
if(keyin != 0)
{
for (row=0;row<4;row++)
{
if(keyin == (0x01<<row))
{
kcode = row + 4*col;
return kcode;
}
}
if(row == 4)
return 16; // 按键错误,数码管显示负号
}
scan = (scan<<1)|0x01; // 扫描码移位
}
}
void LED_DIS(uint num)
{
LED = Seg_led[num] ;
}
void Delay(uint count)
{
unsigned char i,j,k;
for(;count-->0;)
for(i=5;i>0;i--)
for(j=4;j>0;j--)
for(k=10;k>0;k--);
}
汇编程序如下:
ORG 00H
START:
MOV R0,#0FEH ;R0扫描值
MOV R1,#00H ;R1记录列号
MOV DPTR,#D_SEG
LCALL IF_KEY
JZ START
LCALL DELAY10MS
LCALL IF_KEY
JZ START
KEY_NUM:
MOV A,#0FFH
MOV P3,A
MOV A,R0
MOV P3,A
LCALL DELAY10MS
MOV A,P3
JB ACC.4,LONE
MOV A,#0 ;行值
ADD A,R1
MOV R2,A
AJMP DISPLAY
LONE:
JB ACC.5,LTWO
MOV A,#4 ;行值
ADD A,R1
MOV R2,A
AJMP DISPLAY
LTWO:
JB ACC.6,LTHR
MOV A,#8 ;行值
ADD A,R1
MOV R2,A
AJMP DISPLAY
LTHR:
JB ACC.7,NEXT_COL
MOV A,#0CH ;行值
ADD A,R1
MOV R2,A
AJMP DISPLAY
NEXT_COL:
INC R1 ;列值加一
MOV A,R0
JNB ACC.3,START
RL A
MOV R0,A
AJMP KEY_NUM
IF_KEY:
MOV A,#0FFH
MOV P3,A
ANL A,#0F0H
MOV P3,A
LCALL DELAY10MS
MOV A,P3
XRL A,#0F0H
RET
DELAY10MS:
MOV R7,#40
D0:
MOV R6,#250
DJNZ R6,$
DJNZ R7,D0
RET
DISPLAY:
MOV A,R2
MOVC A,@A+DPTR
MOV P0,A
AJMP START
D_SEG:
DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H
DB 7FH,6FH,77H,7CH,39H,5EH,79H,71H
RET
END
文章评论(0条评论)
登录后参与讨论