1602显示器成本低廉使用简单,是单片机理想的显示设备。但是,1602显示器同时只能显示32个字符的内容,显示信息明显偏少,而且自然显示的话显示内容很快就会超出显示范围而看不见。直到第一行显示满64个字符后才回到第二行开头显示重现显示内容。为了避免出现显示内容超出显示范围而不可见,程序要适时换行,但在程序中使用显示器的地方有很多个模块,其中有些还是中断模块,各模块实际往显示器送了多少个字符很难判断,很难适时换行导致显示内容进入不可见显示区而影响显示效果,特别是有些时候要输入数字,还会用到退格键删除内容,这更增加了显示控制的难度。有的程序员为了避免出现这种情况就采用固定地点显示方法,就只在显示器几个固定地方显示内容,这样虽然不会出现显示内容不可见的情况,但往往只能安排少数几个显示地点,会出现很多显示单元没利用,使本来不多的显示资源便显紧张,影响程序运行效果,特别是一些显示数据刷新率高的场合,往往前一个数据还没看清,下一下数据已将其履盖。所以固定地点显示的方法也不是最优。根据本人的体会,要充分利用1602显示器的显示资源,要固定地点显示与自然显示方法相结合,在显示器中的一些特定区域设为固定显示点,如将显示器的每行两端两到四个显示单元作为固定显示点,用于较固定的显示需求,其余地方作为自然显示区,编写一个专门显示模块,统一管理显示资源,正确设置显示光标,使显示内容能在自然显示区内合理显示,而又不会影响其他区域的显示。这样就能最大限度发挥显示器的作用。
为了说明本方法对显示器的使用,本人设计了一个简单的例子。在本例中,有一个简单的算术测试程序,在100个时间单位内,单片机不断出一些简单的算术题,由用户答题,正确则正确答题数加分,错误则错题数加分,在显示器的左上角实时显示答对题数字,左下角实时显示答错题数字,右上角则实时显示所剩的时间数字,右下角则用于输入数字显示用,支持退格删除字符。
下面是程序运行时的截图:
单片机源程序如下:
- #include<reg51.h>
- sbit kx0=P2^0;
- sbit kx1=P2^1;
- sbit kx2=P2^2;
- sbit kx3=P2^3;
- sbit ky0=P2^4;
- sbit ky1=P2^5;
- sbit ky2=P2^6;
- sbit ky3=P2^7;
- sbit rs=P3^5;
- sbit rw=P3^6;
- sbit E=P3^7;
- #define StartA 3
- #define StartB 3
- #define EndA 13
- #define EndB 13
- char shifkey,ok,error,xl,yl;
- int Timenum,temp;
- //===========================================================
- void delay(int ii){int i;for(i=0;i<ii;i++);}
- //===========================================================
- void writeCmd(unsigned char c){E=0;rw=0;rs=0;delay(50);delay(50);P1=c;delay(50);E=1;delay(50);E=0; }
- void writeDat(unsigned char c){E=0;rw=0;rs=1;delay(50);delay(50);P1=c;delay(50);E=1;delay(50);E=0;}
- void Putxychar(char x,char y,char c){if(y>0)writeCmd(0x80+0x40+x);else writeCmd(0x80+x);writeDat(c);}
- void Prtstr(char *cp){char i=0;while(cp[i]!=0){writeDat(cp[i]);i++;}}
- void Mplaychar(char c)
- {int i;Putxychar(xl,yl,c);
- xl++;
- if((xl>=EndA)&&(yl==0)){xl=StartB;yl=1;for(i=StartA;i<EndA;i++)Putxychar(i,1,' ');}
- else if(xl>=EndB){xl=StartA;yl=0;for(i=StartB;i<EndB;i++)Putxychar(i,0,' ');}
- }
- void Mplaystr(char *cp){char i=0;while(cp[i]!=0){Mplaychar(cp[i]);i++;}}
- //-----------------------------------------------------------
- void dispnum(int x,int y,int num)
- {if(y>0)writeCmd(0x80+0x40+x);else writeCmd(0x80+x);
- writeDat((num%100)/10+0x30);writeDat((num%100)%10+0x30);
- }
- //===========================================================
- void Timeinit()
- {EA=1;ET1=1;TMOD|=0x20;
- TH1=0;TL1=0;TR1=1;
- }
- //=========================================================
- void Time1Pro()interrupt 3
- {temp++;
- if(temp==3000){temp=0;if(Timenum>0)Timenum--;dispnum(14,0,Timenum);}
- }
- //==========================================================
- int KeyDown()
- {char v,x,y;
- x=4;y=4;
- P2=0x0f;v=P2;
- if(v!=0x0f){if(kx0==0)x=0;if(kx1==0)x=1;if(kx2==0)x=2;if(kx3==0)x=3;
- P2=0xf0;if(ky0==0)y=0;if(ky1==0)y=1;if(ky2==0)y=2;if(ky3==0)y=3;
- }
- return x*4+y;
- }
- //==========================================================
- unsigned int GetNum()
- {char w,pos=0,key;
- unsigned int num;
- w=0;
- writeCmd(0x80+0x40+EndB+1);
- Prtstr(" ");
- writeCmd(0x80+0x40+EndB+1);
- while(1)
- {key=KeyDown();
- if(key<12)
- {key=KeyDown();while(key==KeyDown());
- if(key<10){Putxychar(EndB+pos+1,1,key+0x30);pos++;if(w==0)num=key;else num=num*10+key;w++;}
- else if(key==10){num=num/10;if(pos>0)pos--;Putxychar(EndB+pos+1,1,' ');writeCmd(0x80+0x40+EndB+pos+1);}
- else if(key==11)return num%100;
- }
- }
- }
- //=========================================================
- void Game()
- {int a,b,c;
- while(Timenum)
- {a=rand()%10;
- b=rand()%10;
- Mplaychar(a+0x30);
- Mplaychar('+');
- Mplaychar(b+0x30);
- Mplaychar('=');
- c=GetNum();
- if((c%100)/10)Mplaychar((c%100)/10+0x30);
- Mplaychar((c%100)%10+0x30);
- Mplaychar(';');
- if(c==(a+b)){dispnum(0,0,++ok);}
- else{{dispnum(0,1,++error);}}
- }
- }
- //##########################################################
- void main()
- {int i;
- Timeinit();
- Timenum=100;
- Putxychar(2,0,'[');
- Putxychar(2,1,'[');
- Putxychar(13,0,']');
- Putxychar(13,1,']');
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
附件有完整程序及proteus设计:
P7.zip
(109.73 KB, 下载次数: 7)
|