分享一个STM32菜单框架

发布者:快乐家庭最新更新时间:2024-02-18 来源: elecfans关键字:STM32  液晶显示 手机看文章 扫描二维码
随时随地手机看文章

相信很多攻城狮都用过液晶屏,想写好一点的ui好像不太可能或且花费很多时间,直接写吧,感觉好像很零碎,coding都怕了。

下面介绍一个简单易用的菜单框架,你会发现它能做多层菜单而且结果清晰。

基本原理:99d1faae-fee3-11ed-90ce-dac502259ad0.png    

如上图液晶显示一屏我们定义为一个page,page中的项目定义为item;这样page就是item的容器了。当我们选中其中的一个item进去后是不是又是一个page呢,如下图。99d898dc-fee3-11ed-90ce-dac502259ad0.png    

这样的话每一个item的下面都对应一个page,这样是不是就构成一个多层的菜单了。

99e4b180-fee3-11ed-90ce-dac502259ad0.png      

他们是什么关系呢?

一个page中有item,那么用结构体就可以实现啦;item下面又有page,那么在item中加一个page的指针指向item对应的page页。

前面都是从上到下的,那么怎么返回呢?

观察发现返回就是子page返回父page,这样在page结构体中假如一项父page的指针不就ok了。


具体实现请看源文件。


/******************************************************************************************************/

//主菜单

//定义Item项             //显示方式&序号  项目的名字    项目指向的页(Page)

const struct Item main_item[]={ 0x00, "信息",   &SMS_Page,

        0x01, "设置",   &Setting_Page,

        0x02, "版本",   &Version_Page,

        0x03, "时间",   &Time_Page,

        0x04, "状态",   0,

        0x05, "报警",   0,

        0x06, "飞信",   0,

        0x07, "问答",   0

};

//定义一个Page        父页 该页的回调函数 该页的项          项的个数    

const struct PAGE mainPage={0,mainPageCallBack,main_item,sizeof(main_item)/sizeof(struct Item)};

/*********************************************************************************************************/





const struct PAGE Version_Page={&mainPage,Version_CallBack,0,0};

/***************************************************************************************************************/



//定义Item项              //显示方式&序号    项目的名字      项目指向的页(Page)

const struct Item Setting_item[]={ 0x10, " 00.设0",   0,

         0x11, " 01.设1",   0,

         0x12, " 02.设2",   0,

         0x13, " 03.设3",   0,

         0x14, " 04.设4",   0,

         0x15, " 05.设5",   0,

         0x16, " 06.设6 你好",  0,

         0x17, " 07.设7",   0,

         0x18, " 08.设8",   0,

         0x19, " 09.设9",   0,

         0x1A, " 10.设10",   0

         };

const struct PAGE Setting_Page={&mainPage,Setting_CallBack,Setting_item,sizeof(Setting_item)/sizeof(struct Item)};

/***************************************************************************************************************/



const struct PAGE Time_Page={&mainPage,Time_CallBack,0,0};



/***************************************************************************************************************/

//定义Item项              //显示方式&序号    项目的名字      项目指向的页(Page)

const struct Item SMS_item[]={ 

         0x10, " 00.",   &SMS_Text_Page,

         0x11, " 01.",   &SMS_Text_Page,

         0x12, " 02.",   &SMS_Text_Page,

         0x13, " 03.",   &SMS_Text_Page,

         0x14, " 04.",   &SMS_Text_Page,

         0x15, " 05.",   &SMS_Text_Page,

         0x16, " 06.",   &SMS_Text_Page,

         0x17, " 07.",   &SMS_Text_Page,

         0x18, " 08.",   &SMS_Text_Page,

         0x19, " 09.",   &SMS_Text_Page,

         0x1A, " 10.",   &SMS_Text_Page

         };



const struct PAGE SMS_Page={&mainPage,SMS_CallBack,SMS_item,sizeof(Setting_item)/sizeof(struct Item)};





Menu.h:


#ifndef _Menu_H_BAB

#define _Menu_H_BAB



#include "stm32f10x.h"

#include "LCD.h"

#include "Key.h"



#define KEY_Special  255 ///<这个保留用于特别事件



//菜单调试,在调试时最好定义,可以帮助发现问题;当发布时把其置为0可以加快速度

#define MENU_DEBUG 1



void Menu_Show(void);



struct PAGE

{

 const struct PAGE *pParent;

 void (*Function)(u8 key);

 const struct Item *pItem;

 const u8 ItemNum;

};

struct Item

{

 /**

 高4位作为特殊用途(bit4=1表示列表显示否则两列显示),低4位用于标记Item的序号  


 如果为列表模式时*pText的格式为:" xx.string",最前面保留一个空格用于个光标(>)使用,xx.为两位序号不要"."一定要有,string是要显示的文字,最多能显示6个汉字  


 如果是两列显示则pText,即为要显示的文本(最多2个汉字)

 */

 const u8 TypeAndIndex; 

 const u8 *pText;

 const struct PAGE *pChildrenPage;

};



extern const struct PAGE *pPage;



void SetMainPage(const struct PAGE *pMainPage);

void ShowMenu(const struct PAGE *pPage);

void ShowPage(const struct PAGE *pPage);

void ShowParentPage(void);

void ShowItemPage(void);

void SelPageItem(u8 ItemIndex);

u8 Menu_GetSelItem(void);



void GetShowLst(u8 *pOutMin,u8 *pOutMax);



void KeySelItem(u8 key);



#endif 

Menu.c:


#include "Menu.h"



//保存选中的菜单项变量

static u8 SelItem=0;



/**

用于当前LCD列表中显示着哪几项

高4位:最大序号

低4为:最小序号

*/

static u8 ListShow=0x00;



const struct PAGE *pPage;



void SelItemOfList(u8 index);



void SetMainPage(const struct PAGE *pMainPage)

{

 pPage=pMainPage;

}

/**

获得当前选中的菜单项

@return 返回菜单序号

*/

u8 Menu_GetSelItem(void)

{

 return SelItem;

}



/**

获取当前显示列表的范围

@param pOutMin 当前显示的最小序号

@param pOutMax 当前显示的最大序号

*/

void GetShowLst(u8 *pOutMin,u8 *pOutMax)

{

 *pOutMin=ListShow&0x0f; 

 *pOutMax=ListShow>>4;

}

void ShowList(u8 min,u8 max)

{

 u8 i=0,index=0;

 #if MENU_DEBUG

  if(max-min>3)

  {

   Lcd_Clr_Scr();

   LCD_Write_Str(0,0,"err:ShowList>3");

   while (1);

  }

  

  if ((pPage->pItem[0].TypeAndIndex & 0x10)==0)///<如果是使用列表方式

  {

   

    Lcd_Clr_Scr();

    LCD_Write_Str(0,0,"不是列表类型不能不能列出");

    while (1); 

  }

 #endif

 

 Lcd_Clr_Scr();

 for (index=min;index<=max;index++)

 {



  LCD_Write_Str(i++,0,pPage->pItem[index].pText);

 }

 ListShow=(max<<4)|min; ///<记录当前显示的Item

 

}

/**

页显示



1.当这个页有项目(Item)时:显示Item并同时选中Item 0   


2.没有时:会调用该Page的回调函数并传入KEY_Special 参数 


@param pPage 指向一个page

*/

void ShowPage( const struct PAGE *pPage)

{

 s8 i;

 ///清屏

 Lcd_Clr_Scr();

   

 if(pPage->pItem==0) 

 {

  pPage->Function(KEY_Special);

  return; ///<如果没有Item项则不显示Item,直接返回

 }

  

 if (pPage->pItem[0].TypeAndIndex & 0x10)///<如果是使用列表方式

 {

  ShowList(0,3);

  SelItemOfList(0);

  pPage->Function(KEY_Special);

 }

 else

 { 

  ///取出page中的Item并显示

  for (i=0;iItemNum;i++)

  {

   if (i<4)

   {

    LCD_Write_Str(i,1,pPage->pItem[i].pText);

   }

   else

   {

    LCD_Write_Str(i-4,5,pPage->pItem[i].pText);

   }

   

  }

  SelPageItem(0);///<选中Item 0

  pPage->Function(KEY_Special);

 }

 

};



/**

显示父页(ParentPage)

*/

void ShowParentPage(void)

{

 pPage=pPage->pParent;

 ShowPage(pPage);

}



/**

显示项目(Item)下对应的页(Page)

*/

void ShowItemPage(void)

{

 //如果该项下没有页,这警告或返回

 if (pPage->pItem[Menu_GetSelItem()].pChildrenPage ==0)

 {

  #if MENU_DEBUG

   Lcd_Clr_Scr();

   LCD_Write_Str(0,0,"该项下无显示请修正");

   while (1);

  #else

   return;

  #endif 

 }

 pPage=pPage->pItem[Menu_GetSelItem()].pChildrenPage; //获得菜单项(Item)对应的page



 ShowPage(pPage);

}



/**

选择page中的Item项

@param ItemIndex page中Item的索引号 0~7

*/

void SelPageItem(u8 ItemIndex)

{

 ///检查是否有错误调用

#if MENU_DEBUG



 if (ItemIndex>=8)

 {

  LCD_Write_Str(0,0,"设置菜单项溢出");

  return;

 }

#endif



///清除上次选中的

   if (SelItem<4)

   {

  LCD_Write_Str(SelItem,0,"  ");

  LCD_Write_Str(SelItem,3,"  ");

 

   }

   else

   {

  LCD_Write_Str(SelItem-4,4,"  ");

  LCD_Write_Str(SelItem-4,7,"  ");

   }

///选中这次要选中的  

   if (ItemIndex<4)

   {

  LCD_Write_Str(ItemIndex,0,"【");

  LCD_Write_Str(ItemIndex,3,"】");

  SelItem=ItemIndex;

   }

   else

   {

  LCD_Write_Str(ItemIndex-4,4,"【");

  LCD_Write_Str(ItemIndex-4,7,"】");

  SelItem=ItemIndex;

   } 

};

void SelItemOfList(u8 index)

{

 u8 max;

 u8 min;

 

 max=ListShow>>4;

 min=ListShow&0x0f;

 

 if (index>max) ///<超出最大当前显示的序号

 {

  

  LCD_Write_Str(Menu_GetSelItem()-min,0," ");

  

  min+=1;

  max+=1;

  ShowList(min,max);

  ListShow=(max<<4)|min;

  

  LCD_Write_Str(index-min,0,">");

  

 }

 else if(index>=min)///<在最小和最大序号之间

 {

  LCD_Write_Str(Menu_GetSelItem()-min,0," ");

  LCD_Write_Str(index-min,0,">");

 }

 else     ///<低于最小当前显示最小序号

 {

  LCD_Write_Str(Menu_GetSelItem()-min,0," ");

  

  min-=1;

  max-=1;

  ShowList(min,max);

  ListShow=(max<<4)|min;

  

  LCD_Write_Str(index-min,0,">");

 }

 SelItem=index;

}

void KeySelItem(u8 key)

{

 s8 index;

[1] [2]
关键字:STM32  液晶显示 引用地址:分享一个STM32菜单框架

上一篇:stm32上移植linux的实操案例经验分享
下一篇:基于STM32的平衡小车设计过程分享(3)

推荐阅读最新更新时间:2024-11-18 13:54

基于STM32单片机对HCSR04超声波的控制
注意:定义GPIOB2为超声输出;GPIOB10为输入,定时器用tim2 #include “HCSR04.h” #include “delay.h” #include “sys.h” int overcount; float length=0; void HCSR04_init() { GPIO_InitTypeDef GPIO_InitStructure; TIM_TImeBaseInitTypeDef TIM_TImeBaseInitStructer; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , EN
[单片机]
基于<font color='red'>STM32</font>单片机对HCSR04超声波的控制
基于PAJ7620和STM32手势识别应用案例
1.简介  手势识别是计算机科学和语言技术中的一个主题,目的是通过数学算法来识别人类手势。 手势可以源自任何身体运动或状态,但通常源自面部或手。 本领域中的当前焦点包括来自面部和手势识别的情感识别。 用户可以使用简单的手势来控制或与设备交互,而无需接触他们。姿势,步态和人类行为的识别也是手势识别技术的主题。手势识别可以被视为计算机理解人体语言的方式,从而在机器和人之间搭建比原始文本用户界面或甚至GUI(图形用户界面)更丰富的桥梁。 手势识别使人们能够与机器进行通信,并且无需任何机械设备即可自然交互。 使用手势识别的概念,可以将手指指向计算机屏幕,使得光标将相应地移动。 这可能使常规输入设备(如鼠标,键盘甚至触摸屏)变得冗余。越
[单片机]
基于PAJ7620和<font color='red'>STM32</font>手势识别应用案例
嵌入式系统学习——STM32之按键输入
之前写了两篇关于STM32 GPIO的介绍和运用,跑马灯用到了GPIO的推挽输出,但是对于输入还是没有用到,这次就运用一下GPIO的上拉输入。实验还是和以前51做的实验一样,就是判断按键的输入,然后控制LED灯。这次没有直接配置寄存器,而是调用库函数和位操作结合。 注:每一块开发板对应电路都不相同,编写代码需要对应自己的板子,本人两个LED灯对应的GPIO为:GPIOD13和GPIOD14,并且是共阴极。两个按键对应的GPIO为:GPIOC13和GPIOE0,并且共阴极。 首先,LED初始化和上一篇博客中的跑马灯初始化一样,只需拷贝就可以了。 LED初始化函数: #include sys.h
[单片机]
嵌入式系统学习——<font color='red'>STM32</font>之按键输入
STM32 学习十 Flash下载与调试
一、启动模式 三、FLASH下载与调试 选择调试模式: 1.RAM调试:0x20000000 2.FLASH调试:0x8000000 CM3的Flash烧写次数:1000次 安装Setup_JLinkARM_V408h 连接j-Link-ARM到电脑。我使用虚拟机做开发,这时候需要把USB连接到虚拟机上。 把开发板连接到jLink并上电。 下载操作: 1.新增下载模式 2.设置Options 这里注意与芯片参数要一致。 下载: 下载结束,操作成功。
[单片机]
<font color='red'>STM32</font> 学习十 Flash下载与调试
stm32定时器的pwm1模式和pwm2模式的区别
在参考手册中,对两种模式的描述为 pwm1: 向上计数时,一旦TIMx_CNT TIMx_CCR1时通道1为有效电平,否则为 无效电平;在向下计数时,一旦TIMx_CNT TIMx_CCR1时通道1为无效电平(OC1REF=0),否 则为有效电平(OC1REF=1)。 pwm2: 在向上计数时,一旦TIMx_CNT TIMx_CCR1时通道1为无效电平,否则为 有效电平;在向下计数时,一旦TIMx_CNT TIMx_CCR1时通道1为有效电平,否则为无效电 平。 这里的一个关键点就是通道有效电平和输出电平有什么关系呢? 通道有效电平与OCxREF有关系,而经过我的实验研究和资料查找,发现这个OCxREF和CCX
[单片机]
STM32库文件结构及CMSIS介绍
使用STM32库时,各库文件作用及关系: CMSIS标准介绍:
[单片机]
SD卡存储容量的计算过程
前言 SD卡底层驱动代码量不小,功能稍微有点复杂,其他的功能不说了;本博文主要介绍SD卡V1.0和V2.0版本的SD卡的容量结算; 在对SD卡进行FATFS文件系统(最新R0.13c版本)移植时,接口函数DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void *buff )会获取SD卡的三个重要信息作为f_fdisk和f_mkfs函数为整个SD卡分区和挂载文件系统的依据; 下面的代码来自于STM32官方提供的固件库的SD卡例程,但是:例程里边有错误的地方需要修改,如果不修改有可能会影响到FatFS系统移植时分区的问题,在博文的最后有特别指出; CSD寄存器(Card-Specific Data
[单片机]
SD卡存储容量的计算过程
意法的90纳米STM32微控制器内置独特闪存加速器
    意法半导体宣布取得两项重大技术进展,促使市场成功的STM32系列微控制器的性能和功耗获得进一步提升,这两项进展分别是:内嵌90纳米制程闪存的微控制器问世;推出业内首款针对工业标准的ARM Cortex-M3内核优化的自适应实时(ART)存储器加速器。     意法半导体的首批采用90nm嵌入式闪存制程生产的STM32微控制器的运行速度更快,功耗更低,外设集成度更高,片上存储密度更大。90nm嵌入式闪存技术的性能已经在智能卡和汽车电子IC上得到实证。意法半导体已于2009年发布了内嵌90nm 闪存的微控制器的样片。     由于ARM Cortex-M3的性能高于闪存技术,在运行频率较高时,处理器必须等待闪存,意法半
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved