/********************************************************************************** 程序功能:表决器,模拟三位评委的表决,并做出判断,将结果显示于1602上。 共用到TX-1C学习板上左二列的S6,S7,S10,S11,S14,S15,S18七个按键。 其中S18为清零键,对1602进行清屏和对相关变量清零。 每位评委操控两个按键,分别代表“通过”和“不通过”。 第一位评委控制S6(通过)与S7(不通过); 第二位评委控制S10(通过)与S11(不通过); 第三位评委控制S14(通过)与S15(不通过); 当按“通过”次数多于“不通过”时,1602将显示“yes”,否则显示“no”。 在一个回合中,每位评委只有一次按键的权利,一旦按下,其操控的两个 按键均将被封锁,再按也不会有任何作用。除非按下清零键S18清零后开始下一回合。 ************************************************************************************/ #include<reg52.h> #define uchar unsigned char #define uint unsigned int sbit dula=P2^6; sbit wela=P2^7; sbit lcdrs=P3^5; sbit lcden=P3^4; sbit beep=P2^3; uchar table[]="yes"; uchar table1[]="no"; uchar table2[]="agree"; uchar table3[]="disagree"; uchar table4[]=" "; uchar table5[]="YES!"; uchar table6[]="NO!"; uchar count,pass,nopass; bit flag,flag1,flag2,flag3; //flag是显示agree或者disagree的标志位,flag1,flag2,flag3是该按键释放被激活的标志位,因为每一次同一个人的按键只能被按一次 bit clear; char ok,ng; /*延时函数*/ void delay(uint z) { uint x,y; for(x=z;x>0;x--) //即延时约z毫秒 for(y=110;y>0;y--); } /*1602液晶显示*/ /*写命令*/ void write_com(uchar com) { lcdrs=0; lcden=0; P0=com; delay(5); lcden=1; delay(5); lcden=0; } /*写数据*/ void write_date(uchar date) { lcdrs=1; lcden=0; P0=date; delay(5); lcden=1; delay(5); lcden=0; } /*初始化*/ void init() { dula=0; wela=0; lcden=0; write_com(0x38); delay(20); write_com(0x0c); delay(20); write_com(0x06); delay(20); write_com(0x01); delay(20); } void yes() { uchar a; write_com(0x80+0x40+6); delay(20); for(a=0;a<4;a++) { write_date(table5[a]); delay(20); } //while(1); } void no() { uchar a; write_com(0x80+0x40+6); delay(20); for(a=0;a<3;a++) { write_date(table6[a]); delay(20); } //while(1); } /*agree/disagree显示*/ void display(bit flag) { uchar i; write_com(0x01); //显示之前需要将之前显示的清零 write_com(0x80); if(flag) { for(i=0;i<5;i++) { write_date(table2[i]); delay(5); } } else { for(i=0;i<8;i++) { write_date(table3[i]); delay(5); } } } /*键盘扫描程序*/ void keyscan() { uchar temp; if(!flag1) { P3=0xfe; temp=P3; temp=temp&0xf0; if(temp!=0xf0) { delay(5); if(temp!=0xf0) { temp=P3; switch(temp) { case 0xee: //S6被按下 flag=1; ok++; //agree(); //调用该函数存在错误,最好是在等待按键之后再调用显示函数,所以解决方法是设置标志位,在后面调用display()函数 break; case 0xde: //S7被按下 flag=0; ng++; //disagree(); break; } while(temp!=0xf0) //等待按键被释放 { temp=P3; temp=temp&0xf0; } flag1=1; count++; display(flag); } } } if(!flag2) { P3=0xfd; temp=P3; temp=temp&0xf0; if(temp!=0xf0) { delay(5); if(temp!=0xf0) { temp=P3; switch(temp) { case 0xed: //S10被按下 flag=1; ok++; //flag2=1; break; case 0xdd: //S11被按下 flag=0; ng++; //flag2=1; break; } while(temp!=0xf0) //等待按键被释放 { temp=P3; temp=temp&0xf0; } flag2=1; count++; display(flag); } } } if(!flag3) { P3=0xfb; temp=P3; temp=temp&0xf0; if(temp!=0xf0) { delay(5); if(temp!=0xf0) { temp=P3; switch(temp) { case 0xeb: //S14被按下 flag=1; ok++; break; case 0xdb: //S15被按下 flag=0; ng++; break; } while(temp!=0xf0) //等待按键被释放 { temp=P3; temp=temp&0xf0; } flag3=1; count++; display(flag); } } } P3=0xf7; temp=P3; //S18,清零 temp=temp&0xf0; if(temp!=0xf0) { delay(5); if(temp!=0xf0) { temp=P3; switch(temp) { case 0xe7: clear=1; break; } while(temp!=0xf0) { temp=P3; temp=temp&0xf0; } beep=0; delay(500); beep=1; } } } /*主函数*/ void main() { init(); while(1) { keyscan(); if(count==3) { delay(2000); write_com(0x01); if(ok > ng) { yes(); } if(ng > ok) { no(); } } if(clear) { flag1=0; flag2=0; flag3=0; count=0; write_com(0x01); } } }
各位前辈好,我刚接触单片机不久,但是这个程序也困扰我一个多星期了,出现的问题是:比如说,第一个人agree,第二个人disagree,第三个人agree,那么1602上显示的是yes,但是问题 是yes只显示了2秒左右,就显示乱码了。。还有我按下的S18键不起作用,是为啥呢?
恳请大家花几分钟给看看。。不胜感激了。。。
有几点疑问:
1、sbit dula=P2^6; 这两个引脚是干啥用的。貌似只初始化用到了
sbit wela=P2^7;
2、 P3=0xxx;
temp=P3;
temp=temp&0xf0;
好像这三条语句执行完后,不论P3赋值多少,temp都为0xf0。
对于你的两个问题,yes只显示2s是因为循环里面有个2s的延时。应该是当显示完yes后,再次调用keyscan();后clear就为真了。还有clear没有清0。这也是为什么S18键看起来不起作用的原因。程序会一直清屏。
建议:为什么不使用外部中断触发呢?
首先非常感谢你。
第一个疑问:dula,wela是涉及到数码管的,将其置1是为了关闭数码管;
2、P3=0xxx;
temp=P3;
temp=temp&0xf0;
是一个按键,来控制数码管的。
我做出来了,应该在主程序中if()最后将ok与ng置0,另外下面clear也需要清0