| 刚刚又看了一下你自己改的程序。 看来你还是没有深刻理解单片机工作方法,特别定时器这块。 你的display()函数里面有 delay(),这个delay()是多长时间? 定时器周期又是多久? 请仔细思考这个问题!!! |
Irvingzong 发表于 2020-7-16 10:23 楼上给你的display()函数是驱动8段数码管的程序, 而你的要求好像只是驱动某个BCD值模块的。 都不是一样的目标对象,你如何能改好。 我们做产品的,很少再用模块去辅助驱动8段数码管的,关于BCD值的模块,没有研究过,也没有现成的环境做试验,这里不好给你提供帮助。 但是,最终是驱动8段数码管,所以,以下程序备注很经典,你仔细读懂就会了。 void display() //显示子程序,从第一位开始逐位显示't 00秒 000毫秒' { P2&=0xc0;//位码清0消隐 P0=cnt[m];//送段码 P2|=0x01<<m;//送位码 m++; m%=6; } 步骤大概就是1,消隐; 2,送段码; 3,送位码; 4,改变循环值; 5,检查限定最大循环值。 |
robinsonlin 发表于 2020-7-15 16:21 大佬们帮我看下,设计框图规定了显示子程序,所以我把上面大佬的程序display()函数改了一下,可是运行时数据又乱了,请问是按照楼顶的框图应该怎么改? #include<reg51.h> #define uchar unsigned char #define uint unsigned int sbit A1=P3^4; sbit A2=P3^5; uint m=0; uint count,t,d,e,f; uchar code table[]={0x14,0xde,0x38,0x1a,0xd2,0x13,0x11,0x9e,0x10,0x12}; uchar cnt[6]={0};//小数缓存 bit flag=0; bit init=0; void delay(void) //误差 0us { unsigned char a,b,c; for(c=67;c>0;c--) for(b=124;b>0;b--) for(a=167;a>0;a--); } void start() { TMOD=0x01; //T0 使用工作方式 1 TH0=(65536-1000)/256; //1ms 定时 TL0=(65536-1000)%256; EA=1; ET0=1; TR0=1; } void display() //显示子程序,从第一位开始逐位显示't 00秒 000毫秒' { uint j; if(flag) P0=0xbf;//等待计数时显示'-' else { if(init==1) for(j=5;j>=0;j--) {P0=cnt[j]; delay(); } } } void main(void) { start(); P0=0xb7;//上电提示符 while(1) { if(A1==0 && flag==0) //按键扫描 { flag=1; count=0; t=0; init=1; } if(A2==0 && flag==1) { while(!A2); flag=0; cnt[5]=0xbf; cnt[4]=table[t/10]; cnt[3]=table[t%10];//加秒点 cnt[2]=table[count/100]; cnt[1]=table[count/10%10]; cnt[0]=table[count%10]; m=0; } } } void time0(void) interrupt 1 //T0 中断服务子程序 { TH0=(65536-1000)/256; TL0=(65536-1000)%256; if(flag) { count++; if(count>=1000) { count=0; t++; if(t>=60) { t=0; } } } display(); } |
wulin 发表于 2020-7-14 21:17 谢谢,不过设计要求用一位数码管,可是你第一个程序的display()函数我不是很能理解,能再解释一下吗 |
Irvingzong 发表于 2020-7-14 16:41 手把手教你学51单片机-C语言版 PDF电子书下载 http://www.51hei.com/bbs/dpj-48477-1.html (出处: 单片机论坛) 有C语言基础, 花3天时间看看就能弄明白了 |
Irvingzong 发表于 2020-7-14 16:45 转BCD码是软件层面的要求,可能是用来直接匹配到哪个模块,就可以直接驱动LED8段数码管了。 我跟你讲的是硬件层面的做法,直接用单片机的端口加三极管来驱动LED8段数码管的方法。 |
| 闪烁点可以用GP来制作,也可以用LED来闪烁,这就是基本的定时器应用 |
Irvingzong 发表于 2020-7-14 16:41 改成5或6位数码管显示较为合理
|
Irvingzong 发表于 2020-7-14 16:41 不同的显示设备需要不同的驱动码,LED数码管用的是16进制笔段码。如果非得转成BCD码后再转成笔段码就是自找麻烦了。不过楼主用一个数码管显示5位数也属特殊用法,未见有在实际运用中出现过。 |
本帖最后由 Irvingzong 于 2020-7-14 16:48 编辑 robinsonlin 发表于 2020-7-14 16:33 噢噢好的,师傅要求转成BCD码后译码用十进制显示输出,这个是怎么理解呢?我感觉没有用到BCD码呀 |
wulin 发表于 2020-7-14 12:31 感谢大佬!!另外框图要求转成BCD码后译码显示输出,你这个显示子程序是不是也算是符合呢? |
|
1,为什么要在没有时间定标的主循环中去控制定时器? 时钟就一直让它走,只去采集和记录就好了吗。 你乱控制主定时的TR0, 时间不乱才怪。 2, count++; if(count>=1) {count=0; t++; 这段是干啥? 实在无法理解。 3, 8段数码管输出的不是BCD码。是你那个table[]数组对应的控制值,而且这个值分阴码和阳码,根据你P0口的线序不同,这个控制值也会不同。(为什么要线序不同? 等你自己布线经验多一点就明白了) 你这个显示子程序,有点花。 不太容易懂的,也不利于你弄明白LED的显示原理。想弄明白,还是找教程看吧,论坛上就有的。 |
| 要不要把源文件发上来测试一下 |
完全下图做时间电路和程序,共阳数码管,可以实现楼主想要的功能。 A、B 键互锁,不需要消抖,用闪烁表示换显示位,否则相邻数字相同无法分辨。小数点前为妙,小数点后为毫秒。
|