原创 EDN51静态菜单编写

2008-4-29 23:06 2796 7 12 分类: MCU/ 嵌入式

点击下载


这个是静态的菜单,现在准备做个电子温度闹钟,用动态的。


如果只是控制的法,静态的已经够用了。


程序中存在些不如意的地方,希望和大家一起交流。


#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";
  }


}

PARTNER CONTENT

文章评论5条评论)

登录后参与讨论

用户1334075 2008-10-25 17:18

(*Func_Ptr)(); 这是什么函数,没有看到。另外,你运行后看到的结果和你预期的一致吗?我仿真的结果不对

用户1365849 2008-5-9 15:40

uchar address; if(y==0) address="0x80"+x; else address="0xc0"+x; LCD_write_command(address); 里面的"0x80"需要加引号嘛?

Cybershu 2008-5-8 18:06

学习

用户393407 2008-5-3 14:20

学习思路

用户1334075 2008-5-1 18:40

学学这种思路,挺不错的
相关推荐阅读
jizzll_617398179 2010-02-08 10:53
正确理解A/D转换器的输入
http://www.freescale.com.cn/tech_ariticles/2005/1102_1.asp 许多嵌入式应用都会用到A/D转换器。然而,如果错误连接了A/D转换器输入端的电路,...
jizzll_617398179 2010-01-12 13:37
好久没来,都长草了
好久没来,都长草了,呵呵。整天忙得很,不过估计再过两个月会轻松点~\(≧▽≦)/~啦啦啦...
jizzll_617398179 2009-03-16 21:57
很奇怪,我收到站内信,但是却找不到发信人呢
发信人是个[],点击就跳到我自己的主页了。只好在这里给那位朋友留言了。 我不知道你说的哪篇文章,还有我也不知道你的EDN的ID。你可以在博客上面留言的。...
jizzll_617398179 2009-03-14 13:08
如何在EXCEL中使用16进制数
最近需要计算串口发送的数据,太多而且比较麻烦。知道EXECL功能强大,所以网上找了找,刚好,不错,很方便。网上找到的http://hi.bccn.net/space-99452-do-blog-id-...
jizzll_617398179 2009-03-05 14:37
〖常识〗不同晶振的最大波特率及其误差
最近犯了个错误,呵呵,晶振和波特率的问题,特查了记在这里,O(∩_∩)O~〖常识〗不同晶振的最大波特率及其误差http://www.aoxue.org/bbs/read.php?tid=65585不同...
jizzll_617398179 2009-02-11 14:30
大端模式和小端模式
转载http://www.cnblogs.com/TsuiLei/archive/2008/10/29/1322504.html大端格式:在这种格式中,字数据的高字节存储在低地址中,而字数据的低字节则...
我要评论
5
7
关闭 站长推荐上一条 /3 下一条