附注:
原理图各接口连接关系可参考代码中的端口定义;
P0口数据锁存器为两片74HC573芯片;
1.对独立键盘的检测
/*--------------------------
功能:用数码管实现60s计时器
上电时,数码管显示00
key4控制开始/暂停计时
暂停状态下,key1进行加1操作
key2进行减1操作
key3进行清零操作
---------------------------
Author: Zhang Kaizhou
Date: 2019-5-19 19:14:20
--------------------------*/
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit key1 = P3^4;
sbit key2 = P3^5;
sbit key3 = P3^6;
sbit key4 = P3^7;
sbit wei_address = P2^7;
sbit duan_address = P2^6;
uchar code table[] = {0x3f, 0x06, 0x5b, 0x4f,
0x66, 0x6d, 0x7d, 0x07,
0x7f, 0x6f, 0x77, 0x7c,
0x39, 0x5e, 0x79, 0x71}; // 定义一个无符号字符型数组table[],存放在单片机内部的ROM或Flash中
uchar n1 = 0, n2 = 0;
void init();
void display(uchar num);
void keyScan();
void delay(uchar xms);
void main()
{
init();
while(1)
{
keyScan();
display(n1);
}
}
/*初始化函数*/
void init()
{
TMOD = 0x01; // 定时器0,方式1
TH0 = (65536 - 45872) / 256; // 定时50ms
TL0 = (65536 - 45872) % 256;
EA = 1; // 开全局中断
ET0 = 1; // 开定时器0溢出中断
}
/*定时器0中断服务程序*/
void T0_interrupt() interrupt 1
{
TH0 = (65536 - 45872) / 256; // 定时器0重装初值
TL0 = (65536 - 45872) % 256;
n2++;
if(n2 == 20) // 定时到1s
{
n2 = 0;
n1++;
if(n1 == 60)
{
n1 = 0;
}
}
}
/*数码管显示函数*/
void display(uchar num)
{
uchar shi, ge;
shi = num / 10;
ge = num % 10;
duan_address = 1; // 在数码管上显示十位的数字
P0 = table[shi];
duan_address = 0;
P0 = 0xff;
wei_address = 1;
P0 = 0xfe;
wei_address = 0;
delay(5);
duan_address = 1; // 在数码管上显示个位的数字
P0 = table[ge];
duan_address = 0;
P0 = 0xff;
wei_address = 1;
P0 = 0xfd;
wei_address = 0;
delay(5);
}
/*键盘扫描函数*/
void keyScan()
{
if(!key1) // key1按下,加1
{
delay(10);
if(!key1)
{
n1++;
if(n1 == 60)
{
n1 = 0;
}
while(!key1);
}
}
if(!key2) // key2按下,减1
{
delay(10);
if(!key2)
{
if(!n1)
{
n1 = 60;
}
n1--;
while(!key2);
}
}
if(!key3) // key4按下,暂停或开始定时器0
{
delay(10);
if(!key3)
{
n1 = 0;
while(!key3);
}
}
if(!key4)
{
delay(10);
if(!key4)
{
while(!key4);
TR0 = ~TR0;
}
}
}
/*延时函数*/
void delay(uchar xms)
{
uchar i, j;
for(i = 0; i < xms; i++)
for(j = 0; j < 110; j++);
}
2.对矩阵键盘进行扫描
/*------------------------
功能:扫描4x4矩阵键盘
Author: Zhang Kaizhou
Date: 2019-5-21 21:37:31
-------------------------*/
#include <reg52.h>
#define uchar unsigned char
sbit wei_address = P2^7;
sbit duan_address = P2^6;
uchar code table[] = {0x3f, 0x06, 0x5b, 0x4f,
0x66, 0x6d, 0x7d, 0x07,
0x7f, 0x6f, 0x77, 0x7c,
0x39, 0x5e, 0x79, 0x71}; // 定义一个无符号字符型数组table[],存放在单片机内部的ROM或Flash中
uchar buffer, key;
void init_digitron();
void array_scan_oneline(uchar address);
void array_scan();
void display(uchar key);
void delay(uchar xms);
void main()
{
init_digitron(); // 初始化数码管
while(1) // 循环逐行扫描按键是否按下
{
array_scan();
}
}
/*数码管初始化函数*/
void init_digitron()
{
P0 = 0; // 关闭所有数码管
duan_address = 1;
duan_address = 0;
P0 = 0x00; // 选中所有数码管
wei_address = 1;
wei_address = 0;
}
/*矩阵键盘扫描函数*/
void array_scan()
{
array_scan_oneline(0xfe);
array_scan_oneline(0xfd);
array_scan_oneline(0xfb);
array_scan_oneline(0xf7);
}
/*矩阵键盘扫描一行的函数*/
void array_scan_oneline(uchar address)
{
P3 = address;
buffer = P3;
buffer = buffer & 0xf0;
if(buffer != 0xf0) // 有键按下
{
delay(10); // 消抖
buffer = P3;
buffer = buffer & 0xf0;
if(buffer != 0xf0)
{
buffer = P3;
switch(buffer)
{
case 0xee: key = 0; break;
case 0xde: key = 1; break;
case 0xbe: key = 2; break;
case 0x7e: key = 3; break;
case 0xed: key = 4; break;
case 0xdd: key = 5; break;
case 0xbd: key = 6; break;
case 0x7d: key = 7; break;
case 0xeb: key = 8; break;
case 0xdb: key = 9; break;
case 0xbb: key = 10; break;
case 0x7b: key = 11; break;
case 0xe7: key = 12; break;
case 0xd7: key = 13; break;
case 0xb7: key = 14; break;
case 0x77: key = 15; break;
}
while(buffer != 0xf0) // 等待按键释放
{
buffer = P3;
buffer = buffer & 0xf0;
}
display(key);
}
}
}
/*延时函数*/
void delay(uchar xms)
{
uchar i, j;
for(i = 0; i < xms; i++)
for(j = 0; j < 110; j++);
}
/*数码管显示函数*/
void display(uchar key)
{
P0 = table[key];
duan_address = 1;
duan_address = 0;
}