首页 新闻 会员 周边 捐助

利用51单片机 做一个 表决器

0
悬赏园豆:10 [待解决问题]
/**********************************************************************************
程序功能:表决器,模拟三位评委的表决,并做出判断,将结果显示于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键不起作用,是为啥呢?

恳请大家花几分钟给看看。。不胜感激了。。。

天若海愚的主页 天若海愚 | 初学一级 | 园豆:192
提问于:2013-09-09 08:41
< >
分享
所有回答(1)
0

有几点疑问:

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键看起来不起作用的原因。程序会一直清屏。

 

建议:为什么不使用外部中断触发呢?

薛遗山 | 园豆:106 (初学一级) | 2013-09-09 21:19

首先非常感谢你。

第一个疑问:dula,wela是涉及到数码管的,将其置1是为了关闭数码管;

2、P3=0xxx;
        temp=P3;
        temp=temp&0xf0;

是一个按键,来控制数码管的。

我做出来了,应该在主程序中if()最后将ok与ng置0,另外下面clear也需要清0

支持(0) 反对(0) 天若海愚 | 园豆:192 (初学一级) | 2013-09-11 19:45
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册