历史上的今天
返回首页

历史上的今天

今天是:2025年10月19日(星期日)

正在发生

2022年10月19日 | STC89C52单片机 独立键盘

2022-10-19 来源:csdn

独立键盘

键盘介绍

键盘是电子系统中人机对话的重要组成部分,是人向机器发出指令、输入信息的必须设备


键盘在单片机应用系统中是使用最广泛的一种数据输入设备。键盘是由多个按键组成的。


按键的工作原理

按键通常是一种常开型开关,常态下按键的两个触点处于断开状态,按下按键时它们才闭合。

以下是 轻触开关和轻触按键 图

(img/touch_switch.png?imageView2/2/w/550)]

键盘类型

通常键盘有编码键盘和非编码键盘两种。编码键盘通过硬件电路产生被按按键的键值码,这种键盘使用方便,所需程序简单,但硬件电路复杂,

如计算机的键盘,单片机则通常不采用编码键盘。


而软件编程来识别的称为非编码键盘,非编码键盘硬件电路简单。


在单片机组成的各种系统中,最常用的是非编码键盘。


独立键盘与矩阵键盘的特点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AbUzy3WA-1605375466054)(img/keyboard.png?imageView2/2/w/550)]

非编码键盘分为独立键盘和矩阵键盘。

独立键盘特点:每个按键占用一个IO口,当按键数量较多时,IO口利用效率不高,但程序简单,适用于所需按键较少的场合。

矩阵键盘特点:电路连接复杂,但提高了IO口利用率,软件编程较复杂。适用于使用大量按键的场合。


相关原理图分析

在这里插入图片描述

按键一端与IO口连接,另外一端接地。通过控制IO口输出高电平即可检测按键是否按下,当按下时IO口会被拉低,松开后IO口回到高电平。


按键特性

机械按键在按下或松开时会存在抖动现象。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AmHQOBR9-1605375466061)(img/the_key_features.png?imageView2/2/w/550)]

使用独立按键 S2 控制灯 LED1 亮灭;

#include

#include


#define uint unsigned int

#define uchar unsigned char


sbit DU = P2^6;//数码管段选

sbit WE = P2^7;//数码管段选

sbit key_s2 = P3^0;//独立按键S2

uchar num;//数码管显示的值

uchar count;


//共阴数码管段选表0-9

uchar  code tabel[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};


//毫秒级延时函数定义

void delay(uint z){

uint x,y;

for(x = z; x > 0; x--)

for(y = 114; y > 0 ; y--);


void main()//main函数自身会循环

{

while(1)

{

if(key_s2 == 0)//判断S2是否被按下

{

delay(20);//按键消抖

if(key_s2 == 0)

{

if( count == 0){  // 当 count = 0 的时候 点亮LED1灯

P1 = 0XFE; // 点亮 LED1 灯

count = 1; 

}else if(count == 1){   // 当 count = 1 的时候 关闭LED1灯

P1 = 0xff;  // 关闭所有的LED 灯 

count = 0; 

}

}

while(!key_s2);//松手检测

}

}

}  


独立按键 S2 控制流水灯亮灭。

#include

#include


#define uint unsigned int

#define uchar unsigned char


sbit DU = P2^6;//数码管段选

sbit WE = P2^7;//数码管段选

sbit key_s2 = P3^0;//独立按键S2

sbit key_s3 = P3^1;//独立按键S3

uchar num;//数码管显示的值

uchar count;

uchar temp; // LED灯相关变量


//共阴数码管段选表0-9

uchar  code tabel[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};



//毫秒级延时函数定义

void delay(uint z)

{

uint x,y;

for(x = z; x > 0; x--)

for(y = 114; y > 0 ; y--);


void main() {//main函数自身会循环



if(count == 0){

temp = 0xfe;

P1 = temp;  // 1111 1110

delay(100);

} else if(count == 1) {

P1 = 0xff;

}



while(1){

if(count == 0){

  temp = _crol_(temp, 1);   // 循环左移

P1 = temp;

delay(100);

} else if(count == 1) {

P1 = 0xff;

}


if(key_s2 == 0){//判断S2是否被按下

delay(20);//按键消抖

if(key_s2 == 0){

if( count == 0){

delay(100); // 延时 100毫秒 通过增加延时的时间或减少延时的时间,来控制流水灯的速度

count = 1;

}else if(count == 1){

P1 = 0xff;  // 关闭所有的LED 灯 

count = 0; 

}

}


}

while(!key_s2);//松手检测

}

}


每次按动按键 S3,控制数码管显示数字加 1,当数码管数字变为 10 时, 按动按键 S3,会让数码管重新变为 00。

方法一:


#include

#include


#define uint unsigned int

#define uchar unsigned char


sbit DU = P2^6;//数码管段选

sbit WE = P2^7;//数码管段选

sbit key_s2 = P3^0;//独立按键S2

sbit key_s3 = P3^1;//独立按键S3

sbit key_s4 = P3^2;//独立按键S2

uchar num1 = 0, num2 = 0;//数码管显示的值

uchar count = 0;


//共阴数码管段选表0-9

uchar  code tabel[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};



//毫秒级延时函数定义

void delay(uint z)

{

uint x,y;

for(x = z; x > 0; x--)

for(y = 114; y > 0 ; y--);



/*====================================

描述 :两位共阴数码管动态显示

====================================*/

void display(uchar num1, uchar num2)

{

/*第一位显示*/

P0 = 0XFF;//清除断码

WE = 1;//打开位选锁存器

P0 = 0XFE; //1111 1110

WE = 0;//锁存位选数据

DU = 1;//打开段选锁存器

P0 = tabel[num1];//

DU = 0;//锁存段选数据

delay(1);


/*第二位显示*/

P0 = 0XFF;//清除断码

WE = 1;//打开位选锁存器

P0 = 0XFD; //1111 1101

WE = 0;//锁存位选数据

DU = 1;//打开段选锁存器

P0 = tabel[num2];//

DU = 0;//锁存段选数据

delay(1);

}


void main()//main函数自身会循环

{

display(num1, num2); //数码管显示函数

while(1)

{

if(key_s3 == 0)//判断S2是否被按下

{

delay(20);//按键消抖

if(key_s3 == 0)

{

num2++; 

if(num2 == 10){

num1 = 1;

num2 = 0;

count++;

} else if(count == 1){

num1 = 0;

num2 = 0;

count = 0;

display(num1, num2);

}

while(!key_s3);//松手检测 

}

}

   display(num1, num2); 

}

}  


方法二:


#include

#include


#define uint unsigned int

#define uchar unsigned char


sbit DU = P2^6;//数码管段选

sbit WE = P2^7;//数码管段选


sbit key_s3 = P3^1;//独立按键S3


uchar display_num = 0; // 对数码管显示的数值初始化

uchar num1 = 0, num2 = 0;//数码管显示的值


//共阴数码管段选表0-9

uchar  code tabel[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};



//毫秒级延时函数定义

void delay(uint z)

{

uint x,y;

for(x = z; x > 0; x--)

for(y = 114; y > 0 ; y--);



/*====================================

描述 :两位共阴数码管动态显示

====================================*/

void display(uchar num1, uchar num2)

{

/*第一位显示*/

P0 = 0XFF;//清除断码

WE = 1;//打开位选锁存器

P0 = 0XFE; //1111 1110

WE = 0;//锁存位选数据

DU = 1;//打开段选锁存器

P0 = tabel[num1];//

DU = 0;//锁存段选数据

delay(1);


/*第二位显示*/

P0 = 0XFF;//清除断码

WE = 1;//打开位选锁存器

P0 = 0XFD; //1111 1101

WE = 0;//锁存位选数据

DU = 1;//打开段选锁存器

P0 = tabel[num2];//

DU = 0;//锁存段选数据

delay(1);

}


void main()//main函数自身会循环

{

display(num1, num2); //数码管显示函数

while(1)

{

if(key_s3 == 0)//判断S2是否被按下

{

display_num++; // 每按一次独立按键,数码管显示的值加 1

delay(20);//按键消抖

if(key_s3 == 0)

{

switch(display_num){ // 通过 switch case 语句对 数码管的数值进行精准的管理

    case 0 :

       num1 = 0;

   num2 = 0;

       break; 

    case 1 :

       num1 = 0;

   num2 = 1;

       break;

case 2 :

       num1 = 0;

   num2 = 2;

       break;

case 3 :

       num1 = 0;

   num2 = 3;

       break;

case 4 :

       num1 = 0;

   num2 = 4;

       break;

case 5 :

       num1 = 0;

   num2 = 5;

       break;

case 6 :

       num1 = 0;

   num2 = 6;

       break;   

case 7 :

       num1 = 0;

   num2 = 7;

       break; 

case 8 :

       num1 = 0;

   num2 = 8;

       break;

case 9 :

       num1 = 0;

   num2 = 9;

       break;

case 10 :

       num1 = 1;

   num2 = 0;

       break;

default : // 当display_num数值大于10的时候,display_num 重新赋值0,不能使 display_num 大于 10

display_num = 0;

num1 = 0;

    num2 = 0;      

}

while(!key_s3);//松手检测 

}

}


   display(num1, num2); 

}

}  


每次按动按键 S4,控制数码管显示数字减 1,当数码管数字变为 00 时, 按动按键 S4,会让数码管重新变为 10。

方法一:


#include

#include


#define uint unsigned int

#define uchar unsigned char


sbit DU = P2^6;//数码管段选

sbit WE = P2^7;//数码管段选

sbit key_s2 = P3^0;//独立按键S2

sbit key_s3 = P3^1;//独立按键S3

sbit key_s4 = P3^2;//独立按键S2

uchar num1 = 0, num2 = 0;//数码管显示的值

uchar count = 0;


//共阴数码管段选表0-9

uchar  code tabel[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};



//毫秒级延时函数定义

void delay(uint z)

{

uint x,y;

for(x = z; x > 0; x--)

for(y = 114; y > 0 ; y--);



/*====================================

描述 :两位共阴数码管动态显示

====================================*/

void display(uchar num1, uchar num2)

{

/*第一位显示*/

P0 = 0XFF;//清除断码

WE = 1;//打开位选锁存器

P0 = 0XFE; //1111 1110

WE = 0;//锁存位选数据

DU = 1;//打开段选锁存器

P0 = tabel[num1];//

DU = 0;//锁存段选数据

delay(1);


/*第二位显示*/

P0 = 0XFF;//清除断码

WE = 1;//打开位选锁存器

P0 = 0XFD; //1111 1101

WE = 0;//锁存位选数据

DU = 1;//打开段选锁存器

P0 = tabel[num2];//

DU = 0;//锁存段选数据

delay(1);

}


void main()//main函数自身会循环

{

display(num1, num2); //数码管显示函数

while(1)

{

if(key_s4 == 0)//判断S2是否被按下

{

delay(20);//按键消抖

if(key_s4 == 0)

{

if(count == 0){

num1 = 1;

num2 = 0;

count++;

} else if(count == 1){

num1 = 0;

num2 = 9;

count++;

} else if(count < 11){

num2--;

count++;

} else {

count = 0;

}


if(count == 0){

num1 = 1;

num2 = 0;

count++;

while(!key_s4);//松手检测 

}

}

   display(num1, num2); 

}


方法二:


/*********************************************************************************

* 【作    者】: vvcat

* 【版    本】: V1.0

* 【外部晶振】: 11.0592mhz

* 【主控芯片】: STC89C52

* 【编译环境】: Keil μVisio4

* 【程序功能】: 独立按键识别                     

* 【使用说明】: 每次按动按键 S4,控制数码管显示数字减 1,当数码管数字变为 00 时, 按动按键 S4,会让数码管重新变为 10。

**********************************************************************************/

#include

#include


#define uint unsigned int

#define uchar unsigned char


sbit DU = P2^6;//数码管段选

sbit WE = P2^7;//数码管段选

sbit key_s4 = P3^2;//独立按键S4

uchar display_num = 0; // 对数码管显示的数值初始化

uchar num1 = 0, num2 = 0;//数码管显示的值


//共阴数码管段选表0-9

uchar  code tabel[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};



//毫秒级延时函数定义

void delay(uint z)

{

uint x,y;

for(x = z; x > 0; x--)

for(y = 114; y > 0 ; y--);



/*====================================

描述 :两位共阴数码管动态显示

====================================*/

void display(uchar num1, uchar num2)

{

/*第一位显示*/

P0 = 0XFF;//清除断码

WE = 1;//打开位选锁存器

P0 = 0XFE; //1111 1110

WE = 0;//锁存位选数据

DU = 1;//打开段选锁存器

P0 = tabel[num1];//

DU = 0;//锁存段选数据

delay(1);


/*第二位显示*/

P0 = 0XFF;//清除断码

WE = 1;//打开位选锁存器

P0 = 0XFD; //1111 1101

WE = 0;//锁存位选数据

DU = 1;//打开段选锁存器

P0 = tabel[num2];//

DU = 0;//锁存段选数据

delay(1);

}


void main()//main函数自身会循环

{

display(num1, num2); //数码管显示函数

while(1)

{

if(key_s4 == 0)//判断S4是否被按下

{

display_num--; // 每按一次独立按键,数码管显示的值减去1

delay(20);//按键消抖

if(key_s4 == 0)

{

switch(display_num){   // 通过 switch case 语句对 数码管的数值进行精准的管理

    case 0 :

       num1 = 0;

   num2 = 0;

       break; 

    case 1 :

       num1 = 0;

   num2 = 1;

       break;

case 2 :

       num1 = 0;

   num2 = 2;

       break;

推荐阅读

史海拾趣

问答坊 | AI 解惑

单电源运算放大器的设计考虑

单电源运算放大器的设计考虑 为了减小产品尺寸、降低成本、延长电池寿命、提高电池供电系统的性能,热计人员加快了低电压、单电源系统的开发、应用趋势。这种趋势对消费者是有益的,但却使得为特定应用选择合适的运算放大器变得复杂。 通常, ...…

查看全部问答>

440b0的启动代码与bootload 有什么区别

440b0的启动代码与bootload 有什么区别 一个工程下面有着几个文件都是什么意思 Led_test.c 44BLIB_A.S 44binit.s 上面的文件哪个是启动代码哪个是bootload…

查看全部问答>

【Labview】一本关于labview的电子书[清华版教材]

今天偶然发现的一本电子书,和大家共享。适合初学者。   也欢迎大家在此讨论学习此书时遇到的问题或者心得,希望和大家共同进步。 [ 本帖最后由 安_然 于 2010-3-29 17:21 编辑 ]…

查看全部问答>

开关电源问题请教

我想做一个输出200W的开关电源,效率为90%,想采用半桥式电路,想问大家采用什么芯片比较好,TL494可以吗?…

查看全部问答>

串口收发字符串的问题的!!!

最近在调试串口时,遇到个奇怪的问题,收发字符串时总是把最后一个接受再最前面了:   例如:发送:123456789  而接收的是 912345678           发送:ABCDEFGHI  而接收的是 IABC ...…

查看全部问答>

力传感器怎么跟ARM9连接

请问一下FSS系列的力传感器怎么跟ARM9开发板连接?要不要放大电路的?如果要的话,放大电路要怎样设计?…

查看全部问答>

CF卡驱动的问题

CE 5.0 PCMCIA的驱动加载了,插入CF卡跳出\"未经确认的PCCARD适配器\",要求输入驱动名称,是否还需要驱动? CE自带有PCCARD的测试程序,测试总是只能过6项(不插卡也一样),有人用过没?…

查看全部问答>

有没有高手可以定制WINCE.NET 的ROM的,,付费... 付费.......

我有一个WINDOWS MOBILE的PDA,用的三星CPU,有高手能定制一个wince.net的ROM出来.付费.. 联系我QQ:86163938  MSN:myfm3a@hotmail.com …

查看全部问答>

arm下如何设置无线网

我用2410的开发板,2.6.8的linux内核,用优龙提供的无线网卡驱动 insmod rt73.ko; ifconfig rausb0 192.168.5.2 up后,无线网貌似已经启动起来了,  我用笔记本当ap,设了全开放,无加密接入,用别的电脑都能正常接入。 2410的无线网 ...…

查看全部问答>

求西门子资料:mc35 GPRS Startup User’s Guide

mc35 GPRS Startup User’s Guide,哪有有这个资料啊,是西门子的,但从网上却找不到,只在别的文档里看到了这个名字,有的请提供下,谢谢了…

查看全部问答>