打印

单片机做的数码管菜单显示,看下哪里需要改进?

[复制链接]
5875|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
8421bcd|  楼主 | 2009-12-7 01:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 8421bcd 于 2009-12-7 14:37 编辑

#include < reg51.h >
#include <intrins.h>
#define uchar unsigned char
#define uint  unsigned int
uchar layer = 0;            //用于表示显示的哪一级菜单
uchar sign = 0;     //要显示的菜单号,一共个菜单
uchar enable = 4;     //闪灯位,为0时不闪
uchar enabledata;        //操作数用于闪灯   
struct jigou{     
    uchar a;        
    uchar b;
    uchar c;
    uchar d;
    }parameter[] = {{0,0,0,0},{1,1,1,1},{2,2,2,2},{3,3,3,3},{4,4,4,4},{5,5,5,5},{6,6,6,6}};  //各菜单下的显示参数,实际中读24C02
uchar LEDData[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x98,0xff};   //数码管显示的值0-9,最后0xff是关显示            
uchar data1[4] = {0,1,2,3};
uchar dispdata[4] = {0,1,2,3}; //显示的菜单数据
void delay(uint ms)   // 延时子程序  
{
uchar k;
while(ms--)
{
  for( k = 0; k < 120; k++ );
}
}
void addparameter( uchar a )   //当layer=2时,被UPKEY键掉用,实现操作数的加
{
switch(a)
{
  case 0:
  enabledata =++ parameter[sign].a;
  break;
  case 1:
  enabledata =++ parameter[sign].b;
  break;
  case 2:
  enabledata =++ parameter[sign].c;
  break;
  case 3:
  enabledata =++ parameter[sign].d;
  break;
  default:
  break;
}
}
void subparameter( uchar a )   //当layer=2时,被DOWNKEY键调用,实现操作数的减
{
switch(a)
{
  case 0:
  enabledata =-- parameter[sign].a;
  break;
  case 1:
  enabledata =-- parameter[sign].b;
  break;
  case 2:
  enabledata =-- parameter[sign].c;
  break;
  case 3:
  enabledata =-- parameter[sign].d;
  break;
  default:
  break;  
}
}
void copymenu()        //用五拷贝参数 ,用于esckey键
{
dispdata[0] = sign;
dispdata[1] = 10;
dispdata[2] = 10;
dispdata[3] = 10;
enabledata = sign;      //用于功功能操作灯闪烁
}
void copy(void)       //拷贝操作项的参数
{
dispdata[0] = parameter[sign].a;
dispdata[1] = parameter[sign].b;
dispdata[2] = parameter[sign].c;
dispdata[3] = parameter[sign].d;
enabledata = dispdata[enable];  //用于功能操作灯闪烁
}
void copyfre(void)       //恢复最初的显示,假设是当前的运行速度
{
dispdata[0] = data1[0];
dispdata[1] = data1[1];
dispdata[2] = data1[2];
dispdata[3] = data1[3];
}
void esckey()     //返回键处理程序   
{
if( layer == 0||layer == 2 ) //当操作层在0或2时,反回到1layer
{
     enable = 0;
  layer = 1;  
  copymenu();
  return;
}
if( layer == 1 )  //当layer在1层时,返回到开机显示的参数
{
  layer=0;
  enable=4;
  copyfre();
}  
if( layer > 1 )    //当操作层在2时,返回第上级显示界面
{
  layer = 1;
  enable = 0;
  copymenu();
}

}         
void upkey()     //upkey处理程序
{
if( layer == 0 )   //在层0时,不执行操作
  return ;    //在层1时,参数项加1
if( layer == 1&&sign < 6 )
{
    ++sign;
    copymenu( );
    return;
  }
  if( layer == 2&&dispdata[enable] <9 ) //如果是在参数操作层,切操作数不大于9,参数相应位加1
  {
   addparameter(enable );
  copy();
  }
}
void downkey()
{
if ( layer == 0 )
  return;
if( layer == 1&&0 < sign )
{
    --sign;
    copymenu();
  }
  if( layer == 2&&0<dispdata[enable]&&dispdata[enable] != 10) //如果是在参数操作层,切操作数不等于0
  {
   subparameter( enable );
  copy();
  }
}
void enterkey()      //dnterkey处理程序
{
if(layer == 0)     
return;       //层0时,返回
if ( layer==1 )     //层1时,显示参数项的参数,并最后一位闪烁
{
    copy();
    enable = 3;      
    layer = 2;
    return;
  }
  if ( layer == 2 )    //闪烁位循环左移
  {
   if(enable == 0)
  {
   enable = 3;
   copy();
   return;
   }
   --enable;
  copy();
  }
}
void  scankey(void)    //键盘扫描程序
{
uint keyvalue = P2&0x0f;
switch(~keyvalue&0x0f)
{
  case 1:    //返回键按下
  esckey();
  break;
  case 2:
  upkey();
  break;
  case 4:
  downkey();
  break;
  case 8:
  enterkey();
  break;
}
}
void keydown(void)     //决断有无按键按下
{

P2 = 0xff;
if( P2 != 0xff )
{
  scankey();
  }
while ( P2 != 0xff) ;
}
void disp()                        //显示入口函,当入口不为 0-3数字时,灯不闪烁
{ uchar m,i;
    uint left = 119;                                //转换为二进制为0b00010001,可以用移位指令控制四个数码管显示!
    enabledata = dispdata[enable];
    for( i = 0;1;i = ~i )
    {
  left = 119;  
  if( enable != 4 )
  {
         dispdata[enable] = enabledata;
        if( i )                                 //用于实现选中的操作数闪烁
         dispdata[enable] = 10;
   }
        for( m = 0;m <= 119;m++ )
        {
   left = _crol_(left,1);  //循环右移(每次移动一位)  
            P1 = (left&0x0f);
            P0 = LEDData[dispdata[m%4]];
   keydown();
            delay(3);
            P0 = 0xff;
         }
      }
}
main()
{  
   while(1)
   {   
     disp();
   }
}

menu.rar

56.15 KB

相关帖子

沙发
8421bcd|  楼主 | 2009-12-7 10:20 | 只看该作者
刚下载到单片机里面,运行可以进入按键处理程序,但是按键处理程序好像没有执行,这是怎么会事呀,在PROTEUS下访真没有问题的呀!

使用特权

评论回复
板凳
new1988| | 2009-12-7 11:29 | 只看该作者
你用的是什么型号的单片机啊?
   你的RAM够用吗?51单片机总共才128个字节的RAM,你的全局变量都是用的int型,真的浪费!

使用特权

评论回复
地板
8421bcd|  楼主 | 2009-12-7 14:36 | 只看该作者
测试时用的是51最后可能会用PCI的,谢谢提醒!已经修改过来了。

使用特权

评论回复
5
8421bcd|  楼主 | 2009-12-7 14:41 | 只看该作者
当程序进入层2时,UPKEY和DOWNKEY对参数进行加减运算的时候,有时键盘程序执行了,但是确没有对参数进行加减!怎么会有时响应有时就不响应?

使用特权

评论回复
6
8421bcd|  楼主 | 2009-12-7 15:18 | 只看该作者
if( layer == 2&&0<dispdata[enable]&&dispdata[enable] != 10) //如果是在参数操作层,切操作数不等于0
         {
                 subparameter( enable );
                copy();
         }
用的KEIL3.53,这样写单片机是不是有时响应不过来?

使用特权

评论回复
7
8421bcd|  楼主 | 2009-12-7 15:53 | 只看该作者
原来是程序有问题,已经测试没问题了!下一步```

使用特权

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

本版积分规则

19

主题

123

帖子

0

粉丝