單片機源程序如下:
- /***
- *****************************************************************************
- * @file menu.c
- * @author 原作:張子墨
- * @version V1.0
- * @brief OLED四行多級菜單
- *****************************************************************************
- ***/
- #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 刷新菜單功能函數
- * @param none
- * @retval none
- */
- void Display_OLEDMenu (void)
- {
- unsigned char LineMete = Level[sOption[SelectIndex].KeyLevel][2]; //循環量,顯示行數
- OLED_Fill(0, 0, 128, 64, 0); //清屏,否則會出現一些亂碼
- delay_ms(10);
- do //分別顯示各行菜單項
- {
- OLED_Fill(0, 0, 127, 15, 0);
- Show_Str(0, 0, sOption[FirstLineDisIndex].WordMete*8, 16, \
- sOption[FirstLineDisIndex].KeyWord, 16, 1);
- 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:
復制代碼
這個是Keil4的工程,用Keil5編譯有錯誤:
OLED菜單程序.rar
(1.09 MB, 下載次數: 750)
2017-7-21 02:40 上傳
點擊文件名下載附件
僅供參考
|