stc89c52rc是stc公司生产的一种低功耗、高性能cmos8位微控制器,具有8k字节系统可编程flash存储器。stc89c52使用经典的mcs-51内核,但是做了很多的改进使得芯片具有传统51单片机不具备的功能。在单芯片上,拥有灵巧的8 位cpu 和在系统可编程flash,使得stc89c52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。
stc52单片机键盘原理图
说明:
1. 独立键盘部分
s2~s5为4个独立键盘, 与单片机的p3.4~p3.7分别相连
2. 矩阵键盘部分
s6~s21为16个矩阵键盘,8条线分别与单片机的p3口相连, 其中矩阵键盘的4行分别与单片机的p3.0~p3.3相连,矩阵键盘的4列分别与单片机的p3.4~p3.7相连。
程序设计详解
1. 用数码管的前两位显示一个十进制数,变化范围为00-59.
程序功能:
用数码管的前两位显示一个十进制数,变化范围为00-59,开始时显示00,每按下s2键一次,数值加1;每按下s3键一次,数值减1;每按下s4键一次,数值归零;按下s5键一次,利用定时器功能使数值开始每秒加1,再次按下s5键,数值停止自动加1,保持原数。
程序源码:
#include
#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 dula = p2 ^ 6;
sbit wela = p2 ^ 7;
uchar code table[] = {
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
void init();
void keyscan();
void display(uchar);
void delayms(uint);
uchar t0, num;
void main()
{
init();
while (1)
{
keyscan();
display(num);
}
}
void init()
{
tmod = 0x01;
th0 = (65536 - 45872) / 256;
tl0 = (65536 - 45872) % 256;
ea = 1;
et0 = 1;
}
void keyscan()
{
if (key1 == 0)
{
delayms(10);
if (key1 == 0)
{
if (num == 60)
num = 0;
num++;
while (!key1)
display(num);
}
}
if (key2 == 0)
{
delayms(10);
if (key2 == 0)
{
if (num == 0)
num = 60;
num--;
while (!key2)
display(num);
}
}
if (key3 == 0)
{
delayms(10);
if (key3 == 0)
{
num = 0;
while (!key3)
display(num);
}
}
if (key4 == 0)
{
delayms(10);
if (key4 == 0)
{
tr0 = ~tr0;
while (!key4)
display(num);
}
}
}
void display(uchar numdis)
{
dula = 1;
p0 = table[numdis / 10];
dula = 0;
p0 = 0xff;
wela = 1;
p0 = 0xfe;
wela = 0;
delayms(5);
dula = 1;
p0 = table[numdis % 10];
dula = 0;
p0 = 0xff;
wela = 1;
p0 = 0xfd;
wela = 0;
delayms(5);
}
void delayms(uint xms)
{
uint i, j;
for (i = xms; i 》 0; i--)
for (j = 110; j 》 0; j--)
;
}
void t0_timer() interrupt 1
{
th0 = (65536 - 45872) / 256;
tl0 = (65536 - 45872) % 256;
t0++;
if (t0 == 20)
{
t0 = 0;
num++;
if (num == 60)
num = 0;
}
}
程序小结:
a. 键盘按键检测需要做两次 (每个键盘按键用了两个if)
b. 键盘按键退出也需要检测 (每次按键退出用了一个while(!key))
c. 这段程序包含按键加1,按键减1,按键归零,按键开始计数,再按停止计数
2. 按矩阵键盘,在数码管上显示0~f,6个数码管同时静态显示即可。
程序功能
上电不显示, 按矩阵键盘,在数码管上显示0~f,6个数码管同时静态显示即可。
程序源码
#include
#define uchar unsigned char
#define uint unsigned int
sbit dula = p2 ^ 6;
sbit wela = p2 ^ 7;
uchar code table[] = {
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
void delayms(uint);
void display(uchar);
void matrixkeyscan();
void main()
{
dula = 1;
p0 = 0;
dula = 0;
wela = 1;
p0 = 0xc0;
wela = 0;
while (1)
{
matrixkeyscan();
}
}
void delayms(uint xms)
{
uint i, j;
for (i = xms; i 》 0; i--)
for (j = 110; j 》 0; j--)
;
}
void display(uchar num)
{
dula = 1;
p0 = table[num];
dula = 0;
}
void matrixkeyscan()
{
uchar temp, key;
p3 = 0xfe;
temp = p3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
delayms(10);
temp = p3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
temp = p3;
switch(temp)
{
case 0xee:
key = 0;
break;
case 0xde:
key = 1;
break;
case 0xbe:
key = 2;
break;
case 0x7e:
key = 3;
break;
}
while (temp != 0xf0)
{
temp = p3;
temp = temp & 0xf0;
}
display(key);
}
}
p3 = 0xfd;
temp = p3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
delayms(10);
temp = p3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
temp = p3;
switch(temp)
{
case 0xed:
key = 4;
break;
case 0xdd:
key = 5;
break;
case 0xbd:
key = 6;
break;
case 0x7d:
key = 7;
break;
}
while (temp != 0xf0)
{
temp = p3;
temp = temp & 0xf0;
}
display(key);
}
}
p3 = 0xfb;
temp = p3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
delayms(10);
temp = p3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
temp = p3;
switch(temp)
{
case 0xeb:
key = 8;
break;
case 0xdb:
key = 9;
break;
case 0xbb:
key = 10;
break;
case 0x7b:
key = 11;
break;
}
while (temp != 0xf0)
{
temp = p3;
temp = temp & 0xf0;
}
display(key);
}
}
p3 = 0xf7;
temp = p3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
delayms(10);
temp = p3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
temp = p3;
switch(temp)
{
case 0xe7:
key = 12;
break;
case 0xd7:
key = 13;
break;
case 0xb7:
key = 14;
break;
case 0x77:
key = 15;
break;
}
while (temp != 0xf0)
{
temp = p3;
temp = temp & 0xf0;
}
display(key);
}
}
}
程序小结
a. 先送行线低电平,检测列线信号
b. 通过延时来消抖
c. 需要检查释放
3. 数码管前三位显示一个跑表,从000到999之间以1%秒速度运行
程序功能
当按下一个独立键盘时跑表停止,松开手后跑表继续运行。用定时器设计表。
程序源码
#include
#define uint unsigned int
#define uchar unsigned char
sbit dula = p2 ^ 6;
sbit wela = p2 ^ 7;
sbit s2 = p3 ^ 4;
uchar code table[] = {
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,
0x76,0x79,0x38,0x3f,0
};
uchar flag, t0, bai, shi, ge;
uint shu;
void init();
void display(uchar aa, uchar bb, uchar cc);
void delayms(uint);
void main()
{
init();
while (1)
{
display(bai, shi, ge);
if (s2 == 0)
{
delayms(10);
if (s2 == 0)
{
tr0 = 0;
while (!s2)
display(bai, shi, ge);
tr0 = 1;
}
}
}
}
void init()
{
tmod = 0x01;
th0 = (65536 - 10000) / 256;
tl0 = (65536 - 10000) % 256;
ea = 1;
et0 = 1;
tr0 = 1;
}
void t0_timer() interrupt 1
{
th0 = (65536 - 10000) / 256;
tl0 = (65536 - 10000) % 256;
t0++;
if (t0 == 1)
{
t0 = 0;
shu++;
if (shu == 1000)
shu = 0;
bai = shu / 100;
shi = shu % 100 / 10;
ge = shu % 10;
}
}
void display(uchar aa, uchar bb, uchar cc)
{
dula = 1;
p0 = table[aa];
dula = 0;
p0 = 0xff;
wela = 1;
p0 = 0xfe;
wela = 0;
delayms(1);
dula = 1;
p0 = table[bb];
dula = 0;
p0 = 0xff;
wela = 1;
p0 = 0xfd;
wela = 0;
delayms(1);
dula = 1;
p0 = table[cc];
dula = 0;
p0 = 0xff;
wela = 1;
p0 = 0xfb;
wela = 0;
delayms(1);
}
void delayms(uint xms)
{
uint i, j;
for (i = xms; i 》 0; i--)
for (j = 110; j 》 0; j--)
;
}
程序小结
a. 松开检测 while (!s2)
b. 1%秒速度运行: 选择定时基数为1000(即10ms), 定时倍数为1,相乘为10ms
说明: 由于间隔时间太短,所以这里出现的问题是低位数据显示看不清楚,可以选用定时倍数为10 (但定时数变成了100ms, 可能与题意不符)
4. 数码管前三位显示一个跑表,从000到999之间以1%秒速度运行
程序功能
当按下第一个独立键盘时跑表停止,松开手后跑表继续运行。
当按下第二个独立键盘时计时停止,
当按下第三个独立键盘时计时开始,
当按下第三个独立键盘时计数值清零从头开始
程序源码
#include
#define uint unsigned int
#define uchar unsigned char
sbit dula = p2 ^ 6;
sbit wela = p2 ^ 7;
sbit s2 = p3 ^ 4;
sbit s3 = p3 ^ 5;
sbit s4 = p3 ^ 6;
sbit s5 = p3 ^ 7;
uchar code table[] = {
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,
0x76,0x79,0x38,0x3f,0
};
uchar flag, t0;
uint shu;
void init();
void display(uint num);
void delayms(uint);
void keyscan();
void main()
{
init();
while (1)
{
display(shu);
keyscan();
}
}
void init()
{
tmod = 0x01;
th0 = (65536 - 10000) / 256;
tl0 = (65536 - 10000) % 256;
ea = 1;
et0 = 1;
tr0 = 1;
}
void keyscan()
{
if (s2 == 0)
{
delayms(10);
if (s2 == 0)
{
tr0 = 0;
while (!s2)
display(shu);
tr0 = 1;
}
}
if (s3 == 0)
{
delayms(10);
if (s3 == 0)
{
tr0 = 0;
while (!s3)
display(shu);
}
}
if (s4 == 0)
{
delayms(10);
if (s4 == 0)
{
tr0 = 1;
while (!s4)
display(shu);
}
}
if (s5 == 0)
{
delayms(10);
if (s5 == 0)
{
shu = 0;
while (!s5)
display(shu);
}
}
}
void t0_timer() interrupt 1
{
th0 = (65536 - 10000) / 256;
tl0 = (65536 - 10000) % 256;
t0++;
if (t0 == 1)
{
t0 = 0;
shu++;
if (shu == 1000)
shu = 0;
}
}
void display(uint num)
{
dula = 1;
p0 = table[num / 100];
dula = 0;
p0 = 0xff;
wela = 1;
p0 = 0xfe;
wela = 0;
delayms(1);
dula = 1;
p0 = table[num % 100 / 10];
dula = 0;
p0 = 0xff;
wela = 1;
p0 = 0xfd;
wela = 0;
delayms(1);
dula = 1;
p0 = table[num % 100 % 10];
dula = 0;
p0 = 0xff;
wela = 1;
p0 = 0xfb;
wela = 0;
delayms(1);
}
void delayms(uint xms)
{
uint i, j;
for (i = xms; i 》 0; i--)
for (j = 110; j 》 0; j--)
;
}
程序小结
1. 按键退出检测时需要加上display(shu), 否则数码管显示前两位为空白
2. 按键退出检测与执行动作的顺序问题
1) 如果要求一按键马上执行动作, 应该时先执行动作,再做按键退出检测
即如:
shu = 0;
while (!s5)
display(shu);
2) 如果要求按键退出后再执行动作, 应该时先检查按键退出,再执行动作
即如:
while (!s5)
display(shu);
shu = 0;
5. 按下16个矩阵键盘,依次在前三个数码管上显示1~16的平方
程序功能
按下16个矩阵键盘,依次在前三个数码管上显示1~16的平方,即按下第一个显示1,按下第二个显示4,…按下第16个显示16*16 (256)
程序源码
#include
#define uchar unsigned char
#define uint unsigned int
sbit dula = p2 ^ 6;
sbit wela = p2 ^ 7;
uchar code table[] = {
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
void delayms(uint);
void display(uint);
void matrixkeyscan();
void main()
{
while (1)
{
matrixkeyscan();
}
}
void delayms(uint xms)
{
uint i, j;
for (i = xms; i 》 0; i--)
for (j = 110; j 》 0; j--)
;
}
void display(uint num)
{
dula = 1;
p0 = table[num / 100];
dula = 0;
p0 = 0xff;
wela = 1;
p0 = 0xfe;
wela = 0;
delayms(1);
dula = 1;
p0 = table[num % 100 / 10];
dula = 0;
p0 = 0xff;
wela = 1;
p0 = 0xfd;
wela = 0;
delayms(1);
dula = 1;
p0 = table[num % 100 % 10];
dula = 0;
p0 = 0xff;
wela = 1;
p0 = 0xfb;
wela = 0;
delayms(1);
}
void matrixkeyscan()
{
uchar temp, key;
p3 = 0xfe;
temp = p3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
delayms(10);
temp = p3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
temp = p3;
switch(temp)
{
case 0xee:
key = 1;
break;
case 0xde:
key = 2;
break;
case 0xbe:
key = 3;
break;
case 0x7e:
key = 4;
break;
}
while (temp != 0xf0)
{
temp = p3;
temp = temp & 0xf0;
}
}
}
p3 = 0xfd;
temp = p3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
delayms(10);
temp = p3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
temp = p3;
switch(temp)
{
case 0xed:
key = 5;
break;
case 0xdd:
key = 6;
break;
case 0xbd:
key = 7;
break;
case 0x7d:
key = 8;
break;
}
while (temp != 0xf0)
{
temp = p3;
temp = temp & 0xf0;
}
}
}
p3 = 0xfb;
temp = p3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
delayms(10);
temp = p3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
temp = p3;
switch(temp)
{
case 0xeb:
key = 9;
break;
case 0xdb:
key = 10;
break;
case 0xbb:
key = 11;
break;
case 0x7b:
key = 12;
break;
}
while (temp != 0xf0)
{
temp = p3;
temp = temp & 0xf0;
}
}
}
p3 = 0xf7;
temp = p3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
delayms(10);
temp = p3;
temp = temp & 0xf0;
if (temp != 0xf0)
{
temp = p3;
switch(temp)
{
case 0xe7:
key = 13;
break;
case 0xd7:
key = 14;
break;
case 0xb7:
key = 15;
break;
case 0x77:
key = 16;
break;
}
while (temp != 0xf0)
{
temp = p3;
temp = temp & 0xf0;
}
}
}
display(key * key);
}
程序小结
1. display(key * key)不能马上放到每一个按键退出检测后,如果那样做,数码管上只会显示最后一位数字(即个位)
换句话说,
程序不能这样:
while (temp != 0xf0)
{
temp = p3;
temp = temp & 0xf0;
}
display(key*key);
而是应该放到程序最后结束处
物体检测与跟踪算法
重点讨论如何优化Docker镜像以使其轻量化
5G有没有新的应用场景 设备造价及网络建设成本是否过高
如何才能提供容器云服务?
布局布线技术的发展
stc52单片机键盘原理图及程序介绍
机器人服务员频频发生故障状况 还是人类服务员比较好用
用机器人飞艇探索吉萨大金字塔深处的大空洞
对等网络简介及在IPTV网络传输中的应用
动力电池企业将迎来重要发展机遇,预计2025年将步入TWh时代
数智新生长 澎湃兴算力 中兴通讯全栈算力布局亮相2023中国算力大会
选频放大电路的概念及特点介绍
新型电子皮肤可让人们在虚拟现实中互动更真实
PCB制造中如何避免配装和子配装的重新设计
嵊泗智能岛屿电网开始建设,计划离网微电网
¥¥销售/收购/维修2304A 2303 2303A 电源
巴西银行涉嫌垄断交易市场,毫无理由的关闭了加密货币交易经纪商的账户
如何避免多云网络管理的陷阱,这是持续的复杂过程
机器人帮你开车 或许比自动驾驶靠谱
低功耗Cyclone IV FPGA