有可能是鬼影,或者你两个数码管之间的延时太高造成的 |
我认为闪烁是刷新太慢的结果。 你需要以至少100Hz的频率刷新每个LED数位。 有时,你可以使用某种技巧来以相对较低的刷新率帮助减少严重的闪烁。 例如,我们可以选择一个顺序来刷新LED位数,例如同时刷新1、3和5,然后稍后再进行2、4和6。 这非常类似于电视隔行扫描方法。![]() ![]() ![]() |
消隐和延时,更改下试试 |
那个void display中改成这样:P2=0xfe;wela=1;wela=0;P2=0xff;P2=table[shi1];dula=1;dula=0;delay(2):其他类似同样改 |
数码管延时时间太长了。 |
sbit RX=P2^1; sbit TX=P2^0; //t,e定义超声波管教 unsignedint time=0; unsignedint timer=0; unsigned long S=0; bit flag =0; //测量标志 bit srFlag = 1; unsignedint a=100; unsignedint b=600; unsignedinta_o=100; unsignedintb_o=600; unsignedint mid; unsigned char iSW = 0; unsigned char uMode = 1; #define GPIO_DIG P0 sbit LSA=P2^2; sbit LSB=P2^3; sbit LSC=P2^4; unsigned char code DIG_CODE[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; unsigned char disbuff[8] ={0,0,0,0,0,0,0,0}; //电机IO #define GPIO_MOTOR P1 sbit F1 = P1^0; sbit F2 = P1^1; sbit F3 = P1^2; sbit F4 = P1^3; //按键IO sbit K1=P3^1; sbit K2=P3^0; sbit K3=P3^2; sbit K4=P3^3; unsigned char keyEx = 0; unsigned char code FFW[8]={0xf1,0xf3,0xf2,0xf6,0xf4,0xfc,0xf8,0xf9}; //反转顺序 unsigned char code FFZ[8]={0xf9,0xf8,0xfc,0xf4,0xf6,0xf2,0xf3,0xf1}; //正转顺序 unsigned char Direction,Speed; void Delay(unsigned int t); void Motor(); voidDigDisplay(); void Delay1ms() //?? 0us { unsigned char a,b,c; for(c=2;c>0;c--) for(b=38;b>0;b--) for(a=13;a>0;a--); } voidDigDisplay() { unsigned char i; unsignedint j; for(i=0;i<8;i++) { switch(i) //位选,选择点亮的数码管, { case(0): LSA=0;LSB=0;LSC=0; break;//显示第0位 case(1): LSA=1;LSB=0;LSC=0; break;//显示第1位 } |
/********************************************************************* * 实 验 名:超声波测距控制步进电机实验 *********************************************************************/ #include "reg52.h" #include <intrins.h> sbit RX=P2^1; sbit TX=P2^0; //t,e定义超声波管教 unsignedint time=0; unsignedint timer=0; unsigned long S=0; bit flag =0; //测量标志 bit srFlag = 1; unsignedint a=100; unsignedint b=600; unsignedinta_o=100; unsignedintb_o=600; unsignedint mid; unsigned char iSW = 0; unsigned char uMode = 1; #define GPIO_DIG P0 sbit LSA=P2^2; sbit LSB=P2^3; sbit LSC=P2^4; unsigned char code DIG_CODE[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; unsigned char disbuff[8] ={0,0,0,0,0,0,0,0}; //电机IO #define GPIO_MOTOR P1 sbit F1 = P1^0; sbit F2 = P1^1; sbit F3 = P1^2; sbit F4 = P1^3; //按键IO sbit K1=P3^1; sbit K2=P3^0; sbit K3=P3^2; sbit K4=P3^3; unsigned char keyEx = 0; unsigned char code FFW[8]={0xf1,0xf3,0xf2,0xf6,0xf4,0xfc,0xf8,0xf9}; //反转顺序 unsigned char code FFZ[8]={0xf9,0xf8,0xfc,0xf4,0xf6,0xf2,0xf3,0xf1}; //正转顺序 unsigned char Direction,Speed; void Delay(unsigned int t); void Motor(); voidDigDisplay(); void Delay1ms() //?? 0us { unsigned char a,b,c; for(c=2;c>0;c--) for(b=38;b>0;b--) for(a=13;a>0;a--); } voidDigDisplay() { unsigned char i; unsignedint j; for(i=0;i<8;i++) { switch(i) //位选,选择点亮的数码管, { case(0): LSA=0;LSB=0;LSC=0; break;//显示第0位 case(1): LSA=1;LSB=0;LSC=0; break;//显示第1位 case(2): LSA=0;LSB=1;LSC=0; break;//显示第2位 case(3): LSA=1;LSB=1;LSC=0; break;//显示第3位 case(4): LSA=0;LSB=0;LSC=1; break;//显示第4位 case(5): LSA=1;LSB=0;LSC=1; break;//显示第5位 case(6): LSA=0;LSB=1;LSC=1; break;//显示第6位 case(7): LSA=1;LSB=1;LSC=1; break;//显示第7位 //势能端 } GPIO_DIG=disbuff[i];//发送段码 j=10; //扫描间隔时间设定 while(j--); //延时 GPIO_DIG=0x00;//消隐 } } unsigned char scanKey(void) { // 如果此前没有按键 if(keyEx == 0 ) { if( K1 == 0 ) { keyEx = 1; // 有键按下 return 1; // 键值1表示阈值ab切换 } if( K2 == 0 ) { keyEx = 1; // 有键按下 return 2; // 键值2表示'+' } if( K3 == 0 ) { keyEx = 1; // 有键按下 return 3; // 键值3表示'-' } if( K4 == 0 ) { keyEx = 1; // 有键按下 return 4; // 键值4表示数位切换 } return 0; } else { if( K1 == 1 && K2 == 1 && K3 == 1 && K4 == 1 ) { keyEx = 0; // 等待没有按键后,按键保护值清0 } } return 0; } /********************************************************************* * 函 数 名:Motor * 函数功能:电机旋转函数 *********************************************************************/ void Motor() { unsigned char i; for(i=0;i<8;i++) { if(Direction==1) GPIO_MOTOR = FFW[i]&0x1f; //??? if(Direction==2) GPIO_MOTOR = FFZ[i]&0x1f; Delay(Speed); //???? } } void zd3() interrupt 3 //T1中断用来扫描数码管和计800MS启动模块 { TH1=0xf8; TL1=0x30; DigDisplay(); timer++; if(srFlag||timer>=100) //200ms 中断一次 { srFlag = 0; timer=0; TX=1; //至高点平 //800MS 启动一次模块 _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); //20us高电平 TX=0; } } /********************************************************************* * 函 数 名:main * 函数功能:主函数 *********************************************************************/ void main(void) { unsigned char i; Speed=15; TMOD=0x11; //设T0为方式1,GATE=1; TH0=0; TL0=0; //清0 TH1=0xf8; //2MS定时 TL1=0x30; ET0=1; //允许T0中断 ET1=1; //允许T1中断 TR1 = 0; EA = 0; while(scanKey() == 0 ) { disbuff[0] = DIG_CODE[4]; disbuff[1] = DIG_CODE[5]; disbuff[2] = DIG_CODE[0]; disbuff[3] = DIG_CODE[1]; disbuff[4] = DIG_CODE[0]; disbuff[5] = DIG_CODE[3]; disbuff[6] = DIG_CODE[1]; disbuff[7] = DIG_CODE[1]; DigDisplay(); } for(i=0;i<100;i++) { Delay1ms(); } if(uMode == 1 ) { TR1 = 1; EA = 1; } while(1) { if(uMode == 0 ) { disbuff[0] = DIG_CODE[a% 10]; disbuff[1] = DIG_CODE[(a / 10) % 10]; disbuff[2] = DIG_CODE[(a / 100) % 10]; disbuff[3] = DIG_CODE[(a / 1000) % 10]; disbuff[4] = DIG_CODE[b% 10]; disbuff[5] = DIG_CODE[(b / 10) % 10]; disbuff[6] = DIG_CODE[(b / 100) % 10]; disbuff[7] = DIG_CODE[(b / 1000) % 10]; DigDisplay(); switch(scanKey() ) { // 如果按下了模式切换键 case 1: uMode = 1; TR1 = 1; EA = 1; break; // 如果按下了'+'键 case 2: switch(iSW ) { case 0: mid = a; if( mid + 100 <= 3000 ) mid += 100; a = mid; break; case 1: mid = b; if( mid + 100 <= 3000 ) mid += 100; b = mid; break; default: break; } break; // 如果按下了'-'键 case 3: switch(iSW ) { case 0: mid = a; if( mid - 100 > 0 ) mid -= 100; a = mid; break; case 1: mid = b; if( mid - 100 > 0 ) mid -= 100; b = mid; default: break; } break; // 如果按下了换位键 case 4: iSW++; if(iSW>= 2 ) iSW = 0; break; default: break; } if (a>=b) { a = a_o; b + b_o; } } else { TH0 = 0; // 计数清0,等待测距计数 TL0 = 0; // 我们假定工作模式=1代表超声波测距 while( !RX &&scanKey() != 1 ); // 如果有echo信号或者有SET按键 TR0 = 1; if( !RX &&keyEx ) // 如果是有按键而没有echo,则返回参数设置 { // 如果有SET按键 uMode = 0; TR0 = 0; TR1 = 0; EA = 0; continue; } // 如果有echo信号,则一直等待echo信号结束 while(RX ); // echo信号结束,停止计数 TR0 = 0; time = TH0 * 256 + TL0; S= (long)(time*0.17); disbuff[3]=DIG_CODE[S%10000/1000]; disbuff[2]=DIG_CODE[S%1000/100]; disbuff[1]=DIG_CODE[S%100/10]; disbuff[0]=DIG_CODE[S%10/1]; disbuff[4] = 0; disbuff[5] = 0; disbuff[6] = 0; disbuff[7] = 0; DigDisplay(); if(S>=a) { if(S>=b) { Direction=1; Speed = 1; } else { Direction=1; Speed = 20; } } else { Direction=1; Speed = 100; } Motor(); // 此次测距结束,可以启动下一次了 srFlag = 1; } } } /********************************************************************* * 函 数 名:Delay * 函数功能:延时 *********************************************************************/ void Delay(unsigned int t) { unsignedint k; while(t--) { for(k=0; k<20; k++) { } } } |
/********************************************************************* * 实 验 名:超声波测距控制步进电机实验 *********************************************************************/ #include "reg52.h" #include <intrins.h> sbit RX=P2^1; sbit TX=P2^0; //t,e定义超声波管教 unsignedint time=0; unsignedint timer=0; unsigned long S=0; bit flag =0; //测量标志 bit srFlag = 1; unsignedint a=100; unsignedint b=600; unsignedinta_o=100; unsignedintb_o=600; unsignedint mid; unsigned char iSW = 0; unsigned char uMode = 1; #define GPIO_DIG P0 sbit LSA=P2^2; sbit LSB=P2^3; sbit LSC=P2^4; unsigned char code DIG_CODE[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; unsigned char disbuff[8] ={0,0,0,0,0,0,0,0}; //电机IO #define GPIO_MOTOR P1 sbit F1 = P1^0; sbit F2 = P1^1; sbit F3 = P1^2; sbit F4 = P1^3; //按键IO sbit K1=P3^1; sbit K2=P3^0; sbit K3=P3^2; sbit K4=P3^3; unsigned char keyEx = 0; unsigned char code FFW[8]={0xf1,0xf3,0xf2,0xf6,0xf4,0xfc,0xf8,0xf9}; //反转顺序 unsigned char code FFZ[8]={0xf9,0xf8,0xfc,0xf4,0xf6,0xf2,0xf3,0xf1}; //正转顺序 unsigned char Direction,Speed; void Delay(unsigned int t); void Motor(); voidDigDisplay(); void Delay1ms() //?? 0us { unsigned char a,b,c; for(c=2;c>0;c--) for(b=38;b>0;b--) for(a=13;a>0;a--); } voidDigDisplay() { unsigned char i; unsignedint j; for(i=0;i<8;i++) { switch(i) //位选,选择点亮的数码管, { case(0): LSA=0;LSB=0;LSC=0; break;//显示第0位 case(1): LSA=1;LSB=0;LSC=0; break;//显示第1位 case(2): LSA=0;LSB=1;LSC=0; break;//显示第2位 case(3): LSA=1;LSB=1;LSC=0; break;//显示第3位 case(4): LSA=0;LSB=0;LSC=1; break;//显示第4位 case(5): LSA=1;LSB=0;LSC=1; break;//显示第5位 case(6): LSA=0;LSB=1;LSC=1; break;//显示第6位 case(7): LSA=1;LSB=1;LSC=1; break;//显示第7位 //势能端 } GPIO_DIG=disbuff[i];//发送段码 j=10; //扫描间隔时间设定 while(j--); //延时 GPIO_DIG=0x00;//消隐 } } unsigned char scanKey(void) { // 如果此前没有按键 if(keyEx == 0 ) { if( K1 == 0 ) { keyEx = 1; // 有键按下 return 1; // 键值1表示阈值ab切换 } if( K2 == 0 ) { keyEx = 1; // 有键按下 return 2; // 键值2表示'+' } if( K3 == 0 ) { keyEx = 1; // 有键按下 return 3; // 键值3表示'-' } if( K4 == 0 ) { keyEx = 1; // 有键按下 return 4; // 键值4表示数位切换 } return 0; } else { if( K1 == 1 && K2 == 1 && K3 == 1 && K4 == 1 ) { keyEx = 0; // 等待没有按键后,按键保护值清0 } } return 0; } /********************************************************************* * 函 数 名:Motor * 函数功能:电机旋转函数 *********************************************************************/ void Motor() { unsigned char i; for(i=0;i<8;i++) { if(Direction==1) GPIO_MOTOR = FFW[i]&0x1f; //??? if(Direction==2) GPIO_MOTOR = FFZ[i]&0x1f; Delay(Speed); //???? } } void zd3() interrupt 3 //T1中断用来扫描数码管和计800MS启动模块 { TH1=0xf8; TL1=0x30; DigDisplay(); timer++; if(srFlag||timer>=100) //200ms 中断一次 { srFlag = 0; timer=0; TX=1; //至高点平 //800MS 启动一次模块 _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); //20us高电平 TX=0; } } /********************************************************************* * 函 数 名:main * 函数功能:主函数 *********************************************************************/ void main(void) { unsigned char i; Speed=15; TMOD=0x11; //设T0为方式1,GATE=1; TH0=0; TL0=0; //清0 TH1=0xf8; //2MS定时 TL1=0x30; ET0=1; //允许T0中断 ET1=1; //允许T1中断 TR1 = 0; EA = 0; while(scanKey() == 0 ) { disbuff[0] = DIG_CODE[4]; disbuff[1] = DIG_CODE[5]; disbuff[2] = DIG_CODE[0]; disbuff[3] = DIG_CODE[1]; disbuff[4] = DIG_CODE[0]; disbuff[5] = DIG_CODE[3]; disbuff[6] = DIG_CODE[1]; disbuff[7] = DIG_CODE[1]; DigDisplay(); } for(i=0;i<100;i++) { Delay1ms(); } if(uMode == 1 ) { TR1 = 1; EA = 1; } while(1) { if(uMode == 0 ) { disbuff[0] = DIG_CODE[a% 10]; disbuff[1] = DIG_CODE[(a / 10) % 10]; disbuff[2] = DIG_CODE[(a / 100) % 10]; disbuff[3] = DIG_CODE[(a / 1000) % 10]; disbuff[4] = DIG_CODE[b% 10]; disbuff[5] = DIG_CODE[(b / 10) % 10]; disbuff[6] = DIG_CODE[(b / 100) % 10]; disbuff[7] = DIG_CODE[(b / 1000) % 10]; DigDisplay(); switch(scanKey() ) { // 如果按下了模式切换键 case 1: uMode = 1; TR1 = 1; EA = 1; break; // 如果按下了'+'键 case 2: switch(iSW ) { case 0: mid = a; if( mid + 100 <= 3000 ) mid += 100; a = mid; break; case 1: mid = b; if( mid + 100 <= 3000 ) mid += 100; b = mid; break; default: break; } break; // 如果按下了'-'键 case 3: switch(iSW ) { case 0: mid = a; if( mid - 100 > 0 ) mid -= 100; a = mid; break; case 1: mid = b; if( mid - 100 > 0 ) mid -= 100; b = mid; default: break; } break; // 如果按下了换位键 case 4: iSW++; if(iSW>= 2 ) iSW = 0; break; default: break; } if (a>=b) { a = a_o; b + b_o; } } else { TH0 = 0; // 计数清0,等待测距计数 TL0 = 0; // 我们假定工作模式=1代表超声波测距 while( !RX &&scanKey() != 1 ); // 如果有echo信号或者有SET按键 TR0 = 1; if( !RX &&keyEx ) // 如果是有按键而没有echo,则返回参数设置 { // 如果有SET按键 uMode = 0; TR0 = 0; TR1 = 0; EA = 0; continue; } // 如果有echo信号,则一直等待echo信号结束 while(RX ); // echo信号结束,停止计数 TR0 = 0; time = TH0 * 256 + TL0; S= (long)(time*0.17); disbuff[3]=DIG_CODE[S%10000/1000]; disbuff[2]=DIG_CODE[S%1000/100]; disbuff[1]=DIG_CODE[S%100/10]; disbuff[0]=DIG_CODE[S%10/1]; disbuff[4] = 0; disbuff[5] = 0; disbuff[6] = 0; disbuff[7] = 0; DigDisplay(); if(S>=a) { if(S>=b) { Direction=1; Speed = 1; } else { Direction=1; Speed = 20; } } else { Direction=1; Speed = 100; } Motor(); // 此次测距结束,可以启动下一次了 srFlag = 1; } } } /********************************************************************* * 函 数 名:Delay * 函数功能:延时 *********************************************************************/ void Delay(unsigned int t) { unsignedint k; while(t--) { for(k=0; k<20; k++) { } } } |
函数不对啊 |
是软件问题,建议使用实物制作比较好。加上延时程序看看嫩嗯不能减小 |
减少每个数码管之间的延时 |
检查下显示时间,位选和段选 |
和时间有关,太快了,肉眼是看不到的 |
直接用一个8位数码管不好吗,这样一位一位来而且又是乱排看得尴尬病都犯了 |
消影做完之后,可以先尝试一下调一下延时函数的时间。 |
可能是管子的消隐没做好或者软件显示问题?我三年前好像也出过这个问题,记不太清了。。。 |
我看你显示代码里面没有消影,看看是不是这个原因 |
学会画出流程图并走通流程图。 |
附上C语言程序,大神帮我看看哪里出错了: #include <reg51.h> #include <intrins.h> #define uchar unsigned char #define uint unsigned int sbit dula=P3^1; sbit wela=P3^2; uint bb=0; sbit led1=P3^3; uint x=0,t0=0; uchar num,temp,ch=1; uchar shi=17,fen=13,miao=25,shi1,shi2,fen1,fen2,miao1,miao2; uint nian=2019,yue=7,ri=9,nian1,nian2,yue1,yue2,ri1,ri2,year=00,month=00,day=00,year1,year2,month1,month2,day1,day2; uchar code table[]={ 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71, 0x76,0x79,0x38,0x3f,0}; void delay(uint z) { uint t1,y; for(t1=z;t1>0;t1--) for(y=110;y>0;y--); } void display(uchar shi1,uchar shi2,uchar fen1,uchar fen2,uchar miao1,uchar miao2) { wela=1; P2=0xfe; wela=0; dula=1; P2=table[shi1]; delay(5); dula=0; wela=1; P2=0xfd; wela=0; dula=1; P2=table[shi2]; delay(5); dula=0; wela=1; P2=0xfb; wela=0; dula=1; P2=table[fen1]; delay(5); dula=0; wela=1; P2=0xf7; wela=0; dula=1; P2=table[fen2]; delay(5); dula=0; wela=1; P2=0xef; wela=0; dula=1; P2=table[miao1]; delay(5); dula=0; wela=1; P2=0xdf; wela=0; dula=1; P2=table[miao2]; delay(5); dula=0; } void init() { TMOD=0x11; TH0=(65536-50000)/256; //定时器初始化 TL0=(65536-50000)%256; TH1=(65536-50000)/256; TL1=(65536-50000)%256; EA=1; ET0=1; ET1=1; TR1=1; } uchar keyscan() { P3=0xfe;//检测第一行 temp=P3; temp=temp&0xf0; while(temp!=0xf0) { delay(5); temp=P3; temp=temp&0xf0; while(temp!=0xf0) { switch(temp) { case 0xe0:num=1; break; case 0xd0:num=2; break; case 0xb0:num=3; break; case 0x70:num=4; break; } while(temp!=0xf0) { temp=P3; temp=temp&0xf0; } } } return shi,fen; } void jisuan() { if(num==1) { ch++; if(ch==4) ch=1; num=0; } if(num==2) { if(ch==1) shi++; if(ch==2) nian++; if(ch==3) year++; num=0; } if(num==3) { if(ch==1) fen++; if(ch==2) yue++; if(ch==3) month++; num=0; } if(num==4) { if(ch==1) miao++; if(ch==2) ri++; if(ch==3) day++; num=0; } } void shijian() { shi1=shi/10; shi2=shi%10; fen1=fen/10; fen2=fen%10; miao1=miao/10; miao2=miao%10; if(fen==0&miao==0)/* 当时间为整时时灯灭,否则灯亮 */ { led1=0; }else{ led1=1; } if(shi==24) { shi=0; ri++; } if(fen==60) { fen=0; shi++; } if(miao==60) { miao=0; fen++; } } void riqi() { nian1=nian/10; nian2=nian%10; yue1=yue/10; yue2=yue%10; ri1=ri/10; ri2=ri%10; if(yue==12) { nian++; yue=1; } switch(yue)//判断月份大小 { case 1:case 3:case 5:case 7:case 8:case 10:case 12: if(ri==32) { ri=1; yue++; } break; case 4:case 6:case 9:case 11: if(ri==31) { ri=1; yue++; } break; case 2: //判断闰年 if((nian%4==0&nian%100!=0)||nian%400==0) { yue++; ri=1; } else if(nian%400!=0&ri==29) { yue++; ri=1; } break; } } void naozhong() //闹钟 { year1=year/10; year2=year%10; month1=month/10; month2=month%10; day1=day/10; day2=day%10; if(year==24) { year=0; } if(month==60) { month=0; year++; } if(day==60) { day=0; month++; } } void main() //shi代表当前时间 year代表闹钟时间 { init(); P1=0x00; //P1四个灯 初始化为灭 while(1) { jisuan(); keyscan(); shijian(); riqi(); naozhong(); if(shi==year&fen==month&miao==day) TR0=1; if(ch==1) display(shi1, shi2, fen1, fen2, miao1, miao2); if(ch==2) display(nian1,nian2,yue1,yue2,ri1,ri2); if(ch==3) display(year1,year2,month1,month2,day1,day2); } } void time1() interrupt 3 { TH1=(65536-50000)/256; TL1=(65536-50000)%256; x++; if(x==20) { x=0; miao++; if(miao==60) { miao=0; fen++; if(fen==60) { fen=0; shi++; if(shi==24) { shi=0; } } } } } void timer0() interrupt 1 //定时器0中断 { TH0=(65536-50000)/256; TL0=(65536-50000)%256; t0++; if(t0<1200) { bb++; //增加_b 拖延时间增加闪烁时间 if(bb<15){ P1=0xff; } if(bb>15){ P1=0xf0; if(bb>30){bb=0;} } if(t0==1200) { TR0=0; //60秒后关闭定时器0,关闭灯 P1=0x00; } } } |