打印
[51单片机]

表决器、1602显示

[复制链接]
1568|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yqh2013|  楼主 | 2013-9-9 10:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
CD, LCD, TE, COM, BLE

/**********************************************************************************
程序功能:表决器,模拟三位评委的表决,并做出判断,将结果显示于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 pass,nopass;
bit flag,ok1,ok2,ok3;   //flag是显示agree或者disagree的标志位,flag1,flag2,flag3是该按键释放被激活的标志位,因为每一次同一个人的按键只能被按一次
bit clear;
/*延时函数*/
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(100);
write_com(0x0c);
delay(100);
write_com(0x06);
delay(100);
write_com(0x01);
delay(100);
}
void yes()
{
uchar a;
write_com(0x80+0x40+6);
delay(20);
for(a=0;a<4;a++)
{
  write_date(table5[a]);
  delay(20);
}
}
void no()
{
uchar a;
write_com(0x80+0x40+6);
delay(20);
for(a=0;a<3;a++)
{
  write_date(table6[a]);
  delay(20);
}
}
/*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(20);
  }
}
else
{
  for(i=0;i<8;i++)
  {
   write_date(table3[i]);
   delay(20);
  }
}
}
/*键盘扫描程序*/
void keyscan()
{
uchar temp;
if(!ok1)
{
  P3=0xfe;
  temp=P3;
  temp=temp&0xf0;
  if(temp!=0xf0)  
  {
   delay(10);
   if(temp!=0xf0)
   {
    temp=P3;
    switch(temp)
    {
     case 0xee:   //S6被按下
      flag=1;
      pass++;
      ok1=1;
      //agree();  //调用该函数存在错误,最好是在等待按键之后再调用显示函数,所以解决方法是设置标志位,在后面调用display()函数
      break;
     case 0xde:   //S7被按下
      flag=0;
      nopass++;
      ok1=1;
      //disagree();
      break;
    }
    while(temp!=0xf0)   //等待按键被释放
    {
     temp=P3;
     temp=temp&0xf0;
     beep=0;
    }
    beep=1;
    display(flag);
   }
  }
}
if(!ok2)
{
  P3=0xfd;
  temp=P3;
  temp=temp&0xf0;
  if(temp!=0xf0)
  {
   delay(10);
   if(temp!=0xf0)
   {
    temp=P3;
    switch(temp)
    {
     case 0xed:   //S10被按下
      flag=1;
      pass++;
      ok2=1;
      break;
     case 0xdd:   //S11被按下
      flag=0;
      nopass++;
      ok2=1;
      break;
    }
    while(temp!=0xf0)   //等待按键被释放
    {
     temp=P3;
     temp=temp&0xf0;
     beep=0;
    }
    beep=1;
    display(flag);
   }
  }
}
if(!ok3)
{
  P3=0xfb;
  temp=P3;
  temp=temp&0xf0;
  if(temp!=0xf0)
  {
   delay(10);
   if(temp!=0xf0)
   {
    temp=P3;
    switch(temp)
    {
     case 0xeb:   //S14被按下
      flag=1;
      pass++;
      ok3=1;
      break;
     case 0xdb:   //S15被按下
      flag=0;
      nopass++;
      ok3=1;
      break;
    }
    while(temp!=0xf0)   //等待按键被释放
    {
     temp=P3;
     temp=temp&0xf0;
     beep=0;
    }
    beep=1;
    display(flag);
   }
  }
}
P3=0xf7;
temp=P3;   //S18,清零
temp=temp&0xf0;
if(temp!=0xf0)
{
  delay(10);
  if(temp!=0xf0)
  {
   temp=P3;
   switch(temp)
   {
    case 0xe7:
     clear=1;
     break;
   }
   while(temp!=0xf0)
   {
    temp=P3;
    temp=temp&0xf0;
    beep=0;
   }
   beep=1;
  }
}
}
/*主函数*/
void main()
{
uchar count;
init();
while(1)
{
  keyscan();
  count=pass+nopass;
  if(count==3)
  {
   delay(2000);
   write_com(0x01);
   delay(2000);
   if(pass > nopass)
   {
    yes();
   }
      if(nopass > pass)
   {
    no();
   }
  }
  if(clear)
  {
   ok1=0;
   ok2=0;
   ok3=0;
   count=0;
   pass=0;
   nopass=0;
   clear=0;
   write_com(0x01);
  }
}
}
个位前辈,刚入行不久,为什么以上的程序出现了问题,我一直没有弄出来,现象就是:agree和disagree正常显示,但是最后显示结果“yes”或“no”的时候,1602就显示1秒,然后就出现乱码了。这是什么原因呢?如果不要keyscan()函数,直接给pass和nopass赋值的话,那么结果“yes”或“no”就正常显示。。

相关帖子

沙发
NE5532| | 2013-9-9 16:06 | 只看该作者
1.你好像没有用中断,程序应该是比较好调的。
2.是放开按钮显示的乱码还是按着按钮就显示乱码了?
3.是不是应该考虑给出结果以后就不再扫描键盘了,同理,是不是应该有一个“开始键”来命令表决开始??

调这种程序,可以在显示pass或者not pass之后用while(1);打断点来看程序是否正常,如果正常,就是其后的操作出了问题。

使用特权

评论回复
板凳
NE5532| | 2013-9-9 16:07 | 只看该作者
1.你好像没有用中断,程序应该是比较好调的。
2.是放开按钮显示的乱码还是按着按钮就显示乱码了?
3.是不是应该考虑给出结果以后就不再扫描键盘了,同理,是不是应该有一个“开始键”来命令表决开始??

调这种程序,可以在显示pass或者not pass之后用while(1);打断点来看程序是否正常,如果正常,就是其后的操作出了问题。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

2

帖子

1

粉丝