专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
51单片机
keil c语言
2020-02-04 09:32
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
51单片机
9980
12
12
怎么实现多功能按键?即在按下设置键后,再按键进行相关配置,最后按确定键确定刚才的设置,请问这个程序怎样写?
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
12条回答
hepday
2020-02-04 20:07
#ifndef _MENU_H_
#define _MENU_H_
#include"AT89X52.h"
#include"LCD1602.h"
#define KEY_NULL 0x00
#define KEY_ESC 0x01
#define KEY_SET 0x08
#define KEY_UP 0x02
#define KEY_DOWN 0x04
///-----------------------------------------------
// LCD相关定义
///-----------------------------------------------
#define LCD_MAX_DISP_LINES (2)
///--------------------------------------------------------------------
// MENU相关定义
///--------------------------------------------------------------------
#define IS_ROOTMENU 0xFF
#define NOT_ROOTMENU 0x00
//菜单类型:正常菜单,选项型菜单(返回一数值),显示信息型菜单(显示一定信息)
#define MENUTYPE_NORMAL 0x01
#define MENUTYPE_OPTION 0x02
#define MENUTYPE_DISP 0x03
//--------------------------------------------------------------------*
// 目录结构体定义
//---------------------------------------------------------------------*/
struct MenuItem //typedef
{
char CurLevelMenuMaximum; //本级菜单的最大个数
char *DisplayString; //菜单条显示内容
void (*CurrentOperator)(); //该菜单需要的操作函数指针
struct MenuItem *ChildrenMenus; //子菜单指针
struct MenuItem *ParentMenus; //父菜单指针
unsigned char MenuType; //菜单类型:正常菜单,选项型菜单(返回一数值),显示信息型菜单(显示一定信息)
unsigned char *ReturnParameter; //返回参数
} Null;
unsigned char Para = 3;
void NullOperator(void)
{ }
//--------------------------------------------------------------------*
// 菜单数组声明
//---------------------------------------------------------------------*/
struct MenuItem RootMenu[4];
struct MenuItem RunState[3];
struct MenuItem SetTime[1];
struct MenuItem SetDateTime[1];
//--------------------------------------------------------------------*
// 全局变量定义声明区*
//---------------------------------------------------------------------*/
struct MenuItem (*MenuPoint) = RootMenu;
char DisplayStart = 0;
char UserChoose = 0;
char DisplayPoint = 0;
char MaxItems;
unsigned char NullParameter = 0;
unsigned char Option = 0;
//--------------------------------------------------------------------*
// char CurLevelMenuMaximum; //本级菜单的最大个数
// char *DisplayString; //菜单条显示内容
// void (*CurrentOperator)(); //该菜单需要的操作函数指针
// struct MenuItem *ChildrenMenus; //子菜单指针
// struct MenuItem *ParentMenus; //父菜单指针
//---------------------------------------------------------------------*/
const unsigned char RootMenu_RunState[] = {" 1.OpenSystem "};
const unsigned char RootMenu_SetTime [] = {" 2.SetPasword "};
const unsigned char RootMenu_DataOper[] = {" 3.DataOper "};
const unsigned char RootMenu_SysInfo [] = {" 4.SysInfo "};
struct MenuItem xdata RootMenu[4]= //根目录菜单
{
{4,RootMenu_RunState,NullOperator ,RunState,&Null,MENUTYPE_NORMAL,&NullParameter},
{4,RootMenu_SetTime ,NullOperator ,SetTime ,&Null,MENUTYPE_NORMAL,&NullParameter},//SetDateTime
{4,RootMenu_DataOper,NullOperator ,&Null ,&Null,MENUTYPE_NORMAL,&NullParameter},//
{4,RootMenu_SysInfo ,NullOperator ,&Null ,&Null,MENUTYPE_NORMAL,&NullParameter},
};
const unsigned char RunState0[] = {" 2400 "};
const unsigned char RunState1[] = {" 4800 "};
const unsigned char RunState2[] = {" 9600 "};
struct MenuItem xdata RunState[3]= //1级目录菜单A
{
{3,RunState0,NullOperator,&Null,RootMenu,MENUTYPE_OPTION,&Para},
{3,RunState1,NullOperator,&Null,RootMenu,MENUTYPE_OPTION,&Para},
{3,RunState2,NullOperator,&Null,RootMenu,MENUTYPE_OPTION,&Para},
};
const unsigned char SetTime0[] = {" Test "};
struct MenuItem xdata SetTime[1]= //2级目录菜单A
{
{1,SetTime0,NullOperator,&Null,RootMenu ,MENUTYPE_DISP,&NullParameter},
};
//--------------------------------------------------------------------*
// 函数声明区*
//---------------------------------------------------------------------*/
void sHOWMENU(void);
void KeyProcess_MenuUpdate(unsigned char KeyNum);
//------------------------------------------------------------------*
// 函数说明:目录显示函数*
//------------------------------------------------------------------*/
void sHOWMENU(void)
{ char StrTemp[17];
unsigned char i = 0x00;
bit M;
MaxItems = MenuPoint[0].CurLevelMenuMaximum;
DisplayPoint = DisplayStart;
if (MaxItems >= 2)
{ for (i = 0;i < LCD_MAX_DISP_LINES;i++)
{ WrintStringFor_LCD1602(i,0,MenuPoint[DisplayPoint].DisplayString);
if (MenuPoint[DisplayPoint].MenuType != MENUTYPE_DISP)
{ if ((DisplayPoint) == UserChoose)
{Set_LCD1602(0,i,0x7e);}
else
{Set_LCD1602(0,i,' ');}
WrintStringFor_LCD1602(1,i,StrTemp);
}
else{ WrintStringFor_LCD1602(0,i,StrTemp);}
DisplayPoint += 1;
if ((DisplayPoint) == (MaxItems))
{
DisplayPoint = 0;
}
}
}
else{ for (i = 0; i < MaxItems;i++)
{ WrintStringFor_LCD1602(i,0,MenuPoint[DisplayPoint].DisplayString);
if (MenuPoint[DisplayPoint].MenuType != MENUTYPE_DISP)
{ if ((DisplayPoint) == UserChoose)
{ Set_LCD1602(0,i,0x7e); }
else{ Set_LCD1602(0,i, ' '); }
WrintStringFor_LCD1602(1,i,StrTemp);
}
else { WrintStringFor_LCD1602(0,i,StrTemp);}
DisplayPoint += 1;
if ((DisplayPoint) == (MaxItems))
{ DisplayPoint = 0; }
}
//-----------------------------------------------------------------------/
//TODO:当该级菜单数<LCD能显示的行数,有些行需要显示空白
for (i= MaxItems;i < LCD_MAX_DISP_LINES;i++)
{
WrintStringFor_LCD1602(0, i, " ");
}
//-----------------------------------------------------------------------*/
}
}
//--------------------------------------------------
// [按键说明] *
// ----------------------------------- *
// [K1] KEY_UP(向上) *
// [K5] KEY_DOWN(向下) *
// [K2] KEY_ENTER(确定) *
// [K6] KEY_ESC(后退) *
//---------------------------------------------------/
void KeyProcess_MenuUpdate(unsigned char KeyNum)
{ if (KeyNum != KEY_NULL)
{ switch (KeyNum)
{ case KEY_UP:
UserChoose --;
if (UserChoose < 0)
{ UserChoose = MaxItems - 1;}
Option --;
if (Option >= MenuPoint[0].CurLevelMenuMaximum)
{ Option = MenuPoint[0].CurLevelMenuMaximum - 1;}
break;
case KEY_ESC:
if (MenuPoint[0].ParentMenus != &Null)
{ MenuPoint = MenuPoint[0].ParentMenus;
UserChoose = 0;
DisplayPoint = *MenuPoint[0].ReturnParameter;
}
break;
case KEY_DOWN:
UserChoose ++;
if (UserChoose == MaxItems)
{ UserChoose = 0; }
Option++;
if (Option >= MenuPoint[0].CurLevelMenuMaximum)
{ Option = 0; }
break;
case KEY_SET:
if (MenuPoint[UserChoose].CurrentOperator != NullOperator)
{ (*MenuPoint[UserChoose].CurrentOperator)(); }
//如果菜单类型不是“正常型MENUTYPE_NORMAL”,则按KEY_SET键返回上一级菜单
if ( MenuPoint[DisplayPoint].MenuType != MENUTYPE_NORMAL )
{ if (MenuPoint[UserChoose].ParentMenus != &Null) //如果操作函数不为空并且子菜单不为空,则进行菜单切换
{ * MenuPoint[0].ReturnParameter = Option; //保存选择参数
MenuPoint = MenuPoint[UserChoose].ParentMenus;
UserChoose = 0;
DisplayStart = 0;
}
}
else
{ if (MenuPoint[UserChoose].ChildrenMenus != &Null) //如果操作函数不为空并且子菜单不为空,则进行菜单切换
{ MenuPoint = MenuPoint[UserChoose].ChildrenMenus;
UserChoose = * MenuPoint[0].ReturnParameter;
DisplayStart = UserChoose;
Option = UserChoose;
}
}
break;
}
if ((UserChoose < DisplayStart) || (UserChoose > (DisplayStart+(LCD_MAX_DISP_LINES-1))))
{ DisplayStart = UserChoose; } //菜单翻页
sHOWMENU();
}
}
#endif
嘿嘿这是论坛里大神的,我正在学,表示很多看不懂
加载中...
查看其它12个回答
一周热门
更多
>
相关问题
【东软载波ESF0654 PDS开发板活动】开箱
1 个回答
东软载波ESF0654 PDS开发板外部中断
1 个回答
东软载波ESF0654 PDS开发板高级控制定时器AD16C4T
1 个回答
用串口调试助手为什么只能在hex模式接收发送而在文本模式不行
9 个回答
触摸芯片SC02B/SC04B在地砖灯的设计方案
1 个回答
相关文章
51单片机与蓝牙模块连接
0个评论
51单片机的硬件结构
0个评论
基于51单片机的无线遥控器制作
0个评论
51单片机 AD转换
0个评论
51单片机数码管递增显示
0个评论
如何实现对单片机寄存器的访问
0个评论
基于51单片机的指纹密码锁
0个评论
×
关闭
采纳回答
向帮助了您的知道网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
51单片机
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
×
付费偷看金额在0.1-10元之间
确定
×
关闭
您已邀请
0
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
#define _MENU_H_
#include"AT89X52.h"
#include"LCD1602.h"
#define KEY_NULL 0x00
#define KEY_ESC 0x01
#define KEY_SET 0x08
#define KEY_UP 0x02
#define KEY_DOWN 0x04
///-----------------------------------------------
// LCD相关定义
///-----------------------------------------------
#define LCD_MAX_DISP_LINES (2)
///--------------------------------------------------------------------
// MENU相关定义
///--------------------------------------------------------------------
#define IS_ROOTMENU 0xFF
#define NOT_ROOTMENU 0x00
//菜单类型:正常菜单,选项型菜单(返回一数值),显示信息型菜单(显示一定信息)
#define MENUTYPE_NORMAL 0x01
#define MENUTYPE_OPTION 0x02
#define MENUTYPE_DISP 0x03
//--------------------------------------------------------------------*
// 目录结构体定义
//---------------------------------------------------------------------*/
struct MenuItem //typedef
{
char CurLevelMenuMaximum; //本级菜单的最大个数
char *DisplayString; //菜单条显示内容
void (*CurrentOperator)(); //该菜单需要的操作函数指针
struct MenuItem *ChildrenMenus; //子菜单指针
struct MenuItem *ParentMenus; //父菜单指针
unsigned char MenuType; //菜单类型:正常菜单,选项型菜单(返回一数值),显示信息型菜单(显示一定信息)
unsigned char *ReturnParameter; //返回参数
} Null;
unsigned char Para = 3;
void NullOperator(void)
{ }
//--------------------------------------------------------------------*
// 菜单数组声明
//---------------------------------------------------------------------*/
struct MenuItem RootMenu[4];
struct MenuItem RunState[3];
struct MenuItem SetTime[1];
struct MenuItem SetDateTime[1];
//--------------------------------------------------------------------*
// 全局变量定义声明区*
//---------------------------------------------------------------------*/
struct MenuItem (*MenuPoint) = RootMenu;
char DisplayStart = 0;
char UserChoose = 0;
char DisplayPoint = 0;
char MaxItems;
unsigned char NullParameter = 0;
unsigned char Option = 0;
//--------------------------------------------------------------------*
// char CurLevelMenuMaximum; //本级菜单的最大个数
// char *DisplayString; //菜单条显示内容
// void (*CurrentOperator)(); //该菜单需要的操作函数指针
// struct MenuItem *ChildrenMenus; //子菜单指针
// struct MenuItem *ParentMenus; //父菜单指针
//---------------------------------------------------------------------*/
const unsigned char RootMenu_RunState[] = {" 1.OpenSystem "};
const unsigned char RootMenu_SetTime [] = {" 2.SetPasword "};
const unsigned char RootMenu_DataOper[] = {" 3.DataOper "};
const unsigned char RootMenu_SysInfo [] = {" 4.SysInfo "};
struct MenuItem xdata RootMenu[4]= //根目录菜单
{
{4,RootMenu_RunState,NullOperator ,RunState,&Null,MENUTYPE_NORMAL,&NullParameter},
{4,RootMenu_SetTime ,NullOperator ,SetTime ,&Null,MENUTYPE_NORMAL,&NullParameter},//SetDateTime
{4,RootMenu_DataOper,NullOperator ,&Null ,&Null,MENUTYPE_NORMAL,&NullParameter},//
{4,RootMenu_SysInfo ,NullOperator ,&Null ,&Null,MENUTYPE_NORMAL,&NullParameter},
};
const unsigned char RunState0[] = {" 2400 "};
const unsigned char RunState1[] = {" 4800 "};
const unsigned char RunState2[] = {" 9600 "};
struct MenuItem xdata RunState[3]= //1级目录菜单A
{
{3,RunState0,NullOperator,&Null,RootMenu,MENUTYPE_OPTION,&Para},
{3,RunState1,NullOperator,&Null,RootMenu,MENUTYPE_OPTION,&Para},
{3,RunState2,NullOperator,&Null,RootMenu,MENUTYPE_OPTION,&Para},
};
const unsigned char SetTime0[] = {" Test "};
struct MenuItem xdata SetTime[1]= //2级目录菜单A
{
{1,SetTime0,NullOperator,&Null,RootMenu ,MENUTYPE_DISP,&NullParameter},
};
//--------------------------------------------------------------------*
// 函数声明区*
//---------------------------------------------------------------------*/
void sHOWMENU(void);
void KeyProcess_MenuUpdate(unsigned char KeyNum);
//------------------------------------------------------------------*
// 函数说明:目录显示函数*
//------------------------------------------------------------------*/
void sHOWMENU(void)
{ char StrTemp[17];
unsigned char i = 0x00;
bit M;
MaxItems = MenuPoint[0].CurLevelMenuMaximum;
DisplayPoint = DisplayStart;
if (MaxItems >= 2)
{ for (i = 0;i < LCD_MAX_DISP_LINES;i++)
{ WrintStringFor_LCD1602(i,0,MenuPoint[DisplayPoint].DisplayString);
if (MenuPoint[DisplayPoint].MenuType != MENUTYPE_DISP)
{ if ((DisplayPoint) == UserChoose)
{Set_LCD1602(0,i,0x7e);}
else
{Set_LCD1602(0,i,' ');}
WrintStringFor_LCD1602(1,i,StrTemp);
}
else{ WrintStringFor_LCD1602(0,i,StrTemp);}
DisplayPoint += 1;
if ((DisplayPoint) == (MaxItems))
{
DisplayPoint = 0;
}
}
}
else{ for (i = 0; i < MaxItems;i++)
{ WrintStringFor_LCD1602(i,0,MenuPoint[DisplayPoint].DisplayString);
if (MenuPoint[DisplayPoint].MenuType != MENUTYPE_DISP)
{ if ((DisplayPoint) == UserChoose)
{ Set_LCD1602(0,i,0x7e); }
else{ Set_LCD1602(0,i, ' '); }
WrintStringFor_LCD1602(1,i,StrTemp);
}
else { WrintStringFor_LCD1602(0,i,StrTemp);}
DisplayPoint += 1;
if ((DisplayPoint) == (MaxItems))
{ DisplayPoint = 0; }
}
//-----------------------------------------------------------------------/
//TODO:当该级菜单数<LCD能显示的行数,有些行需要显示空白
for (i= MaxItems;i < LCD_MAX_DISP_LINES;i++)
{
WrintStringFor_LCD1602(0, i, " ");
}
//-----------------------------------------------------------------------*/
}
}
//--------------------------------------------------
// [按键说明] *
// ----------------------------------- *
// [K1] KEY_UP(向上) *
// [K5] KEY_DOWN(向下) *
// [K2] KEY_ENTER(确定) *
// [K6] KEY_ESC(后退) *
//---------------------------------------------------/
void KeyProcess_MenuUpdate(unsigned char KeyNum)
{ if (KeyNum != KEY_NULL)
{ switch (KeyNum)
{ case KEY_UP:
UserChoose --;
if (UserChoose < 0)
{ UserChoose = MaxItems - 1;}
Option --;
if (Option >= MenuPoint[0].CurLevelMenuMaximum)
{ Option = MenuPoint[0].CurLevelMenuMaximum - 1;}
break;
case KEY_ESC:
if (MenuPoint[0].ParentMenus != &Null)
{ MenuPoint = MenuPoint[0].ParentMenus;
UserChoose = 0;
DisplayPoint = *MenuPoint[0].ReturnParameter;
}
break;
case KEY_DOWN:
UserChoose ++;
if (UserChoose == MaxItems)
{ UserChoose = 0; }
Option++;
if (Option >= MenuPoint[0].CurLevelMenuMaximum)
{ Option = 0; }
break;
case KEY_SET:
if (MenuPoint[UserChoose].CurrentOperator != NullOperator)
{ (*MenuPoint[UserChoose].CurrentOperator)(); }
//如果菜单类型不是“正常型MENUTYPE_NORMAL”,则按KEY_SET键返回上一级菜单
if ( MenuPoint[DisplayPoint].MenuType != MENUTYPE_NORMAL )
{ if (MenuPoint[UserChoose].ParentMenus != &Null) //如果操作函数不为空并且子菜单不为空,则进行菜单切换
{ * MenuPoint[0].ReturnParameter = Option; //保存选择参数
MenuPoint = MenuPoint[UserChoose].ParentMenus;
UserChoose = 0;
DisplayStart = 0;
}
}
else
{ if (MenuPoint[UserChoose].ChildrenMenus != &Null) //如果操作函数不为空并且子菜单不为空,则进行菜单切换
{ MenuPoint = MenuPoint[UserChoose].ChildrenMenus;
UserChoose = * MenuPoint[0].ReturnParameter;
DisplayStart = UserChoose;
Option = UserChoose;
}
}
break;
}
if ((UserChoose < DisplayStart) || (UserChoose > (DisplayStart+(LCD_MAX_DISP_LINES-1))))
{ DisplayStart = UserChoose; } //菜单翻页
sHOWMENU();
}
}
#endif
嘿嘿这是论坛里大神的,我正在学,表示很多看不懂
一周热门 更多>