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

发布时间:2023-05-23  

STC89C52RC是STC公司生产的一种低功耗、高性能CMOS8位微控制器,具有8K字节系统可编程Flash存储器。STC89C52使用经典的MCS-51内核,但是做了很多的改进使得芯片具有传统51单片机不具备的功能。在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得STC89C52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。


stc52单片机键盘原理图

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

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


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>