找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2728|回复: 32
收起左侧

单片机驱动数码管微微发亮,这种问题有没有解?附程序电路图

  [复制链接]
ID:686513 发表于 2022-11-8 11:28 | 显示全部楼层 |阅读模式
8888.jpg    
共阳数码管显示:com1 com2 com3显示数字正常,但com4位选控制的这六个灯,前三个为单位显示,后三个为电量显示,单位或电量显示时,正常是不需要亮的灯是不亮,但是不亮时会微微发亮?我也明白是前面显示数字的段码影响的,这种问题有解决办法吗?

单片机源程序如下:
#include "display.h"        
//共阳数码管编码表
unsigned char code leddata[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0x00};
                              //0,  1,   2    3     4    5    6    7    8    9    A    B    C    D   E    F    16    17  
                                                                                                               
//数据显示缓冲区
unsigned char LEDBuf[]= {17,17,17,3,3};        

//位选信号
unsigned char code PLACE_CODE[] ={0xfd,0xfb,0xf7,0xdf};
//1111 1101  1111 1011   1111 0111  1101 1111
//单位段码
unsigned char code unit[] ={0xfe,0xfd,0xfb,0xf8};
//                      1111 1110 /1111 1101/1111 1011            //1111 1000   
//电池段码
unsigned char code BAT[] ={0xFF,0xEF,0xCF,0x8F};
//                      1111 1111/1110 1111/1100 1111/1000 1111;   // 1000 1111

unsigned char digdot0=0,digdot1=0;

void Display()
{
        unsigned char i;
        //1.送段码        
        //2.送位选
  //3.延时 1ms  全部数码管显示时间<10ms内
  //4.消隐
        switch(i)
        {
                case 0:
                        duan=0xff;
                        duan=leddata[LEDBuf[0]];
       if(digdot0==1)
                         {
                                duan=leddata[LEDBuf[0]]&0x7f;        
                         }                        
                  wei=PLACE_CODE[0];                 
                  i++;
                  break;
               
          case 1:
                  duan=0xff;
                        duan=leddata[LEDBuf[1]];
                  if(digdot1==1)
                         {
                                duan=leddata[LEDBuf[1]]&0x7f;        
                         }
                  wei=PLACE_CODE[1];        
                  i++;
                  break;
                 
                case 2:                        
                  duan=0xff;
                        duan=leddata[LEDBuf[2]];                  
                  wei=PLACE_CODE[2];                  
                  i++;
                break;
               
                case 3:                        
                  duan=0xff;
                        duan=unit[LEDBuf[3]];
                  wei=PLACE_CODE[3];         
                  i++;
                break;
               
                case 4:                        
                  duan=0xff;
                        duan=BAT[LEDBuf[4]];
                  wei=PLACE_CODE[3];         
                  i=0;
                break;
               
                default:break;
               
        }
        
}

下面是把case3 和case4  段码相与一起送也试过,也不行!
——————————————————————————————————————————————————————————
case 3:                        
                  duan=0xff;
                        duan=unit[LEDBuf[3]];
                  wei=PLACE_CODE[3];         
                  i++;
                break;
               
                case 4:                        
                  duan=0xff;
                        duan=BAT[LEDBuf[4]];
                  wei=PLACE_CODE[3];         
                  i=0;
                break;
合并一起送段码也不行。
case 3:                        
                  duan=0xff;
                        duan=unit[LEDBuf[3] & BAT[LEDBuf[4]];
                  wei=PLACE_CODE[3];         
                  i=0;
                break;

下面是更新了wulin老师的代码,故障现像依旧。
#include "display.h"
        
//共阳数码管编码表
unsigned char code leddata[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0x00};
                              //0,  1,   2    3     4    5    6    7    8    9    A    B    C    D   E    F    16    17
                                                                                                               
//数据显示缓冲区
unsigned char LEDBuf[]= {17,17,17,3,3};        

//位选信号
unsigned char code PLACE_CODE[] ={0xfd,0xfb,0xf7,0xdf};
//                        1111 1101/1111 1011/1111 0111/1101 1111

//单位段码
unsigned char code unit[] ={0xfe,0xfd,0xfb,0xf8};
//                      1111 1110 /1111 1101/1111 1011    /1111 1000   

//电池段码
unsigned char code BAT[] ={0xFF,0xEF,0xCF,0x8F};
//             1111 1111/1110 1111/1100 1111/1000 1111;   / 1000 1111

unsigned char digdot0=0,digdot1=0;   


void Display()
{
        static unsigned char i;//静态变量

        duan=0xff;//段消隐
        switch(i)
        {
                case 0:
                        wei=PLACE_CODE[0];
                        if(digdot0==1) duan=leddata[LEDBuf[0]]&0x7f;
                        else duan=leddata[LEDBuf[0]];  
                break;

                case 1:
                        wei=PLACE_CODE[1];
                        if(digdot1==1) duan=leddata[LEDBuf[1]]&0x7f;      
                        else duan=leddata[LEDBuf[1]];
                break;

                case 2:                       
                        wei=PLACE_CODE[2];
                        duan=leddata[LEDBuf[2]];
                break;

                case 3:                       
                        wei=PLACE_CODE[3];
                        duan=unit[LEDBuf[3]];
                break;

                case 4:                       
                        wei=PLACE_CODE[3];
                        duan=BAT[LEDBuf[4]];
                break;

                default:break;
        }
        i=++i%5;
}


现象更新:1.今天发现是com4的哪路不对(单位和电量显示灯都会随显示数字的变化微亮),com1 com2 com3显示数字没有这种现像。也就是说com4控制的这路好像没有消隐。
回复

使用道具 举报

ID:955673 发表于 2022-11-8 12:29 | 显示全部楼层
没加消隐?
回复

使用道具 举报

ID:161164 发表于 2022-11-8 13:05 | 显示全部楼层
估计是没消影
最好贴代码来分析
回复

使用道具 举报

ID:94031 发表于 2022-11-8 13:11 | 显示全部楼层
微微发亮不舒服,可以LED回路串电阻减弱。
回复

使用道具 举报

ID:686513 发表于 2022-11-8 13:30 | 显示全部楼层
lkc8210 发表于 2022-11-8 13:05
估计是没消影
最好贴代码来分析

#include "display.h"

       
//共阳数码管编码表
unsigned char code leddata[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0x00};
                              //0,  1,   2    3     4    5    6    7    8    9    A    B    C    D   E    F    16    17  
                                                                                                               
//数据显示缓冲区
unsigned char LEDBuf[]= {17,17,17,3,3};       

//位选信号
unsigned char code PLACE_CODE[] ={0xfd,0xfb,0xf7,0xdf};
//1111 1101  1111 1011   1111 0111  1101 1111
//单位段码
unsigned char code unit[] ={0xfe,0xfd,0xfb,0xf8};
//                      1111 1110 /1111 1101/1111 1011            //1111 1000   
//电池段码
unsigned char code BAT[] ={0xFF,0xEF,0xCF,0x8F};
//                      1111 1111/1110 1111/1100 1111/1000 1111;   // 1000 1111

unsigned char digdot0=0,digdot1=0;

void Display()
{
        unsigned char i;
        //1.送段码       
        //2.送位选
  //3.延时 1ms  全部数码管显示时间<10ms内
  //4.消隐
        switch(i)
        {
                case 0:
                        duan=0xff;
                        duan=leddata[LEDBuf[0]];
       if(digdot0==1)
                         {
                                duan=leddata[LEDBuf[0]]&0x7f;       
                         }                         
                  wei=PLACE_CODE[0];                 
                  i++;
                  break;
               
          case 1:
                  duan=0xff;
                        duan=leddata[LEDBuf[1]];
                  if(digdot1==1)
                         {
                                duan=leddata[LEDBuf[1]]&0x7f;       
                         }
                  wei=PLACE_CODE[1];       
                  i++;
                  break;
                 
                case 2:                       
                  duan=0xff;
                        duan=leddata[LEDBuf[2]];                  
                  wei=PLACE_CODE[2];                  
                  i++;
                break;
               
                case 3:                       
                  duan=0xff;
                        duan=unit[LEDBuf[3]];
                  wei=PLACE_CODE[3];          
                  i++;
                break;
               
                case 4:                       
                  duan=0xff;
                        duan=BAT[LEDBuf[4]];
                  wei=PLACE_CODE[3];          
                  i=0;
                break;
               
                default:break;
               
        }
       
}
回复

使用道具 举报

ID:686513 发表于 2022-11-8 13:32 | 显示全部楼层
xuyaqi 发表于 2022-11-8 13:11
微微发亮不舒服,可以LED回路串电阻减弱。

这种方法试了,是可以减弱,但还是微微亮。
回复

使用道具 举报

ID:686513 发表于 2022-11-8 13:32 | 显示全部楼层
lkc8210 发表于 2022-11-8 13:05
估计是没消影
最好贴代码来分析

消影有的。
回复

使用道具 举报

ID:686513 发表于 2022-11-8 13:39 | 显示全部楼层
本帖最后由 zhth1979 于 2022-11-8 13:52 编辑
lkc8210 发表于 2022-11-8 13:05
估计是没消影
最好贴代码来分析

代码已贴,麻烦大神帮我看看哪里有问题。
回复

使用道具 举报

ID:686513 发表于 2022-11-8 15:14 | 显示全部楼层

有消隐,前三位数字都正常。
回复

使用道具 举报

ID:194257 发表于 2022-11-8 17:19 | 显示全部楼层
送数之前位选要全都置位也就是送0xff,这样才是真正的消隐
回复

使用道具 举报

ID:521890 发表于 2022-11-8 17:49 | 显示全部楼层
换com4驱动三极管。
回复

使用道具 举报

ID:160893 发表于 2022-11-8 18:07 | 显示全部楼层
1,可能每位显示时间短(主程序循环一次的时间)太小,LED还没点亮就扫描下一位了
2.static unsigned char i;//要定义静态函数
3.显示段位码注意顺序消隐--->位码---->段码,否则有残影,如下OK
                case 0:
                        duan=0xff;        //消隐
                                 wei=PLACE_CODE[0];   //位码              
                                               if(digdot0==1)
                                                {
                                                      duan=leddata[LEDBuf[0]]&0x7f; //段加小数点      
                                                }
                                        else
                                                {
                                                        duan=leddata[LEDBuf[0]];
                                                }
                  i++;
                  break;
4.定时器控制Dsplay()<4ms执行一次(>60Hz扫描防闪烁)
回复

使用道具 举报

ID:161164 发表于 2022-11-8 18:09 | 显示全部楼层

代码看了,消影消了个寂莫
次序应该是这样:
2022-11-08_180839.png

回复

使用道具 举报

ID:213173 发表于 2022-11-8 19:02 | 显示全部楼层
zhth1979 发表于 2022-11-8 13:30
#include "display.h"

       

函数放在1~4ms循环周期环境为佳
  1. void Display()
  2. {
  3.         static unsigned char i;//静态变量

  4.         duan=0xff;//段消隐
  5.         switch(i)
  6.         {
  7.                 case 0:
  8.                         wei=PLACE_CODE[0];
  9.                         if(digdot0==1)duan=leddata[LEDBuf[0]]&0x7f;
  10.                         else duan=leddata[LEDBuf[0]];  
  11.                 break;

  12.                 case 1:
  13.                         wei=PLACE_CODE[1];
  14.                         if(digdot1==1)
  15.                                 duan=leddata[LEDBuf[1]]&0x7f;      
  16.                         else duan=leddata[LEDBuf[1]];
  17.                 break;

  18.                 case 2:                       
  19.                         wei=PLACE_CODE[2];
  20.                         duan=leddata[LEDBuf[2]];
  21.                 break;

  22.                 case 3:                       
  23.                         wei=PLACE_CODE[3];
  24.                         duan=unit[LEDBuf[3]];
  25.                 break;

  26.                 case 4:                       
  27.                         wei=PLACE_CODE[3];
  28.                         duan=BAT[LEDBuf[4]];
  29.                 break;

  30.                 default:break;
  31.         }
  32.         i=++i%5;
  33. }
复制代码
回复

使用道具 举报

ID:686513 发表于 2022-11-8 19:12 | 显示全部楼层
发表于 2022-11-8 17:49
换com4驱动三极管。

换了,并且还换了别的型号,没用。
回复

使用道具 举报

ID:624769 发表于 2022-11-8 20:17 | 显示全部楼层
zhth1979 发表于 2022-11-8 19:12
换了,并且还换了别的型号,没用。

看13楼的正确答案。
回复

使用道具 举报

ID:195496 发表于 2022-11-8 20:26 | 显示全部楼层
如果排除程序问题,还不行,要换三极管,换个别的类型的,我常用8550做共阳的位选
回复

使用道具 举报

ID:686513 发表于 2022-11-9 08:46 | 显示全部楼层
lkc8210 发表于 2022-11-8 18:09
代码看了,消影消了个寂莫
次序应该是这样:

按您的次序改了,还是老样子,先送段码和先送位选应该是没关系的。
回复

使用道具 举报

ID:686513 发表于 2022-11-9 09:04 | 显示全部楼层
lkc8210 发表于 2022-11-8 18:09
代码看了,消影消了个寂莫
次序应该是这样:

今天发现是com4的哪路不对(单位和电量显示灯都会随显示数字的变化微亮),com1 com2 com3显示数字没有这种现像。也就是说com4控制的这路好像没有消隐。
回复

使用道具 举报

ID:686513 发表于 2022-11-9 09:06 | 显示全部楼层
大漠落日 发表于 2022-11-8 20:26
如果排除程序问题,还不行,要换三极管,换个别的类型的,我常用8550做共阳的位选

我现在用的就是2TY.
回复

使用道具 举报

ID:686513 发表于 2022-11-9 09:29 | 显示全部楼层
wulin 发表于 2022-11-8 19:02
函数放在1~4ms循环周期环境为佳

您的代码很不错,简洁,直接使用您这段代码还是老样子,这样看不像是底层显示的问题了,是不是数字分解或是按键加减闪烁导致的。
回复

使用道具 举报

ID:686513 发表于 2022-11-9 11:32 | 显示全部楼层
yscbg 发表于 2022-11-8 18:07
1,可能每位显示时间短(主程序循环一次的时间)太小,LED还没点亮就扫描下一位了
2.static unsigned char ...

1和4,底层显示,我放在1ms定时器里了,1ms扫描一位。2.改为静态函数也一样 3.段码和位码先送哪个应该没关系吧?我对调试过,并且直用了wulin老师的代码放进去还是老样子。
回复

使用道具 举报

ID:686513 发表于 2022-11-9 12:12 | 显示全部楼层
zhth1979 发表于 2022-11-9 11:32
1和4,底层显示,我放在1ms定时器里了,1ms扫描一位。2.改为静态函数也一样 3.段码和位码先送哪个应该没 ...

想了想,不管数字,单位,电量如何变化,最终还是通过个底层去显示呀。按说这个底层没问题显示应该就不会有问题才对呀!
回复

使用道具 举报

ID:686513 发表于 2022-11-9 16:21 | 显示全部楼层
xiaoshan7748 发表于 2022-11-8 17:19
送数之前位选要全都置位也就是送0xff,这样才是真正的消隐

先送位选也一样,没变化。
回复

使用道具 举报

ID:384109 发表于 2022-11-9 17:04 | 显示全部楼层
消隐没有延时,等于没消隐
回复

使用道具 举报

ID:213173 发表于 2022-11-9 21:34 | 显示全部楼层
zhth1979 发表于 2022-11-9 09:29
您的代码很不错,简洁,直接使用您这段代码还是老样子,这样看不像是底层显示的问题了,是不是数字分解或 ...

你的程序框架一定有问题,导致显示异常。给你简化一下测试,仿真正常。
4444.jpg


  1. #include <reg51.H>
  2. #define duan P2
  3. #define wei P3 //      
  4. //共阳数码管编码表
  5. unsigned char code leddata[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0x00};
  6.                               //0,  1,   2    3     4    5    6    7    8    9    A    B    C    D   E    F    16    17  
  7. //数据显示缓冲区
  8. unsigned char LEDBuf[4];      
  9. //位选信号
  10. unsigned char code PLACE_CODE[] ={0x02,0x04,0x08,0x20};
  11. //1111 1101  1111 1011   1111 0111  1101 1111

  12. //单位段码
  13. unsigned char code unit[] ={0xfe,0xfd,0xfb,0xf8};
  14. //                      1111 1110 /1111 1101/1111 1011/1111 1000   
  15. //电池段码
  16. unsigned char code BAT[] ={0xff,0xef,0xcf,0x8f};
  17. //                      1111 1111/1110 1111/1100 1111/1000 1111;   // 1000 1111
  18. unsigned int t;

  19. void Display()
  20. {
  21.         static unsigned char i;//静态变量
  22.         switch(i)
  23.         {
  24.                 case 0:LEDBuf[i]=leddata[1];break;
  25.                 case 1:LEDBuf[i]=leddata[2]&0x7f;break;//加小数点
  26.                 case 2:LEDBuf[i]=leddata[3];break;
  27.                 case 3:LEDBuf[i]=leddata[4];break;
  28.         }
  29.         wei&=0xd1;//位消隐
  30.         duan=LEDBuf[i];//送段码
  31.         wei|=PLACE_CODE[i];//送位码
  32.         i=++i%4;
  33. }

  34. void main()
  35. {
  36.         while(1)
  37.         {
  38.                 Display();               
  39.                 t=110;
  40.                 //延时T=t*9+16us(12M晶振)约1ms
  41.                 while(t--);
  42.         }
  43. }
复制代码



回复

使用道具 举报

ID:401564 发表于 2022-11-10 00:16 | 显示全部楼层
几天都没有搞定?
这只是一个数码管而已呀
在每次显示之前,先消隐

duan = 0x00;
wei = 0x00;
delay_us(10);//自己写一个uS延时程序

这个放在 Display()里面,最先执行,然后再执行其它的显示
如果还不行,那就是你程序的其它问题
回复

使用道具 举报

ID:686513 发表于 2022-11-10 12:56 | 显示全部楼层
wulin 发表于 2022-11-9 21:34
你的程序框架一定有问题,导致显示异常。给你简化一下测试,仿真正常。

wulin老师,今天发现是com4的哪路不对(单位和电量显示灯都会随显示数字的变化微亮),com1 com2 com3显示数字没有这种现像。也就是说com4控制的这路好像没有消隐。
回复

使用道具 举报

ID:686513 发表于 2022-11-10 12:56 | 显示全部楼层
Y_G_G 发表于 2022-11-10 00:16
几天都没有搞定?
这只是一个数码管而已呀
在每次显示之前,先消隐

是哪,还没搞定,请大师指点呀!今天发现是com4的哪路不对(单位和电量显示灯都会随显示数字的变化微亮),com1 com2 com3显示数字没有这种现像。也就是说com4控制的这路好像没有消隐。
回复

使用道具 举报

ID:170800 发表于 2023-10-31 13:52 | 显示全部楼层
所谓的消隐没有做好:因为位码最后一次在扫描第4位在开启的状态并没有改变,而段码是下一次送数据时变成显示了,所有消隐最好将所有的段码与位码状态恢复才行!
回复

使用道具 举报

ID:170800 发表于 2023-10-31 14:10 | 显示全部楼层
我也是初学者,学了一年左右,据对消隐的理解看似乎是程序消隐问题:
1、程序是反复扫描来改变状态的,所以位码没有消隐会是最后一次扫描的状态;
2、我看程序是,swtich后,第4位状态最后一次开启后关没有关闭;
3、下一个循环送段时,第四位闪亮状态,在送完段码后的一瞬间,第四位是亮的,然后第一位码送到,才同时就相当于关闭第四位,瞬间点亮的余辉形成微亮,典型的第4位没有消隐的处理;
4、26楼的程序是正确的,所以仿真没有问题,如果楼主的仿真也没有问题的话,是软件仿真与实际的差异问题;
5、我个人认为正确的消隐是:如果先送段码则前先作位消隐,如果先送位码,则先作段码消隐,所以14楼程序也是正确的;交换送显示数据的顺序,消隐的对象是不同的,我初学的程序不懂,就在送显示数据前,所有的状态恢复到最初的状态,慢慢看别人的程序,再看书后,理解才清晰点;
——不知道说清楚没有,因为知识很多是从51Hei学到的,所以回复特有耐性,与其他学习者共勉。
回复

使用道具 举报

ID:466505 发表于 2023-10-31 14:52 | 显示全部楼层
有没有可能有LED反向轻微漏电导致其它LED微亮?
回复

使用道具 举报

ID:397054 发表于 2023-10-31 15:43 | 显示全部楼层
一年过去了,问题解决了没有啊?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表