stc52单片机键盘原理图及程序介绍

电子说

1.3w人已加入

描述

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);

而是应该放到程序最后结束处

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分