首页 >> 大全

C语言----基于旋转编码器按键的菜单结构

2023-11-09 大全 15 作者:考证青年

参考:

在不使用的情况下,做显示界面,菜单结构将会是很重要的东西。因为如果显示逻辑复杂,当遇上需要修改的界面的时候,复杂、混乱的显示逻辑(没错,就是那种很多语句的结构),将会使人抓狂。在参考了“傻孩子菜单框架”之后自己整理了一个菜单框架,主要应用在如:EC11旋转编码器上。这东西是什么,自己淘宝就知道了了。。。。

编码器提供3种不同的逻辑:左旋转、右旋转、确定。

这点跟我参考的菜单框架有点不同的,他的是4个按键逻辑。所以相应的要对菜单结构体进行改动。

显示逻辑:

(1)当检测到对应按键码时,进入菜单结构体中的按键处理函数,函数根据按键码的不同,要么移动菜单游标切换深度。要么加、减标志位。

(2)标志位为一个16bit数组如([2];),具有2个元素。元素0为当前的标志位状态,程序主要运用的是元素0。元素1用来保存上一次标志位的状态。如按键处理函数改变了“[0]”的值,只要将它与“[1]”对比,如果不同则代表这个标志位被程序改变了,将会触发此标志位管理的显示功能。这一过程类似于单片机的中断。检测到标志位改变则触发相应的中断事件。

_旋转按键编码器程序_旋转编码开关程序

(3) 界面深度处理:在最高深度时,按下“ENTER”就会进入下一深度,最低深度则会进入上一深度。那么中间的深度呢?我进行了一个处理,就是在中间的深度,如果当前的标志位达到最大值,则会跳转到上一深度。如果不是,则跳转下一深度。在VS上运行下面的代码,跳转到“布类、速度、返回”的位置就很明了。当显示“返回”时,“”这个标志位达到最大值“2”, 此时按下“”会跳转到第一深度,如果是“布类”、“速度”,则会跳转到对应的下一深度。

所以,这个菜单结构采用的是“消息->消息处理”的机制,按键可以改变标志位数值以及移动菜单游标到不同的结构体成员。实现同深度以及不同深度的结构体成员之间的跳转。

下面代码在 2015下编译运行通过,代码是一个简单的洗衣机菜单的例子。结构如下图:

旋转按键编码器程序__旋转编码开关程序

画面上有2个位置会显示内容,分别是位置1跟位置2。这两个位置显示的内容会根据我们的按键操作进行切换,比方位置一“模式”可以切换成显示“布类”,也可以切换成显示“牛仔”。具体可以运行以下代码:

#include 
#include   
#include  /************* LCD显示框架相关定义 **************/
#define Null 0  #define u8    unsigned char
#define u16   unsigned short
#define u32   unsigned int//比较标志位
#define CompareF(Flag)   (*Flag == *(Flag+1)) 
//同化标志位
#define ClearF(Flag)     (*(Flag+1) = *Flag)#define LEFT   1
#define RIGHT  3
#define ENTER  2void  MFunc_MD(u8 key);
void  MFunc_TB(u8 key);//菜单标志位结构体
struct MFlag
{u16 m1_Main[2];u16 m2_Mode[2];u16 m2_Water[2];u16 m3_type[2];u16 m3_speed[2];
};//菜单结构体
struct MenuItem
{ u16   MN;        //当前菜单标志位最大值u16  *MF;        //菜单标志位void (*Func)(u8 key);  //菜单功能函数struct MenuItem  *Next;struct MenuItem  *Prev;
};//声明菜单结构体变量
struct MenuItem  m1_Main[1];
struct MenuItem  m2_Option[2];
struct MenuItem  m3_Mode[2];struct MenuItem  *pMenu;//声明标志位结构体变量
struct MFlag  MenuF =
{{ 0,0 },{ 0,0 },{ 0,0 },{ 0,0 },{ 0,0 },
};/**************** 菜单结构体变量的定义 *****************/
//一级深度菜单结构体
struct MenuItem  m1_Main[1] =
{{2, &MenuF.m1_Main[0] ,MFunc_TB,m2_Option, Null },
};//二级深度菜单结构体
struct MenuItem  m2_Option[2] =
{{3, &MenuF.m2_Mode[0] , MFunc_MD, &m3_Mode[0], m1_Main },{5, &MenuF.m2_Water[0], MFunc_TB, Null,        m1_Main },
};//三级深度菜单结构体
struct MenuItem  m3_Mode[2] =
{{5, &MenuF.m3_type[0],  MFunc_TB, Null, &m2_Option[0] },{5, &MenuF.m3_speed[0], MFunc_TB, Null, &m2_Option[0] },
};/****************** 菜单跳转函数的定义 *******************///底部以及顶部菜单结构体成员的按键处理函数
//struct MenuItem  *Next;  其中一个为空,使用此菜单函数
//struct MenuItem  *Prev;
void  MFunc_TB(u8 key)
{switch (key){case LEFT:  if(*pMenu->MF>0)  *pMenu->MF -= 1;                   //当前标志位-1break;case RIGHT: if (*pMenu->MF < (pMenu->MN - 1))  *pMenu->MF += 1;  //当前标志位+1break;case ENTER:  if (pMenu->Prev == Null)	pMenu = pMenu->Next + *pMenu->MF;  //跳转到下一深度else			pMenu = pMenu->Prev;               //跳转到上一深度*(pMenu->MF + 1) += 1;             //刷新当前标志位,否则切换深度后不显示当前选项break;}
}//	struct MenuItem  *Next; 都不为空,使用此菜单功能函数,此函数跳转深度后会将跳转前的菜单成员的标志位清零
//  struct MenuItem  *Prev;
void  MFunc_MD(u8 key)
{switch (key){case LEFT:  if (*pMenu->MF>0)  *pMenu->MF -= 1;                  //当前标志位-1break;case RIGHT: if (*pMenu->MF < (pMenu->MN - 1))  *pMenu->MF += 1;  //当前标志位+1break;case ENTER: if (*pMenu->MF > (pMenu->MN - 2))          {*pMenu->MF = 0;                         //清零当前标志位,下一次进入该选项从0开始显示*(pMenu->MF+1) = 0;                     //清零当前标志位,下一次进入该选项从0开始显示pMenu = pMenu->Prev + *pMenu->Prev->MF; //跳转到上一深度}else{pMenu = pMenu->Next + *pMenu->MF;       //跳转到下一深度}*(pMenu->MF + 1) += 1;             break;}
}/****************** 显示功能函数的定义 *******************///同化标志位
void  ClearFlag(void)
{ClearF(MenuF.m1_Main);ClearF(MenuF.m2_Mode);ClearF(MenuF.m2_Water);ClearF(MenuF.m3_speed);ClearF(MenuF.m3_type);
}void D_MenuCur(void) 
{printf("菜单游标位置: ");switch (MenuF.m1_Main[0]){case 0: printf("位置1\r\n");  break;case 1: printf("位置2\r\n");  break;default: break;}                
}void D_location1(void)
{printf("位置1: ");//比较m2_Mode[0]与m2_Mode[1]是否相等if(CompareF(MenuF.m2_Mode)){switch (MenuF.m2_Mode[0]){case 0: printf("布类");  break;case 1: printf("速度");  break;case 2: printf("返回上层");  break;}}if (CompareF(MenuF.m3_speed)){switch (MenuF.m3_speed[0]){case 0: printf("最慢");  break;case 1: printf("慢速");  break;case 2: printf("中速");  break;case 3: printf("快速");  break;case 4: printf("最快");  break;}}if (CompareF(MenuF.m3_type)){switch (MenuF.m3_type[0]){case 0: printf("牛仔");  break;case 1: printf("帆布");  break;case 2: printf("尼龙");  break;case 3: printf("涤纶");  break;case 4: printf("棉布");  break;}}if (CompareF(MenuF.m1_Main)){if (MenuF.m1_Main[0] == 0){printf("模式");}}printf("\r\n");
}void D_location2(void)
{printf("位置2: ");if (CompareF(MenuF.m2_Water)){switch (MenuF.m2_Water[0]){case 0: printf("最低");  break;case 1: printf("低");  break;case 2: printf("中等");  break;case 3: printf("高");  break;case 4: printf("最高");  break;}}if (CompareF(MenuF.m1_Main)){if (MenuF.m1_Main[0] == 1){printf("水量");}}printf("\r\n");
}//输出画面
void printfGUI(void)
{printf("****************************\r\n");printf("                            \r\n");D_MenuCur();D_location1();D_location2();printf("                            \r\n");printf("****************************\r\n\r\n");
}//打印标志位
void printfLoc(void)
{printf("m1_Main = {x,x};\r\n",  MenuF.m1_Main[0],  MenuF.m1_Main[1]);printf("m2_Mode = {x,x};\r\n",  MenuF.m2_Mode[0],  MenuF.m2_Mode[1]);printf("m2_Water ={x,x};\r\n",  MenuF.m2_Water[0], MenuF.m2_Water[1]);printf("m3_type = {x,x};\r\n",  MenuF.m3_type[0],  MenuF.m3_type[1]);printf("m3_speed ={x,x};\r\n",  MenuF.m3_speed[0], MenuF.m3_speed[1]);printf("\r\n");
}//画面初始化
void GUI_Init(void)
{printf("****************************\r\n");printf("                            \r\n");printf("菜单游标位置: ");printf("位置1\r\n");printf("位置1: ");printf("模式\r\n");printf("位置2: ");printf("水量");printf("                            \r\n");printf("****************************\r\n\r\n");
}int main(void)
{u8 temp = 0;pMenu = &m1_Main;GUI_Init();  //初始化界面while (1){temp = _getch();switch (temp){case '1': (*(pMenu->Func))(LEFT);     break;case '3': (*(pMenu->Func))(RIGHT);    break;case '2': (*(pMenu->Func))(ENTER);    break;default:  break;}printfGUI();ClearFlag();  //清零标志位printfLoc();  //打印标志位}
}

运行截图:

旋转按键编码器程序_旋转编码开关程序_

_旋转编码开关程序_旋转按键编码器程序

当按下键盘的‘1’、‘2’、‘3’,会打印出当前的标志位,并且显示位置上面会换成标志位对应的字符。

在实际应用中,把打印字符换成输出对应图片即可。

另外,不要问我为什么菜单游标从“位置2”移到“位置1”,位置2的字符会消失。VS的字符输出功能是,显示你当前输出的内容,你移动到游标位置1,位置2的内容没有改变。。。

真正的LCD显示,你只需要更改你移动的地方,其他不变的地方,进行改动是需要刷图片浪费资源的。。。。如果变换一个标志位需要改动好几个位置的显示,自己修改一下“void (void)”等的显示功能函数。变动里面的判断逻辑即可。

tags: c语言

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了