0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

jf_f8pIz0xS 来源:电子发烧友整理 2018-02-09 11:18 次阅读

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

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

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

    关注

    5998

    文章

    43963

    浏览量

    620691
  • STC52
    +关注

    关注

    0

    文章

    2

    浏览量

    2965
收藏 人收藏

    评论

    相关推荐

    STC单片机开发板原理图

    本帖最后由 lcl05072099 于 2011-4-25 08:45 编辑 基于STC89C52单片机开发板原理图
    发表于 04-25 08:42

    键盘开关LED与直接单片机程序控制LED亮度差距大(已解决

    本帖最后由 minDragon 于 2012-8-4 09:58 编辑 是这样的,我P1上接了限流电阻和8个小的LED灯,写入程序STC52单片机里去点亮P1上的LED灯时,亮度很亮。但
    发表于 08-04 09:35

    stc52单片机做的利用蜂鸣播放音乐资源占用大吗?

    stc52单片机做的利用蜂鸣器播放音乐,很耗单片机资源吗?为什么放我在播放的时候,单片机好像反应不过来了,我做用ds18b20检测温度报警,已经实现了,但我觉得蜂鸣太单调,我就想播放
    发表于 10-14 22:34

    请问有stc52 hc05通信的程序代码吗?

    买的hc05 带的测试c是stm32 的 求 stc52程序代码,本人放学单片机 ,个人爱好 请多指教 想用android 控制 电磁继电器
    发表于 03-20 04:44

    STC52单片机简单控制直流电机正反转

    单片机STC52简单控制直流电机正反转(已验证)本实验源码来源于:坛友-书盲《STC单片机简单控制直流电机正反转》源代码:main.c#include***it EN= P1^0;//
    发表于 06-28 07:38

    STC52单片机如何控制直流电机正反转?

    STC52单片机如何控制直流电机正反转?
    发表于 10-14 07:42

    stc52单片机晶振不起振是为什么?

    stc52单片机晶振不起振两端电压只有0.1V晶振和芯片都换过了电容20
    发表于 09-26 07:52

    stc89s52单片机设计应用原理图

    stc89s52单片机设计应用原理图原理图包括以下几个模块:流水灯模块、数码管显示模块、温度传感器模块、液晶显示模块、串口通信模块、键盘
    发表于 05-21 15:06 272次下载
    <b class='flag-5'>stc89s52</b><b class='flag-5'>单片机</b>设计应用<b class='flag-5'>原理图</b>

    STC52单片机心形流水灯音乐播放

    STC52单片机心形流水灯 音乐播放 源码 PCB 原理图
    发表于 11-10 17:39 51次下载

    点阵时钟-基于STC52单片机的时钟设计

    16*16点阵时钟——基于STC52单片机的时钟设计
    发表于 12-24 18:28 31次下载

    单片机STC89C52程序

    单片机STC89C52程序
    发表于 01-11 18:16 107次下载

    STC89C52单片机介绍

    STC89C52单片机介绍
    发表于 05-20 13:55 245次下载

    STC52计算器1602显示

    基于STC52单片机芯片的简单运算计算器,结果保留3位小数(可随意更改保留位数),采用1602液晶显示
    发表于 02-27 16:28 3次下载

    STC89C52单片机的I2C使用程序免费下载

    本文档的主要内容详细介绍的是STC89C52单片机的I2C使用程序免费下载。
    发表于 07-26 17:36 18次下载
    <b class='flag-5'>STC89C52</b><b class='flag-5'>单片机</b>的I2C使用<b class='flag-5'>程序</b>免费下载

    基于单片机的指纹识别和键盘密码锁

    方案介绍这是一个基于AS608+STC89C52单片机的指纹识别和键盘密码锁。里面包括程序原理图
    发表于 12-27 15:27 9次下载