找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2727|回复: 3
收起左侧

STM32C8T6单片机IIC OLED0.96GUI 菜单程序设计

[复制链接]
ID:302293 发表于 2022-4-25 10:40 | 显示全部楼层 |阅读模式
   程序测试正常,有什么问题可以一起研究

单片机源程序如下:
  1. /**
  2. * @file GUI.c
  3. * @author LQH
  4. * @brief  使用本库时,注意初始化字符串一定要占满15个字符,不然,不会将上次的字符覆盖
  5. * @version 0.1
  6. * @date 2022-02-13
  7. *
  8. * @copyright Copyright (c) 2022
  9. *
  10. */
  11. #include "GUI.h"
  12. #include "oled.h"
  13. #include "bmp.h"

  14. #include "keyscan.h"
  15. #include "mytime.h"

  16. int8_t selectItem = 0;//当前菜单在当前菜单页的索引,最大为3,一页最多显示四个菜单
  17. int8_t scrollBar  = 0;//滚动条
  18. struct Menu_t *menuPoint;//当前菜单

  19. //拿来做测试的数据
  20. int8_t kp = 0;
  21. int8_t ki = 0;
  22. int8_t kd = 0;
  23. int16_t count_test=0;
  24. uint16_t count1=0,count2=2,count3=4,count4=6,count5=8;

  25. //一些菜单的功能函数
  26. void KpSub(void);
  27. void KiAdd(void);
  28. void KdAdd(void);
  29. void KpAdd(void);
  30. void HourAdd(void);
  31. void MinuteAdd(void);
  32. void SecondAdd(void);
  33. void YearAdd(void);
  34. void MonthAdd(void);
  35. void DayAdd(void);
  36. void TimeOK(void);
  37. void TimeSetInit(void);

  38. //主UI
  39. struct MenuProperty_t MainUIProperty={1,0};
  40. struct Menu_t MainUI=
  41. {&MainUIProperty,"MainUI" ,NULL,NULL,NULL};

  42. //主菜单
  43. struct MenuProperty_t menuMainProperty={4,0};
  44. struct Menu_t menuMain[4]=
  45. {
  46.         {&menuMainProperty,"last menu     ", NULL,NULL, &MainUI,NULL},
  47.         {&menuMainProperty,"Animal        ", NULL,NULL, &MainUI,NULL},
  48.         {&menuMainProperty,"Pid           ", NULL,NULL, &MainUI,NULL},
  49.         {&menuMainProperty,"Time set      ", NULL,TimeSetInit, &MainUI,NULL}
  50. };
  51. //animal的子菜单
  52. struct MenuProperty_t setMenu1Property={6,2};
  53. struct Menu_t setMenu1[6]=
  54. {
  55.         {&setMenu1Property,"last menu     ",NULL,NULL,menuMain,NULL},
  56.         {&setMenu1Property,"bull          ",NULL,NULL,menuMain,NULL},
  57.         {&setMenu1Property,"bird          ",NULL,NULL,menuMain,NULL},
  58.         {&setMenu1Property,"dog           ",NULL,NULL,menuMain,NULL},
  59.         {&setMenu1Property,"bow           ",NULL,NULL,menuMain,NULL},
  60.         {&setMenu1Property,"fish          ",NULL,NULL,menuMain,NULL}
  61. };
  62. //Pid的子菜单
  63. struct MenuProperty_t setMenu2Property={5,1};
  64. struct Menu_t setMenu2[5]=
  65. {
  66.         {&setMenu2Property,"last menu      ",NULL, NULL, menuMain,NULL},
  67.         {&setMenu2Property,"KP   0         ",KpSub,KpAdd,menuMain,NULL},
  68.         {&setMenu2Property,"KI   0         ",NULL, KiAdd,menuMain,NULL},
  69.         {&setMenu2Property,"KD   0         ",NULL, KdAdd,menuMain,NULL},
  70.         {&setMenu2Property,"PWM  0         ",NULL, NULL, menuMain,NULL},
  71. };
  72. //Time set的子菜单
  73. struct MenuProperty_t setMenu3Property={8,4};
  74. struct Menu_t setMenu3[8]=
  75. {
  76.         {&setMenu3Property,"last menu      ",NULL, NULL,menuMain,NULL},
  77.         {&setMenu3Property,"Hour   0       ",NULL, HourAdd,menuMain,NULL},
  78.         {&setMenu3Property,"Minute 0       ",NULL, MinuteAdd,menuMain,NULL},
  79.         {&setMenu3Property,"Second 0       ",NULL, SecondAdd,menuMain,NULL},
  80.         {&setMenu3Property,"Year   0       ",NULL, YearAdd,menuMain,NULL},
  81.         {&setMenu3Property,"Month  0       ",NULL, MonthAdd,menuMain,NULL},
  82.         {&setMenu3Property,"Day    0       ",NULL, DayAdd,menuMain,NULL},
  83.         {&setMenu3Property,"OK             ",NULL, TimeOK,menuMain,NULL},
  84. };

  85. void KpSub()
  86. {
  87.         kp--;
  88. }

  89. void KpAdd()
  90. {
  91.         kp++;
  92. }

  93. void KiAdd()
  94. {
  95.         ki++;
  96. }

  97. void KdAdd()
  98. {
  99.         kd++;
  100. }

  101. void HourAdd(void)
  102. {
  103.         myTimeTemp.Hour++;
  104.         if(myTimeTemp.Hour>23)
  105.                 myTimeTemp.Hour=0;        
  106. }
  107. void MinuteAdd(void)
  108. {
  109.         myTimeTemp.Minute++;
  110.         if(myTimeTemp.Minute>59)
  111.                 myTimeTemp.Minute=0;        
  112. }
  113. void SecondAdd(void)
  114. {
  115.         myTimeTemp.Second++;
  116.         if(myTimeTemp.Second>59)
  117.                 myTimeTemp.Second=0;
  118. }
  119. void YearAdd(void)
  120. {
  121.         myTimeTemp.Year++;
  122. }
  123. void MonthAdd(void)
  124. {
  125.         myTimeTemp.Month++;
  126.         if(myTimeTemp.Month>12)
  127.                 myTimeTemp.Month=1;
  128. }
  129. void DayAdd(void)
  130. {
  131.         myTimeTemp.Day++;
  132.         if(myTimeTemp.Day>30)
  133.                 myTimeTemp.Day=1;
  134. }
  135. void TimeOK(void)
  136. {
  137.         myTime = myTimeTemp;
  138. }

  139. void TimeSetInit(void)
  140. {
  141.         myTimeTemp = myTime;
  142. }
  143. /**
  144. * @brief 主界面,可以自己设置图画,我这里画了两条线和一个时钟
  145. *
  146. */
  147. void MainUiSet()
  148. {
  149.         int i;
  150.         u8 time_x = 18,time_y = 12,date_x=26,date_y=40;
  151.         for(i=1;i<15;i++)
  152.         {
  153.                 OLED_ShowChar(8*i,0, '-',16,1);
  154.                 OLED_ShowChar(8*i,48,'-',16,1);
  155.         }        

  156.         OLED_ShowNum(time_x,    time_y,myTime.Hour  ,2,24,1);
  157.         OLED_ShowChar(time_x+24,time_y,':'   ,24,1);
  158.         OLED_ShowNum(time_x+36, time_y,myTime.Minute,2,24,1);
  159.         OLED_ShowChar(time_x+60,time_y,':'   ,24,1);
  160.         OLED_ShowNum(time_x+72, time_y,myTime.Second,2,24,1);
  161.         
  162.         OLED_ShowNum(date_x,    date_y,myTime.Year  ,4,16,1);
  163.         OLED_ShowChar(date_x+32,date_y,'/'   ,16,1);
  164.         OLED_ShowNum(date_x+40, date_y,myTime.Month,2,16,1);
  165.         OLED_ShowChar(date_x+56,date_y,'/'   ,16,1);
  166.         OLED_ShowNum(date_x+64, date_y,myTime.Day,  2,16,1);
  167. }

  168. /**
  169.   * @Name    DisplayRefreash
  170.   * @brief   刷新当前菜单页的所有菜单项
  171.   * @param   nowMenu: 当前菜单指针
  172. **                         selectItem: 当前菜单在当前菜单页的索引,指小光标在第几行
  173. **           scrollBar:滚动条所在位置
  174.   * @retval  void
  175.   * @author  LQH
  176.   * @Data    2022-01-27
  177.   */
  178. void DisplayRefreash(struct Menu_t *nowMenu,u8 selectItem,u8 scrollBar)
  179. {
  180.         int i = 0;
  181.         static u8 lastSelectItem=0;//记录上次索引
  182.         if(nowMenu==&MainUI)//当回到主菜单时,由于没有全占屏,所以全部清屏,再画
  183.         {
  184.                 OLED_Clear();
  185.                 MainUiSet();
  186.         }else
  187.         {        
  188.                 OLED_ShowChar(0,lastSelectItem*16, ' ',16,1);//清除上次索引
  189.                 OLED_ShowChar(0,selectItem*16,     '>',16,1);//画出这次索引
  190.                 for(i=0;i<(nowMenu->MenuProperty->MenuLen-nowMenu->MenuProperty->scrollBarLen);i++)
  191.                 {
  192.                         OLED_ShowString(8,i*16,nowMenu[i+scrollBar].displayString,16,1);
  193.                 }
  194.         }
  195.         OLED_Refresh();
  196.         lastSelectItem = selectItem;
  197. }
  198. /**
  199.   * @Name    DisplayRefreashDate
  200.   * @brief   刷新当前菜单页的所有菜单项,主要拿来更新数据
  201.   * @param   nowMenu:    当前菜单指针
  202. **                         selectItem: 当前菜单在当前菜单页的索引,指小光标在第几行
  203. **           scrollBar: 滚动条所在位置
  204.   * @retval  void
  205.   * @author  LQH
  206.   * @Data    2022-01-27
  207.   */
  208. void DisplayRefreashData(struct Menu_t *nowMenu,u8 selectItem,u8 scrollBar)
  209. {
  210.         int i = 0;
  211.         for(i=0;i<(nowMenu->MenuProperty->MenuLen-nowMenu->MenuProperty->scrollBarLen);i++)
  212.         {
  213.                 OLED_ShowString(8,i*16,nowMenu[i+scrollBar].displayString,16,1);
  214.         }
  215.         OLED_Refresh();
  216. }

  217. /**
  218.   * @name    GuiInit
  219.   * @brief   一些菜单初始化主要是主菜单页的子菜单确定,由于父菜单结构体初始化时不能初始化子菜单
  220.   *                  所以在这里初始化
  221.   * @param   :
  222.   * @retval  void
  223.   * @author  LQH
  224.   * @date    2022-01-27
  225.   */
  226. void GuiInit()
  227. {
  228.         MainUI.childrenMenu = menuMain;
  229.         menuMain[1].childrenMenu = setMenu1;
  230.         menuMain[2].childrenMenu = setMenu2;
  231.         menuMain[3].childrenMenu = setMenu3;
  232.         menuPoint = &MainUI;
  233.         DisplayRefreash(menuPoint,selectItem,scrollBar);
  234. }
  235. /**
  236.   * @name    GuiDataDisplayRefresh
  237.   * @brief   菜单页的数据更新,记得一定要字符串占满15个字符
  238.   * @param   :
  239.   * @retval  void
  240.   * @author  LQH
  241.   * @date    2022-01-27
  242.   */
  243. void GuiDataDisplayRefresh()
  244. {
  245.         if(menuPoint == setMenu1)
  246.         {
  247.                 sprintf((char*)setMenu1[1].displayString,"bull  %3d     ",count1);
  248.                 sprintf((char*)setMenu1[2].displayString,"bird  %3d     ",count2);
  249.                 sprintf((char*)setMenu1[3].displayString,"dog   %3d     ",count3);
  250.                 sprintf((char*)setMenu1[4].displayString,"bow   %3d     ",count4);
  251.                 sprintf((char*)setMenu1[5].displayString,"fish  %3d     ",count5);
  252.                 DisplayRefreashData(menuPoint,selectItem,scrollBar);
  253.         }
  254.         else if(menuPoint==setMenu2)
  255.         {
  256.                 sprintf((char*)setMenu2[1].displayString,"KP   %3d      ",kp);
  257.                 sprintf((char*)setMenu2[2].displayString,"KI   %3d      ",ki);
  258.                 sprintf((char*)setMenu2[3].displayString,"KD   %3d      ",kd);
  259.                 sprintf((char*)setMenu2[4].displayString,"PWM  %3d      ",0);
  260.                 DisplayRefreashData(menuPoint,selectItem,scrollBar);
  261.         }
  262.         else if(menuPoint==setMenu3)
  263.         {
  264.                 sprintf((char*)setMenu3[1].displayString,"Hour   %2d    ",myTimeTemp.Hour);        
  265.                 sprintf((char*)setMenu3[2].displayString,"Minute %2d    ",myTimeTemp.Minute);        
  266.                 sprintf((char*)setMenu3[3].displayString,"Second %2d    ",myTimeTemp.Second);        
  267.                 sprintf((char*)setMenu3[4].displayString,"Year   %4d    ",myTimeTemp.Year);
  268.                 sprintf((char*)setMenu3[5].displayString,"Month  %2d    ",myTimeTemp.Month);
  269.                 sprintf((char*)setMenu3[6].displayString,"Day    %2d    ",myTimeTemp.Day);
  270.                 DisplayRefreashData(menuPoint,selectItem,scrollBar);
  271.         }
  272.         else if(menuPoint==&MainUI)
  273.         {
  274.                 MainUiSet();
  275.                 OLED_Refresh();
  276.         }
  277. }
  278. /**
  279.   * @Name    GuiControl
  280.   * @brief   按键控制,按键控制的确定变量在keyscan.c中,按键扫描实现又是放在定时器里面的
  281.   * @param   : [输入/出]
  282.   * @retval  void
  283.   * @author  LQH
  284.   * @Data    2022-01-27
  285.   */
  286. void GuiControl()
  287. {
  288.         if(isKeyUp==1)//上键按下
  289.         {
  290.                 isKeyUp=0;//标志位清零
  291.                 selectItem--;//当前菜单在当前菜单页的索引--
  292.                 if(selectItem<0&&scrollBar!=0)//小于0,但是滚动条不在0,就减滚动条
  293.                 {
  294.                         selectItem = 0;
  295.                         scrollBar--;
  296.                 }else if(selectItem<0&&scrollBar==0)//小于0,滚动条也在0,就将索引移到最后,滚动条到最大
  297.                 {
  298.                         selectItem = menuPoint->MenuProperty->MenuLen-1-menuPoint->MenuProperty->scrollBarLen;
  299.                         scrollBar  = menuPoint->MenuProperty->scrollBarLen;
  300.                 }
  301.                 DisplayRefreash(menuPoint,selectItem,scrollBar);//刷新显示
  302.         }else if(isKeyDown==1)//和上键差不多
  303.         {
  304.                 isKeyDown=0;
  305.                 selectItem++;
  306.                 //假如索引大于最大值,但是滚动条不在最大值,保持索引最大值,滚动条++
  307.                 if(selectItem>(menuPoint->MenuProperty->MenuLen-1-menuPoint->MenuProperty->scrollBarLen)&&scrollBar!=menuPoint->MenuProperty->scrollBarLen)
  308.                 {
  309.                         selectItem = menuPoint->MenuProperty->MenuLen-1-menuPoint->MenuProperty->scrollBarLen;
  310.                         scrollBar++;
  311.                         
  312.                 }
  313.                 //假如索引大于最大值,滚动条在最大值,移动到第一个位置
  314.                 else if(selectItem>(menuPoint->MenuProperty->MenuLen-1-menuPoint->MenuProperty->scrollBarLen)&&scrollBar==menuPoint->MenuProperty->scrollBarLen)
  315.                 {
  316.                         selectItem=0;
  317.                         scrollBar =0;
  318.                 }
  319.                 DisplayRefreash(menuPoint,selectItem,scrollBar);
  320.         }else if(isKeyLeft==1)
  321.         {
  322.                 //假如当前菜单的func1不为空,执行相关函数
  323.                 if(menuPoint[selectItem+scrollBar].func1!=NULL)
  324.                 {
  325.                         menuPoint[selectItem+scrollBar].func1();
  326.                 }
  327.                 isKeyLeft=0;
  328.                 DisplayRefreash(menuPoint,selectItem,scrollBar);
  329.         }else if(isKeyRight==1)
  330.         {
  331.                 if(selectItem==0 && scrollBar==0 && menuPoint[selectItem].fatherMenu!=NULL)//假如索引为零而且父菜单不为空,指向父指针
  332.                 {
  333.                         menuPoint = menuPoint[selectItem].fatherMenu;
  334.                 }
  335.                 else if(menuPoint[selectItem+scrollBar].childrenMenu!=NULL)//假如该索引子菜单页不为空,指向子菜单
  336.                 {
  337.                         if(menuPoint[selectItem+scrollBar].func2!=NULL)//假如当前菜单的func2不为空,执行相关函数
  338.                         {
  339.                                 menuPoint[selectItem+scrollBar].func2();
  340.                         }
  341.                         menuPoint = menuPoint[selectItem+scrollBar].childrenMenu;
  342.                         selectItem = 0;
  343.                 }
  344.                 else if(menuPoint[selectItem+scrollBar].func2!=NULL)//假如当前菜单的func2不为空,执行相关函数
  345.                 {
  346.                         menuPoint[selectItem+scrollBar].func2();
  347.                 }
  348.                 isKeyRight=0;
  349.                 DisplayRefreash(menuPoint,selectItem,scrollBar);
  350.         }else if(isKeyOk==1)
  351.         {
  352.                 isKeyOk=0;
  353.                 DisplayRefreash(menuPoint,selectItem,scrollBar);
  354.         }
  355.         GuiDataDisplayRefresh();
  356. }
复制代码

Keil代码下载:
代码.7z (218.14 KB, 下载次数: 121)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:286761 发表于 2022-9-7 16:35 | 显示全部楼层
太好了,最近在搞这个。刚好可以参考一下。。。。谢谢楼主分享
回复

使用道具 举报

ID:286761 发表于 2022-9-7 16:36 | 显示全部楼层
太好了,刚好最近在研究这方面的东西。谢谢楼主分享.....
回复

使用道具 举报

ID:656801 发表于 2022-9-14 23:26 | 显示全部楼层
好资料  可以用上了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表