这个是静态的菜单,现在准备做个电子温度闹钟,用动态的。
如果只是控制的法,静态的已经够用了。
程序中存在些不如意的地方,希望和大家一起交流。
#include<at89x52.h>
#include <intrins.h>
# define uchar unsigned char
# define uint unsigned int
unsigned char Func_Index=0; //存放当前的菜单索引
void (*Func_Ptr)(); //定义按键功能指针
////////////////////////////////////////////定义状态
void State0();
void State1();
void State2();
void State3();
void State4();
void State5();
void State6();
void State7();
void State8();
void State9();
void State10();
//定义按键
sbit k1=P2^0;
sbit k2=P2^3;
sbit k3=P2^4;
sbit k4=P2^5;
sbit k5=P2^6;
sbit k6=P2^7;
sbit k7=P1^5;
sbit k8=P1^6;
unsigned char key;
/************定义结构的类型**********/
typedef struct
{
uchar Index; //当前的状态索引号 存储以后用来查询
uchar Gore; //返回待机键状态索引号
uchar Right; //右键状态索引号
uchar Up; //向上键状态索引号
uchar Down; //向下键状态索引号
uchar Enter; //确定键状态索引号
uchar Left; //向左键状态索引号
uchar Goback1; //返回上一级键状态索引号
void (*Operate)(); //当前状态应执行的操作
} StateTab;
/**********结构数组*************/
StateTab code Menu_Tab[11]=
{
{ 0, 0, 0, 1, 2, 3, 0, 0,(*State0)}, // 待机
//
{ 1, 0, 1, 1, 1, 1, 1, 1,(*State1)}, // 查看温度及报警范围设置
//
{ 2, 0, 2, 2, 2, 2, 2, 2,(*State2)}, // 查看闹铃设置
//
{ 3, 0, 3, 6, 4, 7, 3, 3,(*State3)}, // 主菜单 时间
//
{ 4, 0, 4, 3, 5, 8, 4, 4,(*State4)}, // 主菜单 闹铃
//
{ 5, 0, 5, 4, 6, 9, 5, 5,(*State5)}, // 主菜单 温度
//
{ 6, 0, 6, 5, 3,10, 6, 6,(*State6)}, // 主菜单扩展
//
{ 7, 0, 7, 7, 7, 3, 7, 3,(*State7)}, // 时间调整
//
{ 8, 0, 8, 8, 8, 4, 8, 4,(*State8)}, // 闹铃设置
//
{ 9, 0, 9, 9, 9, 5, 9, 5,(*State9)}, // 温度报警设置
//
{10, 0,10,10,10, 5,10, 5,(*State10)}, // 扩展设置
};
////////////////////////////////////////////////////////////////////
# define LCD_DB P0
sbit LCD_RS=P1^0;
sbit LCD_RW=P1^1;
sbit LCD_E=P1^2;
/******定义函数****************/
void MenuOperate(uchar key);
void keyscan();
void LCD_init(void);//初始化函数
void LCD_write_command(uchar command);//写指令函数
void LCD_write_data(uchar dat);//写数据函数
void LCD_disp_char(uchar x,uchar y,uchar dat);//在某个屏幕位置上显示一个字符,X(0-16),y(1-2)
void delay_n40us(uint n);//延时函数
void Printx(uchar x, uchar y,unsigned char *str);
void GotoXY(unsigned char x, unsigned char y);
//*******初始化函数***************
void LCD_init(void)
{
delay_n40us(10000);
LCD_write_command(0x38);//设置8位格式,2行,5x7
LCD_write_command(0x38);//设置8位格式,2行,5x7
LCD_write_command(0x38);//设置8位格式,2行,5x7
LCD_write_command(0x02);//整体显示,关光标,不闪烁
LCD_write_command(0x0C);//清除屏幕显示
LCD_write_command(0x06);//设定输入方式,增量不移位
}
//********************************
//********写指令函数************
void LCD_write_command(uchar dat)
{
LCD_E = 0;
LCD_RS=0;//指令
LCD_RW=0;//写入
LCD_DB=dat;
LCD_E=1;//允许
delay_n40us(10);//实践证明,我的LCD1602上,用for循环1次就能完成普通写指令。
LCD_E = 0;
}
//////////////////////////////////////////
///////////////////写数据函数/////////////////////
void LCD_write_data(uchar dat)
{
LCD_E = 0;
LCD_RS=1;//数据
LCD_RW=0;//写入
LCD_DB=dat;
LCD_E=1;//允许
delay_n40us(10);
LCD_E = 0;
}
///////////////////////////////////
//////////////////显示一个字符函数////////////
void LCD_disp_char(uchar x,uchar y,uchar dat)
{
uchar address;
if(y==1)
address="0x80"+x;
else
address="0xc0"+x;
LCD_write_command(address);
LCD_write_data(dat);
}
//////////////////////////////延时/////////////////////
void delay_n40us(uint n)
{
uint i;
uchar j;
for(i=n;i>0;i--)
for(j=0;j<15;j++)
;
}
//////////////////////////////////////
//////////////////////////坐标//////////////////////////////
void GotoXY(unsigned char x, unsigned char y)
{
uchar address;
if(y==0)
address="0x80"+x;
else
address="0xc0"+x;
LCD_write_command(address);
}
//将字符输出到液晶显示
void Printx(uchar x, uchar y,unsigned char *str)
{
GotoXY(x,y);
while(*str!='\0')
{ LCD_write_data(*str);
str++;
}
}
/////////////////////////////////////////////////////////////////////////状态///////////////////////////////////////////////////////////////////////////////
void State0()
{
Printx(0,0,"time ");
Printx(0,1," ");
delay_n40us(1000);
}
void State1()
{
Printx(0,0,"tempalarm ");
Printx(0,1," ");
delay_n40us(1000);
}
void State2()
{
Printx(0,0,"timealarmrange ");
Printx(0,1," ");
delay_n40us(1000);
}
void State3()
{
Printx(0,0,"1:timeset in");
Printx(0,1,"2:timalarm ");
delay_n40us(2000);
}
void State4()
{
Printx(0,0,"2:timalarm in");
Printx(0,1,"3:temalarm ");
delay_n40us(2000);
}
void State5()
{
Printx(0,0,"3:temalarm in");
Printx(0,1,"4:kuozhan ");
delay_n40us(2000);
}
void State6()
{
Printx(0,0,"4:kuozhan in");
Printx(0,1,"1:timeset ");
delay_n40us(2000);
}
void State7()
{
Printx(0,0,"jiztime ");
Printx(0,1," ");
delay_n40us(2000);
}
void State8()
{
Printx(0,0,"alarmtime ");
Printx(0,1," ");
delay_n40us(1000);
}
void State9()
{
Printx(0,0,"jizkuo ");
Printx(0,1," ");
delay_n40us(1000);
}
void State10()
{
Printx(0,0,"kuozhan ");
Printx(0,1," ");
delay_n40us(1000);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/***********菜单操作函数*************/
void MenuOperate(uchar key)
{
switch(key)
{
case 1: //返回键
{
Func_Index=Menu_Tab[Func_Index].Gore;
break;
}
case 2: //右
{
Func_Index=Menu_Tab[Func_Index].Right;
break;
}
case 3: //Up键
{
Func_Index=Menu_Tab[Func_Index].Up;
break;
}
case 4: //下键
{
Func_Index=Menu_Tab[Func_Index].Down;
break;
}
case 5: //确定键
{
Func_Index=Menu_Tab[Func_Index].Enter;
break;
}
case 6: //左键
{
Func_Index=Menu_Tab[Func_Index].Left;
break;
}
case 7: //返回上一层键
{
Func_Index=Menu_Tab[Func_Index].Goback1;
break;
}
// case 8: //扩展键
// {
// Func_Index1=Menu_Tab[Func_Index].Kuozhang;
// break;
// }
}
Func_Ptr=Menu_Tab[Func_Index].Operate; //执行当前操作
(*Func_Ptr)();
}
//////////////////////////////////键盘扫描////////////////////
void keyscan()
{
if(k1==0)
{delay_n40us(1000);
if(k1==0)
{
key=1;
}
}
if(k2==0)
{delay_n40us(1000);
if(k2==0)
{
key=2;
}
}
if(k3==0)
{delay_n40us(1000);
if(k3==0)
{
key=3;
}
}
if(k4==0)
{delay_n40us(1000);
if(k4==0)
{
key=4;
}
}
if(k5==0)
{delay_n40us(1000);
if(k5==0)
{
key=5;
}
}
if(k6==0)
{delay_n40us(1000);
if(k6==0)
{
key=6;
}
}
if(k7==0)
{delay_n40us(1000);
if(k7==0)
{
key=7;
}
}
if(k8==0)
{delay_n40us(1000);
if(k8==0)
{
key=8;
}
}
}
//////////////////////主函数////////////////////////
void main()
{
LCD_init();
Printx(0,0,"welcome to");
Printx(2,1,"jizzll'bolg");
delay_n40us(100000);
MenuOperate(0);
while(1)
{
keyscan();
MenuOperate(key);
key="0";
}
}
用户1334075 2008-10-25 17:18
用户1365849 2008-5-9 15:40
Cybershu 2008-5-8 18:06
用户393407 2008-5-3 14:20
用户1334075 2008-5-1 18:40