admin管理员组文章数量:1621468
项目场景:
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);
}
}
}
版权声明:本文标题:51单片机按键值显示在数码管上,数码管亮度控制,数码管显示原理 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dongtai/1728832958a1175819.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论