找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 580|回复: 22
收起左侧

关于单片机数码管消隐问题

[复制链接]
ID:1131511 发表于 2024-9-10 11:12 | 显示全部楼层 |阅读模式
应该是关于消隐的内容没有弄好,第七位数码管的数字看不到了,各位大佬能帮忙看看到底应该怎么改代码才能得到稳定的显示呢?

数码管第七位不显示
数码管第七位不显示且定时器进位也有问题.PNG

单片机源程序如下:
  1. #include<stc15.h>
  2. #define uChar unsigned char
  3. #define uInt unsigned int
  4. uChar a[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //共阴0.1.2.3.4.5.6.7.8.9
  5. uChar b[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //不断进1位
  6. uChar second=46,minute=59,hour=12,year=24,month=9,day=17,count;

  7. sbit Key1 = P2^0; //计时停止
  8. sbit Key2 = P2^1; //调位
  9. sbit Key3 = P2^2; //加一
  10. sbit Key4 = P2^3; //切换  
  11. sbit Buzzer=P5^4;
  12. /*********************延迟函数********************/
  13. void Delay(uInt t)
  14. {
  15. while(t)
  16. {
  17. t--;
  18. }
  19. }
  20. /*********************时分秒显示函数*******************/
  21. void Dispaly1(uChar second,uChar minute,uChar hour)
  22. {
  23. /*********************第一位数码管*********************/
  24. P1=b[0];
  25. P0=a[hour/10];
  26. Delay(10);
  27. /*********************第二位数码管*********************/
  28. P1=b[1];
  29. P0=a[hour%10];
  30. Delay(10);
  31. /*********************第三位数码管*********************/
  32. P1=b[2];
  33. P0=0x40;
  34. Delay(10);
  35. /*********************第四位数码管*********************/
  36. P1=b[3];
  37. P0=a[minute/10];
  38. Delay(10);
  39. /*********************第五位数码管*********************/
  40. P1=b[4];
  41. P0=a[minute%10];
  42. Delay(10);
  43. /*********************第六位数码管*********************/
  44. P1=b[5];
  45. P0=0x40;
  46. Delay(10);
  47. /*********************第七位数码管*********************/
  48. P1=b[6];
  49. P0=a[second/10];
  50. Delay(10);
  51. /*********************第八位数码管*********************/
  52. P1=b[7];
  53. P0=a[second%10];
  54. Delay(10);
  55. }
  56. /*********************年月日显示函数********************/
  57. void Dispaly2(uChar day,uChar month,uChar year)
  58. {
  59. P1=b[0];
  60. P0=a[day/10];
  61. Delay(10);

  62. P1=b[1];
  63. P0=a[day%10];
  64. Delay(10);

  65. P1=b[2];
  66. P0=0x40;
  67. Delay(10);

  68. P1=b[3];
  69. P0=a[month/10];
  70. Delay(10);

  71. P1=b[4];
  72. P0=a[month%10];
  73. Delay(10);

  74. P1=b[5];
  75. P0=0x40;
  76. Delay(10);

  77. P1=b[6];
  78. P0=a[year/10];
  79. Delay(10);

  80. P1=b[7];
  81. P0=a[year%10];
  82. Delay(10);
  83. }


  84. /*********************时钟按键扫描函数*********************/
  85. void Keyscan1()
  86. {
  87. static uChar i=0,j=0;
  88. if(Key1==0)
  89. {
  90. Delay(10); //消抖
  91. if(Key1==0)
  92. while(!Key1); //等待按键弹
  93. i++;
  94. }
  95. /*时钟暂停功能*/
  96. if(i%2==1)
  97. {
  98. TR0=0;/*如果是奇数次按键自然关闭定时器0*/
  99. }
  100. if(i%2==0)
  101. {
  102. TR0=1;/*如果是偶数次按键则打开定时器0*/
  103. }
  104. /*时钟调位和数值加一功能*/
  105. if(Key2==0)
  106. {
  107. Delay(10);
  108. if(Key2==0)
  109. while(!Key2);
  110. j++;
  111. }
  112. if(j%4==1)  //调秒的时间
  113. {
  114. if(Key3==0)
  115. {
  116. Delay(10);
  117. if(Key3==0)
  118. while(!Key3);
  119. second++;
  120. if(second==60)
  121. second=0;
  122. }
  123. }
  124. if(j%4==2)  //调分的时间
  125. {
  126. if(Key3==0)
  127. {
  128. Delay(10);
  129. if(Key3==0)
  130. while(!Key3);
  131. minute++;
  132. if(minute==60)
  133. minute=0;
  134. }
  135. }
  136. if(j%4==3) //调时的时间
  137. {
  138. if(Key3==0)
  139. {
  140. Delay(10);
  141. if(Key3==0)
  142. while(!Key3);
  143. hour++;
  144. if(hour==24)
  145. hour=0;
  146. }
  147. }
  148. }
  149. /*********************日期按键扫描函数*********************/
  150. void Keyscan2()
  151. {
  152. static uChar m=0,n=0;
  153. if(Key1==0)
  154. {
  155. Delay(10);
  156. if(Key1==0)
  157. while(!Key3);
  158. m++;
  159. }
  160. if(m%2==1)
  161. {
  162. TR0=0;/*奇数次按键则关闭定时器0*/
  163. }

  164. if(m%2==0)
  165. {
  166. TR0=1;/*偶数次按键则打开定时器0*/
  167. }
  168. if(Key2==0)
  169. {
  170. Delay(10);
  171. if(Key2==0)
  172. while(!Key2);
  173. n++;
  174. }
  175. /*日期调位和日期加一功能*/
  176. if(n%4==1)
  177. {
  178. if(Key3==0)
  179. {
  180. Delay(10);
  181. if(Key3==0)
  182. while(!Key3);
  183. day++;
  184. if(day==30)
  185. day=0;
  186. }
  187. }
  188. if(n%4==2)
  189. {
  190. if(Key3==0)
  191. {
  192. Delay(10);
  193. if(Key3==0)
  194. while(!Key3);
  195. month++;
  196. if(month==12)
  197. month=0;
  198. }
  199. }
  200. if(n%4==3)
  201. {
  202. if(Key3==0)
  203. {
  204. Delay(10);
  205. if(Key3==0)
  206. while(!Key3);
  207. year++;
  208. if(year==99)
  209. year=0;
  210. }
  211. }
  212. }

  213. /************************************************/
  214. /***************主函数***************************/
  215. /************************************************/
  216. void main()
  217. {                                                
  218. TMOD=0x01;          /*定时器以方式一工作*/
  219. TH0=(65536-10000)/256;
  220. TL0=(65536-10000)%256;/*10ms计时*/
  221. ET0=1;/*允许定时器0中断*/
  222. EA=1;
  223. TR0=1;/*打开定时器0*/
  224. while(1)
  225. {
  226. static uChar h=0;
  227. /*时钟和日期切换功能*/
  228. if(Key4==0)
  229. {
  230. Delay(10);
  231. if(Key4==0)
  232. while(!Key4);
  233. h++;
  234. }
  235. if(h%2==0)/*如果按键偶数次则显示时钟*/
  236. {
  237. Dispaly1(second,minute,hour);
  238. Keyscan1();
  239. }

  240. if(h%2==1)/*如果按键奇数次则显示日期*/
  241. {
  242. Dispaly2(year,month,day);
  243. Keyscan2();
  244. }
  245. }
  246. }

  247. /**********************中断函数**************************/
  248. void time0_int(void) interrupt 1
  249. {
  250. TH0=(65536-10000)/256;
  251. TL0=(65536-10000)%256;
  252. count++;
  253. if(count==100)
  254. {
  255. count=0;
  256. second++;
  257. if(second==60)
  258. {
  259. second=0;
  260. minute++;
  261. if(minute==60)
  262. {
  263. minute=0;
  264. hour++;
  265. if(hour==24)
  266. {
  267. hour=0;
  268. day++;
  269. if(day==30)
  270. {
  271. day=0;
  272. month++;
  273. if(month==12)
  274. {
  275. month=0;
  276. year++;
  277. if(year==99)
  278. {
  279. year=0;
  280. }
  281. }
  282. }                  
  283. }
  284. }
  285. }
  286. }
  287. /*判断整点提醒*/
  288. if(second==00&&minute==00)                                                                  
  289. Buzzer=0;
  290. else
  291. Buzzer=1;
  292. }
复制代码

回复

使用道具 举报

ID:1131511 发表于 2024-9-10 11:49 | 显示全部楼层
我后面发现应该是延时的问题,但是当我把延时增加到10000后,屏幕闪烁,这样它的频率在肉眼上就不够快且看着很难受,各位大佬有没有其他更加好的办法呢
回复

使用道具 举报

ID:1109793 发表于 2024-9-10 19:11 | 显示全部楼层
在delay(10)之后要换下一位显示之前要先消隐,比如在移位前先把段驱动P0=0;
要么delay(10)要么delay(10000),搞代码不要这极端。你还可以试试比如delay(100);
又或者使用定时器获得更好的效果。
回复

使用道具 举报

ID:468209 发表于 2024-9-10 19:38 来自手机 | 显示全部楼层
数码管应该用for循环显示 如:  for(i=0;i<8;i++) {      
回复

使用道具 举报

ID:468209 发表于 2024-9-10 19:38 来自手机 | 显示全部楼层
数码管应该用for循环显示 如:  for(i=0;i<8;i++) {      
回复

使用道具 举报

ID:344848 发表于 2024-9-10 21:02 | 显示全部楼层
qiuqiubuyao 发表于 2024-9-10 11:49
我后面发现应该是延时的问题,但是当我把延时增加到10000后,屏幕闪烁,这样它的频率在肉眼上就不够快且看 ...

视觉暂留时间,它的长短因人而异,一般在50~200ms。
若数码管为N位,驱动位选的信号频率应大于N*50Hz。
回复

使用道具 举报

ID:462827 发表于 2024-9-10 23:34 | 显示全部楼层
你的数码管显示代码里根本就没有消影,还有,扫描的间隔/延时太短了
回复

使用道具 举报

ID:1131511 发表于 2024-9-11 08:13 | 显示全部楼层
xiaobendan001 发表于 2024-9-10 19:11
在delay(10)之后要换下一位显示之前要先消隐,比如在移位前先把段驱动P0=0;
要么delay(10)要么delay(10000 ...

感谢回复,我按照您的修改之后显示确实好了,之后秒数的时间又延长了,之后在定时器那里修改之后,时间问题也基本没有了,又或者有没有更好确定时间精度的办法呢
回复

使用道具 举报

ID:1131511 发表于 2024-9-11 08:18 | 显示全部楼层
1860774xxxx 发表于 2024-9-10 19:38
数码管应该用for循环显示 如:  for(i=0;i

感谢回复,虽然刚开始我也觉得用for会更加好,但是因为我的数据是分时分秒来着的,如果单单用for来表示b【i】的位置的话,代码长度也没有办法变短,反而看起来也不够直观,所以就直接这样显示了,或者您会有更好的使用方法。
回复

使用道具 举报

ID:1131713 发表于 2024-9-11 09:51 | 显示全部楼层
数码管的显示,要遵循先关闭,然后驱动segment,然后驱动com,所有共享segment的管都要先关闭,比如4个数字的,6个数字一起的,全部都先关闭com,最后所有数字配完再开com
回复

使用道具 举报

ID:1109793 发表于 2024-9-11 11:46 | 显示全部楼层
qiuqiubuyao 发表于 2024-9-11 08:13
感谢回复,我按照您的修改之后显示确实好了,之后秒数的时间又延长了,之后在定时器那里修改之后,时间问 ...

时间的操作还有用定时器吧,显示方面还好一些,建议使用专用的显示芯片
回复

使用道具 举报

ID:619259 发表于 2024-9-11 15:56 | 显示全部楼层
数码管动态显示程序中没有消隐程序行,在proteus仿真中会出现一些无序的乱码或意想不到的显示错误。
程序中8个数码管的程序段最后都要加上消隐,以第一个数码管为例:
原程序为:
P1=b[0];
P0=a[hour/10];
Delay(10);
加上消隐后程序应为(增加一行):
P1=b[0];
P0=a[hour/10];
Delay(10);
P0=0x00;

另外8个数码管的总延时时间不要超过20ms,所以每一个数码管的延时建议选用1ms-2ms为宜。
回复

使用道具 举报

ID:57657 发表于 2024-9-11 18:27 | 显示全部楼层
是否需要消隐看IO口并行位宽,51单片机为8位并行IO,段码和位码做不到并行发送,所以需要消影处理(先关闭前一位再打开下一位),是否显示正常以实物验证为准。
用74HC595或273并行锁存发送、FPGA、16位并行IO的单片机驱动 8位8段数码管或8*8点阵不需要消影。
回复

使用道具 举报

ID:468209 发表于 2024-9-11 19:19 | 显示全部楼层
qiuqiubuyao 发表于 2024-9-11 08:18
感谢回复,虽然刚开始我也觉得用for会更加好,但是因为我的数据是分时分秒来着的,如果单单用for来表示b ...

#include <STC89C5xRC.H>//此文件中定义了单片机的一些特殊功能寄存器


typedef unsigned char u8;   //无符号字符形数据类型进行声明定义 定义名称u8 所占位数8位 范围0~255
typedef unsigned int u16;   //无符号整形数据类型进行声明定义 定义名称u16 所占位数16位 范围0~65535

u8 code ma[11]= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //数字"0123456789-" 共阴
u8 code wei[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; //位 第一位开始点亮 0x7f  0111 1111 .........
u8 wei_num[8]; //存储记录数码管8个段码位的值 要发送数字到哪一位的暂存区

u8 shi,fen,miao; //时 分 秒 变量


/*12T 12M晶振 延时函数 Delay_ms(1)时大约1ms*/
void Delay_ms(u16 ms)
{
    u8 t;
    while(ms--)
    {
        for(t = 0; t < 98; t ++);
    }
}

/*主函数*/
void main()
{
        u8 i;
    while(1)
    {
                  /*数码管显示处理*/
        wei_num[7]=ma[shi%100/10];  //显示 时
        wei_num[6]=ma[shi%10];      //
        wei_num[5]=ma[10];          //显示"-"
        wei_num[4]=ma[fen%100/10];  //显示 分
        wei_num[3]=ma[fen%10];      //
        wei_num[2]=ma[10];          //显示"-"
        wei_num[1]=ma[miao%100/10]; //显示 秒
        wei_num[0]=ma[miao%10];     //
               
                 for(i=0; i<8; i++)
        {
            P0=wei_num; //发送段码
                        P2=wei;     //位
            Delay_ms(1); //间隔一段时间扫描
            P0=0x00;//消隐
        }
    }
}

难道这样还不够明朗吗 加上定时器加上按键就可以了  再说你那按键用while(!xx); 按键按下是会卡死 数码管消灭
回复

使用道具 举报

ID:468209 发表于 2024-9-11 19:45 来自手机 | 显示全部楼层
1860774xxxx 发表于 2024-9-11 19:19
#include //此文件中定义了单片机的一些特殊功能寄存器



P0=wei_num; //发送段码
P2=wei;// 位
这里写漏了
回复

使用道具 举报

ID:1109793 发表于 2024-9-11 19:49 | 显示全部楼层
1860774xxxx 发表于 2024-9-11 19:19
#include //此文件中定义了单片机的一些特殊功能寄存器

P0=wei_num; //发送段码
P0=wei_num; //发送段码
回复

使用道具 举报

ID:468209 发表于 2024-9-11 22:20 来自手机 | 显示全部楼层
xiaobendan001 发表于 2024-9-11 19:49
P0=wei_num; //发送段码
P0=wei_num; //发送段码

我也不知道为什么 后面的i看不到
IMG_20240911_221824.jpg
回复

使用道具 举报

ID:1109793 发表于 2024-9-12 07:22 | 显示全部楼层
1860774xxxx 发表于 2024-9-11 22:20
我也不知道为什么 后面的i看不到

可能需要使用代码功能吧
我发的第二行也有括弧的,实际上是没有的
回复

使用道具 举报

ID:1109793 发表于 2024-9-12 07:35 | 显示全部楼层
  1. #include <STC89C5xRC.H>//此文件中定义了单片机的一些特殊功能寄存器


  2. typedef unsigned char u8;   //无符号字符形数据类型进行声明定义 定义名称u8 所占位数8位 范围0~255
  3. typedef unsigned int u16;   //无符号整形数据类型进行声明定义 定义名称u16 所占位数16位 范围0~65535

  4. u8 code ma[11]= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //数字"0123456789-" 共阴
  5. u8 code wei[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; //位 第一位开始点亮 0x7f  0111 1111 .........
  6. u8 wei_num[8]; //存储记录数码管8个段码位的值 要发送数字到哪一位的暂存区

  7. u8 shi,fen,miao; //时 分 秒 变量


  8. /*12T 12M晶振 延时函数 Delay_ms(1)时大约1ms*/
  9. void Delay_ms(u16 ms)
  10. {
  11.     u8 t;
  12.     while(ms--)
  13.     {
  14.         for(t = 0; t < 98; t ++);
  15.     }
  16. }

  17. /*主函数*/
  18. void main()
  19. {
  20.         u8 i;
  21.     while(1)
  22.     {
  23.                   /*数码管显示处理*/
  24.         wei_num[7]=ma[shi%100/10];  //显示 时
  25.         wei_num[6]=ma[shi%10];      //
  26.         wei_num[5]=ma[10];          //显示"-"
  27.         wei_num[4]=ma[fen%100/10];  //显示 分
  28.         wei_num[3]=ma[fen%10];      //
  29.         wei_num[2]=ma[10];          //显示"-"
  30.         wei_num[1]=ma[miao%100/10]; //显示 秒
  31.         wei_num[0]=ma[miao%10];     //
  32.                
  33.                  for(i=0; i<8; i++)
  34.         {
  35.             P0=wei_num; //发送段码
  36.                         P2=wei;     //位
  37.             Delay_ms(1); //间隔一段时间扫描
  38.             P0=0x00;//消隐
  39.         }
  40.     }
  41. }
复制代码
回复

使用道具 举报

ID:1109793 发表于 2024-9-12 13:05 | 显示全部楼层

开来就是被系统删除了
  1. #include <STC89C5xRC.H>//此文件中定义了单片机的一些特殊功能寄存器


  2. typedef unsigned char u8;   //无符号字符形数据类型进行声明定义 定义名称u8 所占位数8位 范围0~255
  3. typedef unsigned int u16;   //无符号整形数据类型进行声明定义 定义名称u16 所占位数16位 范围0~65535

  4. u8 code ma[11]= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //数字"0123456789-" 共阴
  5. u8 code wei[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; //位 第一位开始点亮 0x7f  0111 1111 .........
  6. u8 wei_num[8]; //存储记录数码管8个段码位的值 要发送数字到哪一位的暂存区

  7. u8 shi,fen,miao; //时 分 秒 变量


  8. /*12T 12M晶振 延时函数 Delay_ms(1)时大约1ms*/
  9. void Delay_ms(u16 ms)
  10. {
  11.     u8 t;
  12.     while(ms--)
  13.     {
  14.         for(t = 0; t < 98; t ++);
  15.     }
  16. }

  17. /*主函数*/
  18. void main()
  19. {
  20.         u8 i;
  21.     while(1)
  22.     {
  23.                   /*数码管显示处理*/
  24.         wei_num[7]=ma[shi%100/10];  //显示 时
  25.         wei_num[6]=ma[shi%10];      //
  26.         wei_num[5]=ma[10];          //显示"-"
  27.         wei_num[4]=ma[fen%100/10];  //显示 分
  28.         wei_num[3]=ma[fen%10];      //
  29.         wei_num[2]=ma[10];          //显示"-"
  30.         wei_num[1]=ma[miao%100/10]; //显示 秒
  31.         wei_num[0]=ma[miao%10];     //
  32.                
  33.                  for(i=0; i<8; i++)
  34.         {
  35.             P0=wei_num[i]; //发送段码
  36.                         P2=wei[i];     //位
  37.             Delay_ms(1); //间隔一段时间扫描
  38.             P0=0x00;//消隐
  39.         }
  40.     }
  41. }
复制代码
回复

使用道具 举报

ID:849913 发表于 2024-9-15 20:20 | 显示全部楼层

        P0M0 = 0x00;
    P0M1 = 0x00;
    P1M0 = 0x00;
    P1M1 = 0x00;
    P2M0 = 0x00;
    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x00;
    P5M0 = 0x00;
    P5M1 = 0x00;
   设置有关系吧
回复

使用道具 举报

ID:849913 发表于 2024-9-17 23:27 | 显示全部楼层
想请教一下你的stc单片机是怎么加到软件里的 我的软件里没有这个
回复

使用道具 举报

ID:1109793 发表于 2024-9-18 07:26 | 显示全部楼层
老董 发表于 2024-9-17 23:27
想请教一下你的stc单片机是怎么加到软件里的 我的软件里没有这个

STC的工具软件里面有个按键
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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