STM32多级界面搭建

在实际的项目之中,需要用单片机在LCD/OLED中搭建一个3级的图形界面。本文的工程文件我将上次传到百度网盘,链接在最后的部分。

  • STM32多级界面搭建
    • 一、方案选择
    • 二、实现效果
    • 三、程序设计
      • 3-1宏定义变量设计
      • 3-2控制函数设计
      • 3-3主函数调用设计
    • 四、总结

一、方案选择

方案一:使用if条件语句写一个界面,但是这种方法在两级界面的时候还可以,在多级界面的时候代码的逻辑上的复杂度会大幅增加,不太使用。

方案二:使用嵌入式图形库lvgl等,但是这个对新手不太友好。

方案三:使用结构体变量存储界面信息,可以是使得多级界面也可以逻辑清晰。

二、实现效果

主界面:
菜单界面:

功能界面:

三、程序设计

3-1宏定义变量设计

·界面标志位
在头文件中首先需要定义一个结构体来存放界面标志位,包括现在界面的状态,当前运行的任务状态,以及当前任务是否处于运行状态。

·界面变量
创建三个枚举变量,Main_Interface,Menu_Interface,Task_Interface,来表示目前界面所在的位置,是主界面还是菜单界面还是任务界面。

·任务变量
创建n个任务,每个任务提供一个代号,方便识别。

#ifndef __GUI_H__
#define __GUI_H__
/********************************************** 创建一个结构体* 存放界面标志位
*********************************************/
typedef struct
{uint8_t Interface_Mark;     //界面状态uint8_t Task_Mark;          //任务状态uint8_t Run_Task;           //开始运行任务
} Mark;/********************************************** 创建一个枚举* 存放界面变量
*********************************************/
enum
{Main_Interface, /****主界面*****/Menu_Interface, /****菜单界面***/Task_Interface, /****任务界面***/
};
/********************************************** 创建一个枚举* 存放功能变量
*********************************************/
enum
{F_ONE,F_TWO,F_THREE,F_FOUR,    Stopping,       /****任务停止***/
};extern  Mark Mark_Sign;void Interface_APP(Mark *Mark_Sign);
void Interface(Mark *Mark_Sign,uint8_t keys);
void GUI_init(void);#endif

3-2控制函数设计

主函数调用
使用定义的结构体来显示界面,即显示初始界面。

显示界面函数
主函数调用,根据Mark_Sign->Interface_Mar变量来确实显示当前所在的界面。

功能切换函数:主函数调用,通过扫描按键,当按下对应按键时,执行相应的函数,如确认进入函数,返回退出函数,功能切换函数。

/***************
//初始化,显示主界面
***************/
void GUI_init(void)
{   Interface_APP(&Mark_Sign);
}
/***************
//mian函数中显示,主循环中调用,用于显示界面
***************/
void Interface_APP(Mark *Mark_Sign)
{switch (Mark_Sign->Interface_Mark){//状态标志位 主界面case Main_Interface:Main_Interface_APP();//显示主界面break;//状态标志位 菜单界面case Menu_Interface:Menu_Interface_APP();//显示菜单界面break;//状态标志位 任务界面case Task_Interface:Function_Menu_APP(Mark_Sign);//显示功能界面break;default:break;}
}
/***************
//mian函数中显示,主循环中调用,按键扫描,当按下对应按键时,执行相应的函数
***************/
void Interface(Mark *Mark_Sign,uint8_t keys)
{/* 1,检测当前按下的按键为确认键* 2,检测当前的界面*    (1)如果是主界面,则进入菜单界面*    (2)如果是菜单界面,则进入任务界面*     (3)如果是任务界面,则开执行被选中的任务*/   if(keys == KEY1_PRES){key_Inter(Mark_Sign);}/*1,检测当前按下的按键为返回键* 2,检测当前的界面* (1)如果是任务界面,则停止正在运行的任务,返回到菜单界面* (2)如果是菜单界面,则返回到主界面*/if(keys == KEY2_PRES){key_Cancel(Mark_Sign);}
/*1,检测当前按下的按键为任务切换* (1)在菜单界面,选择切换接下来要运行的任务*/if(keys == KEY3_PRES){key_Up_move(Mark_Sign);}if(keys == KEY4_PRES){key_Down_move(Mark_Sign);}
}

不同界面的显示函数: 主界面,菜单界面,功能界面

static unsigned char Lcd_Disp_String[21];
/***************
//显示主界面
***************/
void Main_Interface_APP(void)
{LCD_DisplayStringLine(Line1 ,(unsigned char *)"Main_Interface_APP");LCD_DisplayStringLine(Line2 ,(unsigned char *)"ADC-LED-REF");
}/***************
显示菜单界面
***************/
void Menu_Interface_APP(void)
{LCD_DisplayStringLine(Line1 ,(unsigned char *)"Menu_Interface_APP");
}/***************
显示功能界面
***************/
void Function_Menu_APP(Mark *Mark_Sign)
{LCD_DisplayStringLine(Line1 ,(unsigned char *)"Function_Menu_APP  ");if(Mark_Sign->Task_Mark == F_ONE ){LCD_DisplayStringLine(Line2 ,(unsigned char *)"ADC         ");sprintf((char*)Lcd_Disp_String, "  RES38_vol: %6.3f  ",getADC1()*(3.3/4096)); //3.3为总的电压值 2的12次方等于4096 用于对电压值分成一份LCD_DisplayStringLine(Line4, Lcd_Disp_String);}
}

按键控制函数: 确认 返回 切换 其中keys_number用于切换功能时候,选择对应功能的时候记录用,因为up和down函数在切换的时候,需要作出循环的效果,既可以到了上限F_FOUR之后就,继续向上时,重新回到F_ONE, 也可以在到了下限F_ONE之后就,继续向下时,重新回到F_FOUR。

uint8_t keys_number;
/****************  1,检测当前按下的按键为确认键*  2,检测当前的界面*     (1)如果是主界面,则进入菜单界面*     (2)如果是菜单界面,则进入任务界面*     (3)如果是任务界面,则开执行被选中的任务
***************/
void key_Inter(Mark *Mark_Sign)
{//当按下菜单键时,判断当前界面/************判断当前界面为主界面***********************/if(Main_Interface == Mark_Sign->Interface_Mark){/**************进入菜单界面*************/Mark_Sign->Interface_Mark = Menu_Interface;Mark_Sign->Task_Mark = F_ONE;keys_number = 0;}/************判断当前界面为菜单界面*******************/else if(Menu_Interface == Mark_Sign->Interface_Mark){/***************进入任务界面************/Mark_Sign->Interface_Mark = Task_Interface;/**************进入指定的功能任务*******/switch(Mark_Sign->Task_Mark){//Task_Mark;          //任务状态//Run_Task;           //开始运行任务/**************开始运行time任务*******/case F_ONE:Mark_Sign->Run_Task = F_ONE;break;/**************开始运行蓝牙任务*******/case F_TWO:Mark_Sign->Run_Task = F_TWO;break;/**************开始运行F_THREE任务*******/case F_THREE:Mark_Sign->Run_Task = F_THREE;break;/**************开始运行设置任务*******/case F_FOUR:Mark_Sign->Run_Task = F_FOUR;break;default:break;}}/************判断当前界面为任务界面******************/else if(Task_Interface == Mark_Sign->Interface_Mark){/*******判断当前正在运行的任务*******/switch(Mark_Sign->Run_Task){//Task_Mark;          //任务状态//Run_Task;           //开始运行任务/**************开始运行time任务*******/case F_ONE:break;/**************开始运行蓝牙任务*******/case F_TWO:break;/**************开始运行F_THREE任务*******/case F_THREE:break;/**************开始运行设置任务*******/case F_FOUR:break;default:break;}}
}
/*显示推出的时候箭头和向上移动的时候的箭头*/
void Menu_cancel(uint8_t keys_number,Mark *Mark_Sign);
void Menu_input(uint8_t keys_number,Mark *Mark_Sign);
/***************
//返回键,可以返回上一界面,如果在菜单界面
返回的时候指针在指向上次的位置* 1,检测当前按下的按键为返回键* 2,检测当前的界面*    (1)如果是任务界面,则停止正在运行的任务,返回到菜单界面*    (2)如果是菜单界面,则返回到主界面
***************/
void key_Cancel(Mark *Mark_Sign)
{//当按下返回键时,判断当前界面/************判断当前界面为菜单界面*******************/if(Menu_Interface == Mark_Sign->Interface_Mark){/*******退出菜单界面***进入主界面**/Mark_Sign->Interface_Mark = Main_Interface;}/************判断当前界面为任务界面******************/else if(Task_Interface == Mark_Sign->Interface_Mark){/***退出正在运行的任务***/
//            Mark_Sign->Run_Task = Stop;/*******退出任务界面*****/Mark_Sign->Interface_Mark = Menu_Interface;Mark_Sign->Run_Task = Stopping;Menu_cancel(keys_number,Mark_Sign);}
}
/***************
//菜单界面,可以上下选择进入那些功能之中
、、任务界面中
time功能中,可以上下更改对应的时间与日期的值
***************/
void key_Up_move(Mark *Mark_Sign)
{if(Mark_Sign->Interface_Mark==Menu_Interface){if(keys_number==0) keys_number = 4;keys_number--;Menu_cancel(keys_number,Mark_Sign);}else if(Mark_Sign->Run_Task == F_ONE){}
}/***************
//菜单界面,可以上下选择进入那些功能之中
//任务界面中
//time功能中,可以上下更改对应的时间与日期的值
***************/
void key_Down_move(Mark *Mark_Sign)
{if(Mark_Sign->Interface_Mark==Menu_Interface){if(keys_number==4) keys_number=0;keys_number++;Menu_input(keys_number,Mark_Sign);}else if(Mark_Sign->Run_Task == F_ONE){}
}

切换时的效果: 不管是LCD 还是OLED在切换界面的时候,如果不及时清理的话,都会保留上一次的印记,因此在任务变更,界面改变的时候都要及时清理。

==而且可以在任务界面的时候可以写一个光标来表示,即将运行的任务是什么。==这样便于观看。

/*显示推出的时候箭头和向上移动的时候的箭头*/
void Menu_cancel(uint8_t keys_number,Mark *Mark_Sign)
{if(keys_number==3){Mark_Sign->Task_Mark = F_FOUR;LCD_DisplayStringLine(Line2 ,(unsigned char *)"TEST       ");}else if(keys_number==2){Mark_Sign->Task_Mark = F_THREE;LCD_DisplayStringLine(Line2 ,(unsigned char *)"FRE        ");}else if(keys_number==1){Mark_Sign->Task_Mark = F_TWO;LCD_DisplayStringLine(Line2 ,(unsigned char *)"LED        ");}else if(keys_number<=0){Mark_Sign->Task_Mark = F_ONE;LCD_DisplayStringLine(Line2 ,(unsigned char *)"ADC        ");keys_number=0;}
}/*前进移动的时候的箭头*/
void Menu_input(uint8_t keys_number,Mark *Mark_Sign)
{if(keys_number==1){Mark_Sign->Task_Mark = F_TWO;LCD_DisplayStringLine(Line2 ,(unsigned char *)"LED        ");}else if(keys_number==2){Mark_Sign->Task_Mark = F_THREE;LCD_DisplayStringLine(Line2 ,(unsigned char *)"FRE        ");}else if(keys_number==3){Mark_Sign->Task_Mark = F_FOUR;LCD_DisplayStringLine(Line2 ,(unsigned char *)"AAA        ");}else if(keys_number>=4){Mark_Sign->Task_Mark = F_ONE; LCD_DisplayStringLine(Line2 ,(unsigned char *)"ADC        ");}
}

3-3主函数调用设计

主函数调用:
在主函数先定义一个结构体Mark Mark_Sign = {Main_Interface,0,0};来表示初始界面为主界面。之后调用gui_init函数来显示初始界面。

在while循环中不断读取按键值和显示界面函数来实现显示界面的动态更新。

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "usart.h"
#include "gpio.h"
#include "lcd.h"
#include "stdio.h"
#include "gui.h"/* Private define ------------------------------------------------------------*/
Mark Mark_Sign = {Main_Interface,0,0};/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
unsigned char Lcd_Disp_String[21];
/*** @brief  The application entry point.* @retval int*/
int main(void)
{/* Configure the system clock */HAL_Init();SystemClock_Config();/* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();MX_ADC1_Init();MX_ADC2_Init();/* USER CODE BEGIN 2 */LCD_Init();LCD_Clear(White);LCD_SetBackColor(White);LCD_SetTextColor(Black);LCD_Clear(White);LCD_DisplayStringLine(Line1 ,(unsigned char *)"   hello dma.   ");GUI_init();//* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){Interface_APP(&Mark_Sign);Interface(&Mark_Sign, KEY_Scan(0));/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

四、总结

这是一个用结构体写的一个基础多级界面的框架,如果你使用的界面大于或是小时3级的话,这时候就需要对结构的中的界面枚举变量进行更改。根据整个设计你所喜欢的界面叭。总体来说来时不错的

本文的工程文件我将上次传到百度网盘。链接: https://pan.baidu.com/s/1QNpKRsyHVr-UyCGsyvkLBw .
提取码:vsh2

此文本工程参考了链接: 基于STM32之OLED菜单界面框架搭建,特此感谢。

【STM32多级界面】-LCD结构体多级图形界面框架相关推荐

  1. C++结构体多级排序的三种方法

    C++结构体多级排序的三种方法 struct node{int chinese,math;char name[15]; }; 需求:按数学成绩从大到小排序  1.自定义比较器 //自定义比较函数 bo ...

  2. 虚拟机里切换linux图形界面,虚拟机-linux系统中图形界面和命令行界面切换

    linux系统中图形化界面和命令行界面之间的切换可以分为两种,临时性切换和永久性切换. 临时性切换即切换后只对本次生效,系统重启后界面还是默认界面. 永久性切换即切换后系统开机后永远处于的界面. 临时 ...

  3. C语言运行界面字体,C语言实现图形界面登陆窗口.docx

    纯C语言实现图形界面登陆窗口 一下是界面图: 编程工具是:VC6.0 请根据个人需要对源代码进行修改使用,图片放在工程文件夹中.新建时应该将文件后缀设置为.cpp 以下是程序灯源代码: #includ ...

  4. ssh开启图形界面_xwindow——远程启动linux的图形界面

    如果直接在linux命令行中,运行将会弹出图形界面的命令,是不能成功的.为了达到这种成功.我们需要使用一种方式来远程监控linux的图形界面. 原理: X11也叫做X window系统,是一种位图显示 ...

  5. ubuntu返回图形界面_Ubuntu设置命令行界面和图形界面切换方法

    代码: 复制代码 代码如下: sudo gedit /etc/default/grub 引用: 复制代码 代码如下: GRUB_CMDLINE_LINUX="text" 代码: 复 ...

  6. java图形界面制作表格,Java自学-图形界面 表格

    Swing 使用 JTable详解 示例 1 : 基本表格 显示一个Table需要两组数据 一维数组: String[]columnNames 表示表格的标题 二维数组: String[][] her ...

  7. linux 图形界面无法进入,无法进入图形界面的解决过程

    首先说明,我是一个新手,所有有些地方可能很菜,有不对的地方还请大虾教导. 我安装的是Red Hat Linux 9(另一个系统是Windows Xp),安装时候无法进入图形界面,提示"注意: ...

  8. 怎么开发Linux图形界面程序,Linux下的图形界面编程

    Linux下的图形界面编程 一.Qt和GTK+ 虽然Linux下的大多数开发是基于字符界面的,但在Linux环境下也可以开发出美观大方的图形界面.经过多年的发展,目前已经存在多种用于在Linux下开发 ...

  9. gui界面设计心得体会 python_Python图形界面GUI程序设计

    1.GUI是什么? 图形用户界面(Graphical User Interface,简称 GUI,又称图形用户接口)是指采用图形方式显示的计算机操作用户界面. 图形用户界面是一种人与计算机通信的界面显 ...

最新文章

  1. html中base标签的使用,和简介
  2. emoji表情 与 iconfont 一锅炖
  3. java mongodb排序查询_java操作mongodb基础(查询 排序 输出list)
  4. Qt 遍历目录并删除目录下所有文件
  5. 浅谈Java多线程同步机制之同步块(方法)——synchronized
  6. Boolean占几个字节
  7. redis 使用案例
  8. python手册中文版-Python中文文档
  9. Jdk8下载安装配置教程
  10. 手工清除U盘里的恶意病毒
  11. 魏俊妮《如何成为支持业务的HR》课程大纲
  12. tiktok英国小店注册流程介绍
  13. ISV 和SI 是什么
  14. Essential singularity
  15. MYSQL_ASSOC
  16. 阿里云服务器白嫖和购买教程——学生向
  17. php中::双冒号作用
  18. 以Base64字符串形式上传文件——服务器端Java/Servlet接受请求数据中的字符串内容并转换成文件
  19. Android 来电监听
  20. java开源自定义表单_java开发自定义表单功能类:FormUtil

热门文章

  1. idea_设置项目编码
  2. 学习笔记---ih5_九宫格_拼图
  3. 动态路由 华三nat 静态路由_史上最详细H3C路由器NAT典型配置案例
  4. SiT3373:220 -725MHz 低抖动压控差分振荡器VCXO
  5. 基于Qt5图形视图框架的“俄罗斯方块”
  6. 某微型计算机指令格式如图,计算机组成原理期末复习试题2套不含答案
  7. 未找到导入的项目“C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\VC\VCT
  8. GPS与compass对比
  9. 南大软院大神养成计划--CSS网页布局
  10. 互联网公司的中台到底是什么