读懂了别人正确有效的电路和程序,才能找出自己电路和程序的错误 |
wc86110 发表于 2016-6-10 00:58 这个当然!电路与程序是相配的,程序是根据电路和功能编写的,任何案例都是如此。 |
yzwzfyz 发表于 2016-6-9 11:40 请看一下我的回复。 |
你的仿真图只能使用采用的数码管段码。 |
时钟动态显示电路,并保留时钟修正及修正位快速闪烁功能,我下一次编一个。 |
若仅仅是6位时钟,没有修正及修正位快速闪烁功能,电路可简单的多。 |
实际电路应该加限流电阻,不过无论是595、还是80C51,实际流不出很大电流的,长期工作也不会使芯片过热。 |
至于没有限流电阻,那是为了电路图面简洁,连晶振和复位电路都没画。 |
本帖最后由 zl2168 于 2016-6-9 17:58 编辑 "驱动用了P1,P3两个口,不利于程序编写",完全没有这个问题,看你程序怎么编写。P3口是串行传送数据,P1口是位控加修正位快速闪烁。 |
本帖最后由 zl2168 于 2016-6-9 18:00 编辑 用6片595的另一好处是,便于修正时钟参数。而且修正位是快速闪烁(每秒亮暗各5次),修正期间时钟继续正常运行 。你Proteus仿真一下,试试效果。 |
若用动态显示,7段加6位位控,需13根I/O端口线。因为不排除剩余端口线还需其他用途。 |
本电路设计为静态显示,虽然用了6片595,但595价格低廉。用595的好处是串行传送,节省了I/O端口。 |
有人与我讨论电路,很高兴,首先表示感谢,并希望能交个朋友。有关问题我的看法如下: |
写书的人不一定认真。 U2-U7驱动的LED 7个段,都未限流,都是错误的做法。 |
上图的设计不是很好的:缺点如下: 1、用了6个(U2-U7),不经济。 改进,用一个晶体管阵列(一个IC里集成有7个三极管),驱动LED的阳极(共阳)。 2、LED的选择驱动用了P1,P3两个口,不利于程序编写。 改进,只用P1口驱动,这里软件编写方便许多。 3、四个发光二极管,两两串并,一般红色压降为1.4V,两只2.8V,未经限流直接接到IO口,使得2.2V电压(5V-2.8V)加在CPU的芯片上,CPU发热大。 改进:设LED是10mA一只。两组并为20mA,串入一只电阻[R=(5V-2.8V-0.3V)/20=100欧,0.3V是IO口的压降]。 |
先Proteus仿真一下![]() 以上摘自张志良编著《单片机实验实训100例》 ISBN 978-7-5124-1603-1,北航社出版 |
你的程序没有定义标记和注释,别人需花多少时间才能读懂理顺,然后再帮你寻找错误,可能吗? |
张志良编著《单片机实验实训100例》每个案例程序均有详细分析,每条语句均有注释。 |
读懂了别人正确有效的电路和程序,才能找出自己电路和程序的错误。 |
楼上的5种电子钟摘自张志良编著《单片机实验实训100例》 ISBN 978-7-5124-1603-1,北航社出版 |
参考一下楼上的5种电子钟电路、程序和仿真 |
linlin2222 发表于 2016-6-7 17:55 已经标注了 大神帮我看看吧 |
yzwzfyz 发表于 2016-6-8 10:50 我上传了标注的程序和电路图了 他上面不是定义了 StrTab[0]=tab[hour/10]; StrTab[1]=tab[hour%10]; StrTab[2]=0x40; StrTab[3]=tab[minute/10]; StrTab[4]=tab[minute%10]; StrTab[5]=0x40; StrTab[6]=tab[second/10]; StrTab[7]=tab[second%10]; 改变NUM就好了 |
#include<reg51.h> sbit KEY1=P1^0; //定义端口参数 sbit KEY2=P1^1; sbit KEY3=P1^2; sbit LED=P2^2; //定义指示灯 code unsigned char tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //共阴极数码管0-9 unsigned char StrTab[8]; //定义缓冲区 unsigned char minute=19,hour=23,second; //定义初始化 void delay(unsigned int cnt) { while(--cnt); } void displaypro(void) { StrTab[0]=tab[hour/10]; //显示小时 StrTab[1]=tab[hour%10]; StrTab[2]=0x40; //显示- StrTab[3]=tab[minute/10]; //显示分钟 StrTab[4]=tab[minute%10]; StrTab[5]=0x40; //显示- StrTab[6]=tab[second/10]; //显示秒 StrTab[7]=tab[second%10]; } main() { TMOD |=0x01; //定时器0 10ms 用于计时 TH0=0xd8; //初始值 TL0=0xf0; ET0=1; TR0=1; TMOD |=0x10; //定时器1 动态扫描 TH1=0xf8; TL1=0xf0; ET1=1; TR1=1; EA=1; displaypro(); //调用显示处理函数 while(1) { if(!KEY3) { delay(10000); if(!KEY3) //按键3去抖以及动作 { hour++; if(hour==24) hour=0; displaypro(); } } if(!KEY2) //按键2去抖以及动作 { delay(10000); if(!KEY2) { minute++; if(minute==60) minute=0; displaypro(); } } if(!KEY1) { delay(10000); if(!KEY1) //按键1去抖以及动作 { second++; if(second==60) second=0; displaypro(); } } } } //定时器1中断// void time1_isr(void)interrupt 3 using 0 //定时器1动态扫描 { static unsigned char num; TH1=0xf8; TL1=0xf0; switch(num) { case 0:P3=0xfe;P0=StrTab[num];break; //分别调用缓冲区的值进行扫描 case 1:P3=0xfd;P0=StrTab[num];break; case 2:P3=0xfb;P0=StrTab[num];break; case 3:P3=0xf7;P0=StrTab[num];break; case 4:P3=0xef;P0=StrTab[num];break; case 5:P3=0xdf;P0=StrTab[num];break; case 6:P3=0xbf;P0=StrTab[num];break; case 7:P3=0x7f;P0=StrTab[num];break; default:break; } num++; //扫描8次,使用8个数码管 if(num==8) num=0; } //定时器0// void time(void)interrupt 1 using 1 { static unsigned char count; //定义内部局部变量 TH0=0xd8; TL0=0xf0; count++; switch(count) { case 0: case 20: case 40: case 60: case 80:displaypro();break; //隔一定时间调用显示处理显示处理 case 50:P1=~P1;break; //半秒 LED 闪烁 default:break; } if(count==100) { count=0; second++; if(second==60) { second=0; minute++; if(minute==60) { minute=0; hour++; if(hour==24) hour=0; } } } } |
case 0:P3=0xfe;P0=StrTab[num];break; case 1:P3=0xfd;P0=StrTab[num];break; case 2:P3=0xfb;P0=StrTab[num];break; case 3:P3=0xf7;P0=StrTab[num];break; case 4:P3=0xef;P0=StrTab[num];break; case 5:P3=0xdf;P0=StrTab[num];break; case 6:P3=0xbf;P0=StrTab[num];break; case 7:P3=0x7f;P0=StrTab[num];break; 这是T1中断所做的事,虽然每次切换了LED,但显示的内容却是相同的StrTab[num],这就必须保证,在每次中断之前,StrTab[num]已被刷新,仅改变num是不够的,因为显示的不是num,而是StrTab[num]! 如果某一次中断前未刷新,则轮显示的LED必定是上一轮的LED值,如此就混淆了。 你用两个时间中断的目的是什么?能保证正确地刷新LED数据么? |
要点:每次中断只显示一个LED,且先关后显示!!! |
先将各行的注释加上去,让别人知道你的目的,再看你错在哪里。 也许:当你完成注释时,自己就已经明白了。 |
yzwzfyz 发表于 2016-6-7 17:40 能不能帮我修改下程序 看哪里错了 |
重点需要强调出来, 别人能够很容易看懂 |
1、取8个RAM单元(编号X0至X7)对应存放8个LED的显示内容(译码后的LED段显示值)。 2、取一个单元做计数器K,从0至7循环计数,分别对应指示显示8个LED。 3、时间中断只用一个,考虑到8个LED扫描显示,中断时常数取5ms,中断后做下列事件: 3.1、处理一下计数器(屏上显示的数字,如时间年月日时分秒,或计数值等)…… 3.2、先关所有LED显示,防止切换闪动; 3.3、将K+1(注:当K=8时清K=0。),将K所指示的Xn(当然需要将对应需要显示的时钟位,译成LED码后再送入Xn)送入显示数据口,再打开K所指定的LED。 要点:每次中断只显示一个LED,且先关后显示。 |
写程序习惯不好,没有注释。 |
图不清楚 |
而且也不能正常计时 |