栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

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);	
}

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;
	}
}

void Interface(Mark *Mark_Sign,uint8_t keys)
{
   
    if(keys == KEY1_PRES)
    {
		key_Inter(Mark_Sign);
    }
	

	
    if(keys == KEY2_PRES)
    {
		key_Cancel(Mark_Sign);
    }

	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;

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;           //开始运行任务

            
            case F_ONE:
                Mark_Sign->Run_Task = F_ONE;
				
                break;
            
            case F_TWO:
                Mark_Sign->Run_Task = F_TWO;

                break;
            
            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;           //开始运行任务

            
            case F_ONE:
				
                break;
            
            case F_TWO:
            
                break;
            
            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);

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);
        }
}

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)
	{
		
	}
}



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循环中不断读取按键值和显示界面函数来实现显示界面的动态更新。

#include "main.h"
#include "adc.h"
#include "usart.h"
#include "gpio.h"
#include "lcd.h"
#include "stdio.h"
#include "gui.h"


Mark Mark_Sign = {Main_Interface,0,0};


void SystemClock_Config(void);
unsigned char Lcd_Disp_String[21];

int main(void)
{
  
  HAL_Init();
  SystemClock_Config();
  
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_ADC1_Init();
  MX_ADC2_Init();
  
	LCD_Init();
	LCD_Clear(White);
	LCD_SetBackColor(White);
	LCD_SetTextColor(Black);
	LCD_Clear(White);
	LCD_DisplayStringLine(Line1 ,(unsigned char *)"   hello	dma.   ");
	
	GUI_init();/

  
  
  
  while (1)
  {
	Interface_APP(&Mark_Sign);
	Interface(&Mark_Sign, KEY_Scan(0));
    
    
  }
  
}
四、总结

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

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

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/873305.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号