2019-03-24 17:48发布
shower.xu 发表于 2015-9-18 14:27 不可能搜不到吧,论坛里有大神讲过,而且讲得很详细。估计是你要直接能下载就跑的代码
硕果累累 发表于 2015-9-18 21:49 我也和你有同样的感受,我也在学习菜单设计,也找了许多这方面的程序来学习,可是一直都是稀里糊涂的,看不 ...
最多设置5个标签!
这个程序是我认为功能能够实现,能够在我的板子上面跑起来,函数清晰。
********感谢原作者的分享***********************
- #include "menu.h"
- #include "oled.h"
- #include "key.h"
- #include "delay.h"
- #include "text.h"
- #include "fontupd.h"
- /*菜单结构定义*/
- struct Option
- {
- unsigned char KeyLevel; //菜单选项所属菜单表号
- unsigned char EnterIndex; //选项进入索引号
- unsigned char CancelIndex; //选项退出索引号
- unsigned char *KeyWord; //菜单选项文字描述指针
- unsigned char WordMete; //菜单选项描述文字字节数
- };
- /**
- * 具体菜单选项定义,定义一个结构数组
- * 存储在编码区,节省内存RAM
- **/
- struct Option sOption[OPTIONMETE] =
- {
- /*菜单表号 进入索引 退出索引 菜单选项文字 菜单选项文字字节数*/
- {0, OPTIONMETE - 1, 0, "1.亮度调节", 10},//0
- {0, 6, 1, "2.时间设置", 10},//1
- {0, OPTIONMETE - 1, 2, "3.系统检测", 10},//2
- {0, OPTIONMETE - 1, 3, "4.修改密码", 10},//3
- {0, OPTIONMETE - 1, 4, "5.帮助说明", 10},//4
- {0, OPTIONMETE - 1, 5, "6.系统信息", 12},//5
- {1, OPTIONMETE - 1, 1, "1.时钟设置", 10},//6
- {1, OPTIONMETE - 1, 1, "2.日期设置", 10},//7
- };
- /*菜单表分类数组*/
- unsigned char Level[MENULEVEL][3] =
- {
- /*每层表单对应的开始索引 结束索引 选项数目*/
- {0, 5, 6},
- {6, 7, 2},
- };
- /*菜单索引定义*/
- unsigned char FirstLineDisIndex = 0; //屏幕第一行显示的索引号
- unsigned char SelectLine_L = 1; //原来选中行
- unsigned char SelectLine = 1; //当前选择的行
- unsigned char SelectIndex = 0; //当前选定行对应的索引号
- unsigned char LastIndex = 0; //进入功能函数前的索引号,判断具体功能使用
- /**
- * @name void Select_Line(unsigned char line, unsigned char clear)
- * @brief 选中行反白显示
- * @param line:选中行 clear:1,选中行清除反白 0,选中行反白显示
- * @retval none
- */
- void Select_Line(unsigned char line, unsigned char clear)
- {
- switch (line) //选择行
- {
- case 1:
- OLED_Fill(0, 0, 127, 15, 0); //清除原来的显示
- Show_Str(0, 0, sOption[FirstLineDisIndex].WordMete*8, 16,
- sOption[FirstLineDisIndex].KeyWord, 16, clear);
- break;
- case 2:
- OLED_Fill(0, 16, 127, 31, 0); //清除原来的显示
- Show_Str(0, 16, sOption[FirstLineDisIndex+1].WordMete*8, 16,
- sOption[FirstLineDisIndex+1].KeyWord, 16, clear);
- break;
- case 3:
- OLED_Fill(0, 32, 127, 47, 0); //清除原来的显示
- Show_Str(0, 32, sOption[FirstLineDisIndex+2].WordMete*8, 16,
- sOption[FirstLineDisIndex+2].KeyWord, 16, clear);
- break;
- case 4:
- OLED_Fill(0, 48, 127, 63, 0); //清除原来的显示
- Show_Str(0, 48, sOption[FirstLineDisIndex+3].WordMete*8, 16,
- sOption[FirstLineDisIndex+3].KeyWord, 16, clear);
- break;
- default :
- break;
- }
- delay_ms(10);
- }
- /**
- * @name void Display_OLEDMenu (void)
- * @brief 刷新菜单功能函数
- * 采用的do{}while(0)循环
- * @param none
- * @retval none
- */
- void Display_OLEDMenu (void)
- {
- unsigned char LineMete = Level[sOption[SelectIndex].KeyLevel][2]; //循环量,显示行数
- /*
- unsigned char LineMtet=Level[sOption[当前选定行对应的索引号].菜单选项所属菜单表号][2]
- */
- OLED_Fill(0, 0, 128, 64, 0); //清屏,否则会出现一些乱码 ,写0来清屏
- delay_ms(10);
- do //分别显示各行菜单项
- {
- OLED_Fill(0, 0, 127, 15, 0);
- //在指定位置开始显示一个字符串
- //支持自动换行
- //(x,y):起始坐标
- //width,height:区域
- //str :字符串
- //size :字体大小
- //mode:0,非叠加方式;1,叠加方式
- //unsigned char FirstLineDisIndex = 0;屏幕第一行显示的索引号
- //unsigned char *KeyWord; //菜单选项文字描述指针
- //unsigned char WordMete; //菜单选项描述文字字节数
- Show_Str(0, 0, sOption[FirstLineDisIndex].WordMete*8, 16,
- sOption[FirstLineDisIndex].KeyWord, 16, 1);
- //unsigned char LineMete = Level[sOption[SelectIndex].KeyLevel][2]; //循环量,显示行数
- if(--LineMete == 0) break;
- OLED_Fill(0, 16, 127, 31, 0);
- Show_Str(0, 16, sOption[FirstLineDisIndex+1].WordMete*8, 16,
- sOption[FirstLineDisIndex+1].KeyWord, 16, 1);
- if(--LineMete == 0) break;
- OLED_Fill(0, 32, 127, 47, 0);
- Show_Str(0, 32, sOption[FirstLineDisIndex+2].WordMete*8, 16,
- sOption[FirstLineDisIndex+2].KeyWord, 16, 1);
- if(--LineMete == 0) break;
- OLED_Fill(0, 48, 127, 63, 0);
- Show_Str(0, 48, sOption[FirstLineDisIndex+3].WordMete*8, 16,
- sOption[FirstLineDisIndex+3].KeyWord, 16, 1);
- }
- while(0);
- Select_Line(SelectLine_L, 1); //消除上一行反白
- Select_Line(SelectLine, 0); //填充所需反白
- }
- /**
- * @name bool MenuLevelStart (void)
- * @brief 判断当前索引是否是表单第一项功能函数
- * @param none
- * @retval 返回Bit标志,是第一项返回TURE,不是返回FALSE
- */
- bool MenuLevelStart (void)
- {
- unsigned char i = MENULEVEL;
- do
- {
- i--;
- if(SelectIndex == Level[i][0])
- return TURE;
- }
- while(i);
- return FALSE;
- }
- /**
- * @name bool MenuLevelEnd (void)
- * @brief 判断当前索引是否是表单最后一项功能函数
- * @param none
- * @retval 返回Bit标志,是最后一项返回TURE,不是返回FALSE
- */
- bool MenuLevelEnd (void)
- {
- unsigned char i = MENULEVEL;
- do
- {
- i--;
- if(SelectIndex == Level[i][1])
- return TURE;
- }
- while(i);
- return FALSE;
- }
- /**
- * @name void MenuUpOneOption (void)
- * @brief 菜单上移一项函数
- * @param none
- * @retval none
- */
- void MenuUpOneOption (void)
- {
- if(MenuLevelStart ()) //如果当前为表单第一项
- {
- if(Level[sOption[SelectIndex].KeyLevel][2] >= 4) //并且表单中选项数目大于等于4个
- {
- FirstLineDisIndex = Level[sOption[SelectIndex].KeyLevel][1] - 3; //第一行显示索引号为倒数第四项
- SelectIndex = Level[sOption[SelectIndex].KeyLevel][1]; //选择索引为表单最后一项
- SelectLine_L = SelectLine; //记录原来行
- SelectLine = 4; //标记选择行为第四行
- }
- else //如果选项数目并不大于四个
- {
- SelectIndex = Level[sOption[SelectIndex].KeyLevel][1]; //选择索引为当前表单最后一个
- SelectLine_L = SelectLine; //记录原来行
- SelectLine = Level[sOption[SelectIndex].KeyLevel][2]; //显示行表单数目(最后一个)
- }
- }
- else //如果当前不是开始索引
- {
- if(SelectLine == 1) //并且已经在屏幕最上边一行
- {
- FirstLineDisIndex--; //显示索引上移
- SelectIndex--; //选择索引自减
- SelectLine_L = SelectLine; //记录原来行
- SelectLine = 1; //选择行还是第一行
- }
- else //如果不是第一行
- {
- SelectLine_L = SelectLine; //记录原来行
- SelectLine--; //选择行自减
- SelectIndex--; //选择索引自减
- }
- }
- Display_OLEDMenu(); //刷新屏幕显示
- }
- /**
- * @name void MenuDownOneOption (void)
- * @brief 菜单下移一项函数
- * @param none
- * @retval none
- */
- void MenuDownOneOption (void)
- {
- if(MenuLevelEnd ()) //如果当前是表单最后一个索引
- {
- FirstLineDisIndex = Level[sOption[SelectIndex].KeyLevel][0]; //第一行显示索引为表单第一个选项
- SelectIndex = Level[sOption[SelectIndex].KeyLevel][0]; //选择索引为表单第一个选项索引
- SelectLine_L = SelectLine; //记录原来行
- SelectLine = 1; //选择行为第一行
- }
- else //如果不是最后的索引
- {
- if(SelectLine != 4) //如果当前不是屏幕最底行
- {
- SelectIndex++; //选择索引自加
- SelectLine_L = SelectLine; //记录原来行
- SelectLine++; //选择行下移
- }
- else //如果是屏幕最低行
- {
- FirstLineDisIndex++; //第一行显示下移
- SelectIndex++; //选择索引自加
- }
- }
- Display_OLEDMenu(); //刷新屏幕显示
- }
- /**
- * @name void MenuEnterOption (void)
- * @brief 进入某项功能函数
- * @param none
- * @retval none
- */
- void MenuEnterOption (void)
- {
- LastIndex = SelectIndex; //标记进入前的索引号(以便判断具体功能)
- SelectIndex = sOption[SelectIndex].EnterIndex; //更新选择索引为之前索引号对应进入索引
- if(SelectIndex != OPTIONMETE - 1) //如果当前索引不是功能选择索引
- {
- FirstLineDisIndex = Level[sOption[SelectIndex].KeyLevel][0]; //第一行显示为进入表单第一项
- SelectLine_L = SelectLine;
- SelectLine = 1; //设定第一行为选择行
- Display_OLEDMenu (); //刷新菜单
- }
- else
- {
- FunctionAction (); //如果是功能选择项,进入功能分支判断函数
- }
- }
- /**
- * @name void MenuCancelOption (void)
- * @brief 菜单退出功能函数
- * @param none
- * @retval none
- */
- void MenuCancelOption (void)
- {
- if(SelectIndex != OPTIONMETE - 1) //如果不是从功能返回
- {
- SelectIndex = sOption[SelectIndex].CancelIndex; //选择索引为选项返回索引
- }
- else //如果是从功能返回
- {
- SelectIndex = LastIndex; //索引等于进入前保存索引
- }
- if(Level[sOption[SelectIndex].KeyLevel][2] >= 4) //如果返回表单选项数目大于4个
- {
- if(SelectIndex > Level[sOption[SelectIndex].KeyLevel][1] - 3) //根据返回选项确定显示首项
- {
- FirstLineDisIndex = Level[sOption[SelectIndex].KeyLevel][1] - 3;
- SelectLine_L = SelectLine;
- SelectLine = 4 - (Level[sOption[SelectIndex].KeyLevel][1] - SelectIndex);
- }
- else //一般显示方式
- {
- FirstLineDisIndex = SelectIndex; //第一行显示索引
- SelectLine_L = SelectLine;
- SelectLine = 1; //选择第一行
- }
- }
- else //如果返回表单选项数目不足4个
- {
- FirstLineDisIndex = Level[sOption[SelectIndex].KeyLevel][0]; //第一行显示索引为表单第一项
- SelectLine_L = SelectLine;
- SelectLine = SelectIndex - Level[sOption[SelectIndex].KeyLevel][0] + 1; //选择行标志为当前选择索引对应行
- }
- Display_OLEDMenu (); //刷新菜单
- }
- /**
- * @name void ShutDown (void)
- * @brief 某一项功能函数 实际应该改为实际功能函数
- * @param none
- * @retval none
- */
- void SystemState (void)
- {
- OLED_Clear(); //清屏
- delay_ms(1);
- Show_Str(16, 29, 128, 16, "系统版本V1.0", 16, 1);
- }
- void System_Help (void)
- {
- OLED_Clear(); //清屏
- delay_ms(1);
- Show_Str(0, 0, 128, 16, "1.上下键选择", 16, 1);
- Show_Str(0, 16, 128, 16, "2.左键确定", 16, 1);
- Show_Str(0, 32, 128, 16, "3.右键退出", 16, 1);
- }
- void SystemTest (void)
- {
- OLED_Clear(); //清屏
- delay_ms(1);
- if (font_init())
- {
- OLED_Fill(0, 16, 128, 31, 0);
- Show_Str(32, 16, 128, 16, "字库错误", 16, 1);
- }
- else
- {
- OLED_Fill(0, 16, 128, 31, 0);
- Show_Str(32, 16, 128, 16, "字库正常", 16, 1);
- }
- }
- u16 radio = 0x7F;
- void OLED_Light (void)
- {
- u8 flag = 1;
- OLED_Clear(); //清屏
- delay_ms(1);
- Show_Str(32, 0, 128, 16, "亮度调节", 16, 1);
- OLED_DrawRectangle(0, 16, 93, 31, 1); //画进度条的边框
- while (1)
- {
- /*限制进度条的范围*/
- if (radio <= 2)
- {
- radio = 2;
- }
- else if (radio >= 255)
- {
- radio = 255;
- }
- OLED_Write_Com(0x81); //对比度设置
- OLED_Write_Com(radio); //1~255;默认0X7F (亮度设置,越大越亮)
- if (flag == 1)
- {
- flag = 0;
- OLED_Fill(1+(92 * radio / 255), 17, 93, 31, 0); //消除进度条的多余部分
- OLED_Fill(1, 17, 1+(92 * radio / 255), 31, 1); //填充进度条
- OLED_ShowNum(94, 16, (100 * radio / 255), 3, 16, 1); //显示进度百分比
- OLED_ShowChar(120, 16, '%', 16, 1);
- }
- delay_ms(10);
- switch (KEY_Scan(1)) //按键扫描
- {
- case KEY_UP : //按上键增加亮度
- flag = 1;
- radio += 2;
- break;
- case KEY_DOWN : //按下键减小亮度
- flag = 1;
- radio -= 2;
- break;
- case KEY_RIGHT : //按右键退出
- MenuCancelOption();
- return;
- default :
- break;
- }
- }
- }
- void NoThisFunction (void)
- {
- unsigned char Font[] = {"没有这个功能"};
- OLED_Clear(); //清屏
- delay_ms(1);
- Show_Str(16, 16, 128, 16, Font, 16, 1);
- delay_ms(500);
- MenuCancelOption();
- }
- /**
- * @name void FunctionAction (void)
- * @brief 具体功能散转函数
- * @param none
- * @retval none
- */
- void FunctionAction (void)
- {
- switch (LastIndex) //根据进入前的索引判断具体函数
- {
- case 0:
- OLED_Light();
- break;
- // case 1:
- // break;
- // case 2:
- // break;
- case 2:
- SystemTest();
- break;
- // case 4:
- // break;
- case 4:
- System_Help();
- break;
- case 5:
- SystemState();
- break;
- default:
- NoThisFunction();
- break; //如果没有具体操作,显示没有这个功能
- }
- }
- /**
- * @name void KeyCodeAction (unsigned char KeyCode)
- * @brief 菜单操作按键处理散转函数
- * @param KeyCode:按键值 实际使用应根据自己的按键重新编写case项
- * @retval none
- */
- void KeyCodeAction (unsigned char KeyCode)
- {
- switch (KeyCode)
- {
- case KEY_UP:
- MenuUpOneOption();
- break; //如果是向上按键,则菜单向上,以下类似
- case KEY_DOWN:
- MenuDownOneOption();
- break;
- case KEY_LEFT:
- MenuEnterOption();
- break;
- case KEY_RIGHT:
- MenuCancelOption();
- break;
- default:
- break;
- }
- }
复制代码搜的到,但是看的不是太明白,能力还没到家,想找个清晰一点的参考学习一下,还没懒到吃现成的呢
谢谢分享,在看您分享的代码了
一周热门 更多>