200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > 51单片机按键值显示在数码管上 数码管亮度控制 数码管显示原理

51单片机按键值显示在数码管上 数码管亮度控制 数码管显示原理

时间:2019-06-14 09:59:10

相关推荐

51单片机按键值显示在数码管上 数码管亮度控制 数码管显示原理

项目场景:

51单片机按下按键在数码管上显示相应的值

问题描述

平常按键检测程序,按下延时消抖,记录一个数字,再按下另一个记录一个数字,然后在一位数码管上显示,就出现了问题。数码管一直显示0 。

下面就是出问题程序,解决方案展示正确程序

#include <regx52.h>sbit LS_A=P2^2;sbit LS_B=P2^3;sbit LS_C=P2^4;unsigned code Nixie_Value[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00};void Delay(unsigned int xms){unsigned char i, j;while(xms--){i = 2;j = 239;do{while (--j);} while (--i);}}void Nixie(unsigned char location,unsigned char number){switch(location){case 1: LS_A=0;LS_B=0;LS_C=0; break;case 2: LS_A=1;LS_B=0;LS_C=0; break;case 3: LS_A=0;LS_B=1;LS_C=0; break;case 4: LS_A=1;LS_B=1;LS_C=0; break;case 5: LS_A=0;LS_B=0;LS_C=1; break;case 6: LS_A=1;LS_B=0;LS_C=1; break;case 7: LS_A=0;LS_B=1;LS_C=1; break;case 8: LS_A=1;LS_B=1;LS_C=1; break;}P0=Nixie_Value[number];Delay(2);P0=0X00;}unsigned char Key(){unsigned char KeyNumber=0;if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}return KeyNumber;}int main(){unsigned char value=0;while(1){value=Key();Nixie(1,value);}}

几个问题:

位选表示哪个数码管 段选表示数码管显示什么

1、在这条语句

P0=Nixie_Value[number];

后加长延时,不就可以显示了吗?确实可以,但是加上延时,程序卡在这里,如果有按键按下,就检测不到了。

2、延时消隐P0=0x00有什么用?

P0=Nixie_Value[number];Delay(2);P0=0X00;

这个延时然后清零消影很关键。若不加这两条语句,由于数码管由一个IO控制,所以当位选成功,段选来临。数码管显示该段选。此时程序执行确定下一个位选,上一个的段选会影响下一个段选,因为P0已经赋值,而下一次段选程序还没执行。这样就会出现鬼影。

延时也是必须存在的,不然可能直接就熄灭不显示东西。

原因分析:

程序解读:程序一直在跑。

while(1){value=Key();Nixie(1,value);}

当按键按下符合某一条语句,进入key()函数的if语句。假如P3_1按下

if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}

然后延时,程序就卡在这了,继续执行while循环,检测松手,再延时消抖,返回数值。这是数值就是某个数了 (1 2 3 4)其中一个 。

接着跳出key函数,执行下一条语句。

Nixie(1,value);

数码管显示这个数字。在分析数码管显示函数Nixie()。

位选表示哪个数码管 段选表示数码管显示什么

三八译码器选择数码管位选,在给P0赋值确定段选。按键按下确实数码管显示过数字(1 2 3 4),但是又接着熄灭了。因为程序接着执行key();人手不可能连续再按下另一个按键,所以数码管又显示0 。再次按下按键分析同理。

解决方案:

将数码管显示函数放到key();函数里面,实现了功能。同时进行了优化,将位选直接写在main函数while循环之前,然后直接操作P0确定段选即可。并且也没有延时。

#include <regx52.h>#include "key.h"sbit LS_A=P2^2;sbit LS_B=P2^3;sbit LS_C=P2^4;unsigned code Nixie_Value[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00};void Key(){unsigned char KeyNumber=0;if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;P0=Nixie_Value[KeyNumber];}if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;P0=Nixie_Value[KeyNumber];}if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;P0=Nixie_Value[KeyNumber];}if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;P0=Nixie_Value[KeyNumber];}}int main(){LS_A=0;LS_B=0;LS_C=0;P0=0x3F;while(1){key();}}

遇到的几个问题,个人体会

为什么数码管滚动?

因为两个位选之间有延时,延时大了,人眼可分辨出来,其实只能控制一个数码管,上一个亮了然后消影,延时后刚好下一个亮。

发现诀窍:重要、重要、重要

静态数码管几个数码管共同点亮,这是利用人眼分辨率低,其实这些数码管已经经历了亮灭,这个亮然后灭,下一个再亮,延时太低,就会导致以为数码管都一直亮着。

数码管亮度控制,当段选后需要一个延时然后消影。然后在一个延时,下一个点亮(位选确定),这两个延时就导致数码管亮度变化。第一个延时长,第二个短,表示数码管亮的时间长,灭队时间短,有占空比理解,则亮度高,反之亮度很低。详细代码见程序二。

先执行Nixie()函数

Nixie(i,i);

执行Nixie()函数延时200毫秒。段选后有延时,点亮200毫秒

P0=Nixie_Value[number];Delay(200);//延时时间要灵活,这是一个变化的值P0=0X00;

两个位选之间100毫秒延时,其实是熄灭100毫秒

Nixie(i,i);Delay(100);

这两个延时就控制了数码管亮度,亮200灭100

程序一、数码管显示1-8不滚动

因此若想数码管都亮着则需要延时很短,可以消影和位选间没有延时。下面这个程序实现数码管显示1-8

#include <regx52.h>sbit LS_A=P2^2;sbit LS_B=P2^3;sbit LS_C=P2^4;unsigned code Nixie_Value[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00};void Delay(unsigned int xms){unsigned char i, j;while(xms--){i = 2;j = 239;do{while (--j);} while (--i);}}void Nixie(unsigned char location,unsigned char number){switch(location){case 1: LS_A=0;LS_B=0;LS_C=0; break;case 2: LS_A=1;LS_B=0;LS_C=0; break;case 3: LS_A=0;LS_B=1;LS_C=0; break;case 4: LS_A=1;LS_B=1;LS_C=0; break;case 5: LS_A=0;LS_B=0;LS_C=1; break;case 6: LS_A=1;LS_B=0;LS_C=1; break;case 7: LS_A=0;LS_B=1;LS_C=1; break;case 8: LS_A=1;LS_B=1;LS_C=1; break;}P0=Nixie_Value[number];Delay(2);//延时时间要灵活,这是一个变化的值P0=0X00;}int main(){unsigned char i=0;while(1){for(i=1;i<=8;i++){Nixie(i,i);}}}

注意段选和消影之间必须有延时,否则不会亮。

P0=Nixie_Value[number];Delay(2);//延时时间要灵活,这是一个变化的值P0=0X00;

程序二、当延时长时,人眼可观察到,就实现了数码管滚动。逐个显示1-8

其实只是在程序一基础上改了延时,就可以实现滚动和亮度控制

#include <regx52.h>sbit LS_A=P2^2;sbit LS_B=P2^3;sbit LS_C=P2^4;unsigned code Nixie_Value[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00};void Delay(unsigned int xms){unsigned char i, j;while(xms--){i = 2;j = 239;do{while (--j);} while (--i);}}void Nixie(unsigned char location,unsigned char number){switch(location){case 1: LS_A=0;LS_B=0;LS_C=0; break;case 2: LS_A=1;LS_B=0;LS_C=0; break;case 3: LS_A=0;LS_B=1;LS_C=0; break;case 4: LS_A=1;LS_B=1;LS_C=0; break;case 5: LS_A=0;LS_B=0;LS_C=1; break;case 6: LS_A=1;LS_B=0;LS_C=1; break;case 7: LS_A=0;LS_B=1;LS_C=1; break;case 8: LS_A=1;LS_B=1;LS_C=1; break;}P0=Nixie_Value[number];Delay(200);//延时时间要灵活,这是一个变化的值P0=0X00;}int main(){unsigned char i=0;while(1){for(i=1;i<=8;i++){Nixie(i,i);Delay(100);}}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。