单片机多级菜单的简单实现

单片机多级菜单的简单实现

多级菜单的思路

最近想把stm32上的oled显示屏做的好看一些,于是动手写了写一个多级菜单,思路很简单,每个页面用单独的函数封装好,每个功能也是用单独的函数进行封装,用了3个按键,两个切换键,一个确定键。

  1. 首先来看看用啥判断页面的(这偷个懒,希望没人打我)
//页面标志位
uint8_t s1 = 0;			//主页面功能号
uint8_t s2 = 0;			//主次页面判断标志位
uint16_t s3 = 1;		//次页面功能号
  1. 主页面的显示函数,这是个很枯燥的一个显示函数。将功能图标显示出来,Draw_BMP()中的第一个形参判断图片是否反白,0是不反白,1是反白。
void function_primary(void) //一级界面,显示功能图标
{	
   Draw_BMP(0,0,0,32,4,BMP5);
   Draw_BMP(0,48,0,80,4,BMP6);
   Draw_BMP(0,95,0,127,4,BMP7);
   Draw_BMP(0,0,4,32,8,BMP8);
   Draw_BMP(0,48,4,80,8,BMP9);
   Draw_BMP(0,95,4,127,8,BMP10);
   switch(s1)		//一级页面功能号
   {
   	case 1: Draw_BMP(1,0,0,32,4,BMP5); break;
   	case 2: Draw_BMP(1,48,0,80,4,BMP6); break;
   	case 3: Draw_BMP(1,95,0,127,4,BMP7); break;
   	case 4: Draw_BMP(1,0,4,32,8,BMP8); break;
   	case 5: Draw_BMP(1,48,4,80,8,BMP9); break;
   	case 6: Draw_BMP(1,95,4,127,8,BMP10); break;
   	default:	break;
   }
}
  1. 二级页面的显示函数,其实和一级页面差不多,无非是换了个标志位。这里就放一个次页面的就好了,其他的想加几个就复制几个。同样OLED_P8x16Str()中的第一个形参判断文字是否反白,0是不反白,1是反白。
void function_level1(void)
{
	sprintf(buf,"1.1");
	OLED_P8x16Str(0u,0u,0u,(uint8_t *)buf);
	sprintf(buf,"1.2");
	OLED_P8x16Str(0u,0u,2u,(uint8_t *)buf);
	sprintf(buf,"1.3");
	OLED_P8x16Str(0u,0u,4u,(uint8_t *)buf);
	sprintf(buf,"1.4  exit");
	OLED_P8x16Str(0u,0u,6u,(uint8_t *)buf);
	switch(s3)	//次页面功能号
	{
		case 1:sprintf(buf,"1.1");
			OLED_P8x16Str(1u,0u,0u,(uint8_t *)buf);
			break;
		case 2:sprintf(buf,"1.2");
			OLED_P8x16Str(1u,0u,2u,(uint8_t *)buf);
			break;
		case 3:sprintf(buf,"1.3");
			OLED_P8x16Str(1u,0u,4u,(uint8_t *)buf);
			break;
		case 4:sprintf(buf,"1.4  exit");
			OLED_P8x16Str(1u,0u,6u,(uint8_t *)buf);
			break;
		default:break;
	}
}
  1. 这里是确定按键,负责选中主界面或次界面的某个功能,按下后进行判断是哪个功能被选中并执行
void function(void)			//主页面切换至次界面
{	
	if(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin)==RESET)
	{
		HAL_Delay(200);
		if(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin) == SET)
		{	
			if(s2 == 0)		//位于主界面
			{
				switch(s1)		//判断切换至哪个次界面
					{
						case 1: OLED_CLS();
								s2 = 1;
								function_level1();
								break;
						case 2: OLED_CLS();
								s2 = 2;
								function_level2();
								break;
						case 3: OLED_CLS();
								s2 = 3;
								function_level3();
								break;
						case 4: OLED_CLS();
								s2 = 4;
								function_level4();
								break;
						case 5: OLED_CLS();
								s2 = 5;
								function_level5();
								break;
						case 6: OLED_CLS();
								s2 = 6;
								function_level6();
								break;
						default:OLED_CLS(); 
								break;
					}
				}
				if(s2 != 0)		//判断是否位于次界面
				{
					if(s3 == 4)		//位于次界面时,选中次界面中功能四,执行切换回主界面
					{
						OLED_CLS();
						function_primary();
						s2 = 0;			//s2恢复初值
						s3 = 1;			//s3恢复初值
					}
				}
			}
		}
}
  1. 这里则是移动按键,负责选中某个功能对应的显示名称,并且将该功能对应的显示反白。这边放的是功能号递增
void key_scan1(void)		//功能切换按键1
{
	if(HAL_GPIO_ReadPin(KEYS_GPIO_Port,KEYS_Pin) == RESET)
	{
		switch(s2)		//判断是主界面中哪个功能的次界面
		{
			case 0:
			HAL_Delay(200);
			if(HAL_GPIO_ReadPin(KEYS_GPIO_Port,KEYS_Pin) == SET)
			{
				OLED_CLS();
				s1+=1;
			}
			if(s1 > 6)
				s1 = 1;
			else
				s1 = s1;
			display();
			break;
			
			case 1:
			HAL_Delay(200);
			if(HAL_GPIO_ReadPin(KEYS_GPIO_Port,KEYS_Pin) == SET)
			{
				OLED_CLS();
				s3+=1;
			}
			if(s3 > 4)
				s3 = 1;
			else
				s3 = s3;
			function_level1();
			break;
				
			case 2:
			HAL_Delay(200);
			if(HAL_GPIO_ReadPin(KEYS_GPIO_Port,KEYS_Pin) == SET)
			{
				OLED_CLS();
				s3+=1;
			}
			if(s3 > 4)
				s3 = 1;
			else
				s3 = s3;
			function_level2();
			break;
				
			case 3:
			HAL_Delay(200);
			if(HAL_GPIO_ReadPin(KEYS_GPIO_Port,KEYS_Pin) == SET)
			{
				OLED_CLS();
				s3+=1;
			}
			if(s3 > 4)
				s3 = 1;
			else
				s3 = s3;
			function_level3();
			break;
		//后面你有多少功能就加多少case语句判断,格式一样
		......
		default:
		break;
			}
	}
}	
  1. 这里是执行功能号递减的按键,只放上面对应要修改的部分,这里要说明一下,按键的函数是对所有的界面判断了功能号,即对s2进行判断,当 s2 = 0 的时候,显示的是一级界面,后面的才是二级界面的功能号。(s2作为功能号,放的是所有功能的序号。即后面有三级界面啥的,功能号都放着里面)
  • 注意:每个页面可能对应的功能不同,s1,s3作为主次界面的判断标志,其界面内拥有的功能数量可能有所不同,可以自行修改。
			case 0:
			HAL_Delay(200);
			if(HAL_GPIO_ReadPin(KEYS_GPIO_Port,KEYS_Pin) == SET)
			{
				OLED_CLS();
				s1-=1;
			}
			if(s1 < 1)
				s1 = 6;
			else
				s1 = s1;
			display();
			break;
  1. 最后在main函数这个大循环里,只要加上那三个按键的函数就行了
  while (1)
  {
		function();		//先执行确定,显示出主页面
		key_scan1();	//再进行功能选择
		key_scan2();
  }
  1. 到这边这个多级菜单也算是完成了,其实这些代码都是没啥难度,想明白思路基本就是敲完一个模板,其他的就C+V操作,改好参数就好了,要实现具体的切换功能键选中后再执行相应的功能,直接在显示的函数里加就好了。其实还有许多复杂的方法可以写多级菜单,链表啊啥的,奈何学艺不精,数据结构想从理论运用到实际还是有难度的。不过这简单的代码虽然看上去还是挺枯燥没啥味道,用起来还是可以的。最后个人认为按键最好加硬件消抖,用户体验提高不少。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值