找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1634|回复: 32
打印 上一主题 下一主题
收起左侧

大佬们,为什么我这单片机数码管会乱闪呢?

[复制链接]
跳转到指定楼层
楼主
ID:1058641 发表于 2024-2-23 20:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. #include "reg52.h"
  2. #include "seg.h"
  3. #include "iic.h"
  4. #include "onewire.h"
  5. #include "key.h"
  6. #include "led.h"

  7. #define uchar unsigned char
  8. #define uint unsigned int
  9.         
  10. //led
  11. uchar led_buf[]={0,0,0,0,0,0,0,0};

  12. //°´¼ü
  13. uchar key_sld;

  14. //ÊýÂë¹Ü
  15. uint seg_sld;
  16. uchar seg_pos;
  17. uchar seg_buf[]={10,10,10,10,10,10,10,10};
  18. uchar seg_point[]={0,0,0,0,0,0,0,0};

  19. //½çÃæ
  20. uchar show_mo=0;
  21. bit mode=0;
  22. uint temp;
  23. uchar set_temp=25;
  24. uint out_v;

  25. //º¯Êý

  26. void smg_reset()
  27. {
  28.         uchar i;
  29.         for(i=0;i<8;i++)
  30.         {
  31.                 seg_buf[i]=10;
  32.                 seg_point[i]=0;
  33.         }
  34. }

  35. void init()
  36. {
  37.         P0=0x00;
  38.         P2=P2&0x1f|0xa0;
  39.         P2&=0x1f;
  40.         
  41.         P0=0xff;
  42.         P2=P2&0x1f|0x80;
  43.         P2&=0x1f;
  44. }

  45. void key_proc()
  46. {
  47.         static uchar key_val,key_old,key_down,key_up;
  48.         if(key_sld)
  49.                 return;
  50.         key_sld=1;
  51.         
  52.         key_val=readkey();
  53.         key_down=key_val&(key_val^key_old);
  54.         key_up=~key_val&(key_val^key_old);
  55.         key_old=key_val;
  56.         
  57.         if(key_down==4)
  58.                 show_mo=(++show_mo)%3;
  59.         else if(show_mo==1 && key_down==6)
  60.                 set_temp=(++set_temp>99)?99:set_temp;
  61.         else if(show_mo==1 && key_down==7)
  62.                 set_temp=(--set_temp==0)?0:set_temp;
  63.         else if(key_down==5)
  64.                 mode=~mode;
  65.         
  66. }

  67. void seg_proc()
  68. {
  69.         uint temp_temp;
  70.         if(seg_sld)
  71.                 return;
  72.         seg_sld=1;
  73.         temp_temp=(uint)ds18b20_read();
  74.         temp=temp_temp;
  75.         
  76.         switch(show_mo)
  77.         {
  78.                 case 0:
  79.                         smg_reset();
  80.                         seg_buf[0]=11;//c
  81.                         seg_buf[4]=temp/1000;
  82.                         seg_buf[5]=temp/100%10;
  83.                         seg_buf[6]=temp/10%10;
  84.                         seg_buf[7]=temp%10;
  85.                         seg_point[5]=1;
  86.                  break;
  87.                
  88.                 case 1:
  89.                         smg_reset();
  90.                         seg_buf[0]=12;//p
  91.                         seg_buf[6]=set_temp/10;
  92.                         seg_buf[7]=set_temp%10;
  93.                  break;
  94.                
  95.                 case 2:
  96.                         smg_reset();
  97.                         seg_buf[0]=13;//a
  98.                         if(mode)
  99.                         {
  100.                                 if(temp_temp>set_temp)
  101.                                         out_v=500;
  102.                                 else
  103.                                         out_v=0;
  104.                                 seg_buf[5]=out_v/100;
  105.                                 seg_buf[6]=out_v/10%10;
  106.                                 seg_buf[7]=out_v%10;
  107.                                 seg_point[5]=1;
  108.                                 da_write(out_v*16);
  109.                         }
  110.                         else
  111.                         {
  112.                                 if(temp_temp<=20)
  113.                                         out_v=1;
  114.                                 else if(temp_temp>=40)
  115.                                         out_v=4;
  116.                                 else
  117.                                         out_v=temp_temp*3/20;
  118.                                 seg_buf[5]=out_v/100;
  119.                                 seg_buf[6]=out_v/10%10;
  120.                                 seg_buf[7]=out_v%10;
  121.                                 seg_point[5]=1;
  122.                                 da_write(out_v*16);
  123.                         }
  124.                         break;
  125.         }
  126. }

  127. void led_proc()
  128. {
  129.         led_buf[0]=(mode==0);
  130.         led_buf[1]=(show_mo==0);
  131.         led_buf[2]=(show_mo==1);
  132.         led_buf[3]=(show_mo==2);
  133. }

  134. void Timer0Init(void)                //1??@12.000MHz
  135. {
  136.         TMOD &= 0xF0;                //???????
  137.         TL0 = 0x18;                //??????
  138.         TH0 = 0xFC;                //??????
  139.         TF0 = 0;                //??TF0??
  140.         TR0 = 1;                //???0????
  141.         ET0 = 1;
  142.         EA =1;
  143. }

  144. void timer() interrupt 1
  145. {
  146.         if(++key_sld==10)
  147.                 key_sld=0;
  148.         if(++seg_sld==1000)
  149.                 seg_sld=0;
  150.         if(++seg_pos==8)
  151.                 seg_pos=0;
  152.         
  153.         segdis(seg_buf[seg_pos],seg_pos,seg_point[seg_pos]);
  154.         led_disp(seg_pos,led_buf[seg_pos]);
  155. }


  156. void main()
  157. {
  158.         Timer0Init();
  159.         init();
  160.         while(1)
  161.         {
  162.                 key_proc();
  163.                 seg_proc();
  164.                 led_proc();
  165.         }
  166. }
复制代码
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1058641 发表于 2024-2-23 21:12 | 只看该作者
就是这种

屏幕截图 2024-02-23 211158.png (89.17 KB, 下载次数: 102)

屏幕截图 2024-02-23 211158.png
回复

使用道具 举报

板凳
ID:123289 发表于 2024-2-24 09:53 | 只看该作者
扫描方案不合理。
回复

使用道具 举报

地板
ID:123289 发表于 2024-2-24 09:57 | 只看该作者
扫屏显示的切换应当用最少的指令完成,在不多于8个LED的情况下:三条指令即可完成,对于STC的单片机,10us不到就完成了,例:8个LED哪个亮(位选)受P1控制,显示什么内容(段码)由P0决定。
要点:技巧如下!!!
先将哪个LED需要亮的参数事先准备好,放在:P1_OUT变量中,同样将这个LED需要显示的段码放在P0_OUT中。【这个做法最关键,不要直接切换操作P0、P1口,而是通过这两个变量来操作。原因是,无论你用多长时间对P1_OUT、P0_OUT进行操作,操作期间,显示不受影响。】
切换:
第一条指令:关断所有显示:P1=FFH              ;关闭所有显示
第二条指令:切换LED段码:P0=P0_OUT         ;这时显示已关,切换不会有残留,重影,闪烁了。
第三条指令:更新显示的LED管:P1=P1_OUT  ;点亮需要显示的LED,例如:11101111B
【这个做法是最优秀的扫描显示切换方法,用时最短,最合理,没有之二!!!】
重复一下关键点:事先处理准备好变量P1_OUT、P0_OUT的值。

以上供参考,请根据你的接口来操作,这里的P0、P1不一定与你的图相同。
回复

使用道具 举报

5#
ID:1110945 发表于 2024-2-24 10:18 | 只看该作者
8个数码管实际就是64个发光二极管,可是控制它的引线只有16根。
实际上同一时间只能显示其中的一个数码管,8个数码管分时轮流显
示,只要切换的时间足够快,人眼就能感觉到8个数码管在同时显示
数字了。数码管有段码表,还有共阴或共阳的区别。其中任何一个环
节出错了那么显示的数字就是乱的。
回复

使用道具 举报

6#
ID:1109793 发表于 2024-2-24 12:28 | 只看该作者
电路好复杂,这是买的谁家的实验板吗?看代码挺费劲,也没有注释,好像没看到驱动代码,只是在计算一些BCD码。先不要计算,只给缓冲区里面固定的数据看,如果还是闪,就是驱动部分了
回复

使用道具 举报

7#
ID:1058641 发表于 2024-2-24 14:47 | 只看该作者
yzwzfyz 发表于 2024-2-24 09:57
扫屏显示的切换应当用最少的指令完成,在不多于8个LED的情况下:三条指令即可完成,对于STC的单片机,10us ...

不太明白
回复

使用道具 举报

8#
ID:1109793 发表于 2024-2-24 16:27 | 只看该作者
闪烁是怎样的也看不到。代码也不全。
回复

使用道具 举报

9#
ID:213173 发表于 2024-2-24 17:30 | 只看该作者

楼主搞了这么长时间数码管还搞不定,情何以堪。前面的帖子给你的示例认真看了吗?这是坛友画的仿真图,写个时钟程序给你试试。
仿真.rar (46.5 KB, 下载次数: 1)

  1. #include "reg52.h"
  2. #include "intrins.h"

  3. sbit key1=P3^0;
  4. sbit key2=P3^1;
  5. sbit key3=P3^2;
  6. sbit GND =P3^7;

  7. unsigned char code smgdata[]={
  8. 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,
  9. 0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xbf,0x8c};
  10. unsigned char  data dis_buf[8];
  11. unsigned int temp,Cnt2ms;
  12. char H=12,M=30,S=0;//时分秒
  13. unsigned char KeySec;//键值
  14. bit flag;//中断标志
  15. bit flicker;//闪烁标志
  16. void keyscan()
  17. {
  18.         static char time=0;
  19.         static bit sign=0;
  20.         if(!key1||!key2||!key3)
  21.         {
  22.                 if(++time>=20 && sign==0)//短按消抖
  23.                 {
  24.                         sign=1;
  25.                         if(!key1)KeySec=++KeySec%4;
  26.                         if(!key2 && KeySec!=0)
  27.                         {
  28.                                 switch(KeySec)
  29.                                 {
  30.                                         case 1: if(++H>23)H=0; break;
  31.                                         case 2: if(++M>59)M=0; break;
  32.                                         case 3: if(++S>59)S=0; break;
  33.                                 }
  34.                         }
  35.                         if(!key3 && KeySec!=0)
  36.                         {
  37.                                 switch(KeySec)
  38.                                 {
  39.                                         case 1: if(--H<0)H=23; break;
  40.                                         case 2: if(--M<0)M=59; break;
  41.                                         case 3: if(--S<0)S=59; break;
  42.                                 }
  43.                         }
  44.                         Cnt2ms=0;
  45.                 }
  46.         }
  47.         else {time=0;sign=0;}
  48. }


  49. void Timer0_Init(void)                //2毫秒@11.0592MHz
  50. {
  51.         TMOD |= 0x01;                        //设置定时器模式
  52.         TL0 = 0xCD;                                //设置定时初始值
  53.         TH0 = 0xF8;                                //设置定时初始值
  54.         TF0 = 0;                                //清除TF0标志
  55.         TR0 = 1;                                //定时器0开始计时
  56.         ET0 = 1;                                //使能定时器0中断
  57.         EA  = 1;
  58. }

  59. void main()
  60. {
  61.         unsigned char i,j;
  62.         GND=0;//模拟地
  63.         Timer0_Init();
  64.         while (1)
  65.         {
  66.                 if(flag)
  67.                 {
  68.                         flag=0;
  69.                         P0=0xff;       P2=0xe0; P2=0x00;//段消影
  70.                         P0=0x01<<i;    P2=0xd0; P2=0x00;//传位码
  71.                         P0=dis_buf[i]; P2=0xe0; P2=0x00;//传段码
  72.                         keyscan();
  73.                         if(++j==100){j=0;flicker=~flicker;}
  74.                         if(KeySec==0)Cnt2ms++;
  75.                         if(Cnt2ms>=500)//秒
  76.                         {
  77.                                 Cnt2ms=0;
  78.                                 S++;
  79.                                 if(S>=60){S=0;M++;}
  80.                                 if(M>=60){M=0;H++;}
  81.                                 if(H>=24)H=0;
  82.                         }
  83.                         switch(i)
  84.                         {
  85.                                 case 0: dis_buf[0]=smgdata[H/10]; break;
  86.                                 case 1: dis_buf[1]=smgdata[H%10]; break;
  87.                                 case 2: dis_buf[2]=0xbf; break;//"-"
  88.                                 case 3: dis_buf[3]=smgdata[M/10]; break;
  89.                                 case 4: dis_buf[4]=smgdata[M%10]; break;
  90.                                 case 5: dis_buf[5]=0xbf; break;//"-"
  91.                                 case 6: dis_buf[6]=smgdata[S/10]; break;
  92.                                 case 7: dis_buf[7]=smgdata[S%10]; break;

  93.                         }      
  94.                         i=++i%8;//循环计数
  95.                         if(KeySec==1 && flicker){dis_buf[0]=dis_buf[1]=0xff;}//时闪烁
  96.                         if(KeySec==2 && flicker){dis_buf[3]=dis_buf[4]=0xff;}//分闪烁
  97.                         if(KeySec==3 && flicker){dis_buf[6]=dis_buf[7]=0xff;}//秒闪烁
  98.                 }
  99.         }
  100. }
  101. void Timer0_Isr(void) interrupt 1
  102. {
  103.         TL0 = 0xCD;                                //设置定时初始值
  104.         TH0 = 0xF8;                                //设置定时初始值
  105.         flag=1;
  106. }
复制代码




回复

使用道具 举报

10#
ID:1058641 发表于 2024-2-24 21:50 | 只看该作者
wulin 发表于 2024-2-24 17:30
楼主搞了这么长时间数码管还搞不定,情何以堪。前面的帖子给你的示例认真看了吗?这是坛友画的仿真图,写 ...

这是数码管部分的
unsigned char smgduan[]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0xff,0xc6,0x7c,0x88};

unsigned char segwei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

void segdis(unsigned char wei,unsigned char duan,unsigned char point)
{
        P0=0xff;
        P2=P2&0x1f|0xe0;
        P0=segwei[wei];
       
        P2=P2&0x1f|0xc0;
        P2&=0x1f;
        P0=smgduan[duan];
       
        if(point)
                P0&=0x7f;
       
        P2=P2&0x1f|0xe0;
        P2&=0x1f;
}
回复

使用道具 举报

11#
ID:213173 发表于 2024-2-25 06:20 | 只看该作者
rtyweq 发表于 2024-2-24 21:50
这是数码管部分的
unsigned char smgduan[]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,

P0分时复用通过573驱动数码管需要分3步:段消影、送位码、送段码。以本例硬件条件编写
  1.         P0=0xff; //P0赋段消影码
  2.         P2&=0x1f;//清P2高3位
  3.         P2|=0xe0;//传送消影段码
  4.         P2&=0x1f;//清P2高3位

  5.         P0=0x01<<i;//P0赋位码
  6.         P2&=0x1f;//清P2高3位
  7.         P2|=0xd0;//传送位码
  8.         P2&=0x1f;//清P2高3位

  9.         P0=dis_buf[i];//P0赋段码
  10.         P2&=0x1f;//清P2高3位
  11.         P2|=0xe0;//传送段码
  12.         P2&=0x1f;//清P2高3位
复制代码
回复

使用道具 举报

12#
ID:1058641 发表于 2024-2-25 11:46 | 只看该作者
wulin 发表于 2024-2-25 06:20
P0分时复用通过573驱动数码管需要分3步:段消影、送位码、送段码。以本例硬件条件编写
        P0=0xff; //P0赋 ...

还是不对劲,我把工程发给你能帮我看看吗
回复

使用道具 举报

13#
ID:1058641 发表于 2024-2-25 11:47 | 只看该作者
这是压缩包

十二.rar

46.38 KB, 下载次数: 9

回复

使用道具 举报

14#
ID:1109793 发表于 2024-2-25 13:15 | 只看该作者

问一下题外话,我鼠标指针指到文件名上面就出来一个黄颜色提示框,点击文件名下载,这个框挡住了文件名,点击也不能下载,是咋回事
回复

使用道具 举报

15#
ID:1058641 发表于 2024-2-25 14:34 | 只看该作者
球球了,真不知道咋回事了
回复

使用道具 举报

16#
ID:1058641 发表于 2024-2-25 15:58 | 只看该作者
有没有哪个大佬能帮我看一下啊
回复

使用道具 举报

17#
ID:1109793 发表于 2024-2-25 19:47 | 只看该作者

问一下,你这用什么打开?我用keil好像不行啊
回复

使用道具 举报

18#
ID:1058641 发表于 2024-2-25 20:43 | 只看该作者
就是keil啊keil5
回复

使用道具 举报

19#
ID:1058641 发表于 2024-2-25 20:44 | 只看该作者
我可以啊
回复

使用道具 举报

20#
ID:1109793 发表于 2024-2-26 07:23 | 只看该作者

真先进,我刚在这里下载了keil3和proteus,研究了一下,顺便问问,proteus能不能导入AD的原理图?
回复

使用道具 举报

21#
ID:213173 发表于 2024-2-26 09:45 | 只看该作者
rtyweq 发表于 2024-2-25 11:46
还是不对劲,我把工程发给你能帮我看看吗

初学阶段不要试图将学习板上的功能模块在一个工程里都实现。要由简入深循序渐进。充分掌握各模块功能后再将各功能模块组合到一个工程里就是水到渠成的事。
回复

使用道具 举报

22#
ID:161164 发表于 2024-2-26 09:48 | 只看该作者
rtyweq 发表于 2024-2-25 11:46
还是不对劲,我把工程发给你能帮我看看吗

如何不对劲?描述一下或录屏
把仿真档也上传
回复

使用道具 举报

23#
ID:1058641 发表于 2024-2-26 15:14 | 只看该作者
这是proteus的仿真,后面是录屏

蓝桥杯单片机仿真原理图 (2).rar

39.82 KB, 下载次数: 6

回复

使用道具 举报

24#
ID:1109793 发表于 2024-2-26 17:44 | 只看该作者
rtyweq 发表于 2024-2-26 15:14
这是proteus的仿真,后面是录屏

正好我用来学习一下proteus
回复

使用道具 举报

25#
ID:1109793 发表于 2024-2-26 17:46 | 只看该作者
rtyweq 发表于 2024-2-26 15:14
这是proteus的仿真,后面是录屏

怎么我在这里下载的proteus还是打不开你的这个文件呢?难道又是版本太低?
回复

使用道具 举报

26#
ID:1058641 发表于 2024-2-26 19:35 | 只看该作者
xiaobendan001 发表于 2024-2-26 17:46
怎么我在这里下载的proteus还是打不开你的这个文件呢?难道又是版本太低?

我是8.10的
回复

使用道具 举报

27#
ID:1109793 发表于 2024-2-27 08:10 | 只看该作者

我找了一个KEIL5怎么只有ARM的
回复

使用道具 举报

28#
ID:192020 发表于 2024-2-27 09:52 | 只看该作者
改的小问题,不够细心

十二_2.rar

52.3 KB, 下载次数: 1

回复

使用道具 举报

29#
ID:1058641 发表于 2024-2-27 12:25 | 只看该作者
qq475878026 发表于 2024-2-27 09:52
改的小问题,不够细心

那里的错唉
回复

使用道具 举报

30#
ID:1058641 发表于 2024-2-27 21:36 | 只看该作者
qq475878026 发表于 2024-2-27 09:52
改的小问题,不够细心

那里的问题唉
回复

使用道具 举报

31#
ID:192020 发表于 2024-2-28 09:07 | 只看该作者

中断里调用segdis函数的传参反了
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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