本帖最后由 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();
}
} |