STM32 任意显示屏都可以使用的简易UI界面(理论可嵌套无限层+区分8位16位整数和浮点数)

一.为什么要用菜单

二.菜单的简单演示

三.STM32 HAL库编写菜单界面

1.按键与菜单事件的链接

(1)编写key触发代码(包括消抖)

	功能描述:①.短按key,使状态位置1②key不能多次翻转状态位(消抖)
#define click 1
#define doubleclick 2
#define longclick 3

struct Key_def {
	volatile uint8 key_status;
	uint8 key_pressed_flag;
	uint8 judge_step;
	uint16 last_time;
	uint16 keep_time;
};

struct Key_def Key[4]={0,0,0,0};
void Key_Scan(void) {
	uint8 i=0;
	uint8 a=0;
	Key[0].key_status = HAL_GPIO_ReadPin(Button1_GPIO_Port,Button1_Pin);
	Key[1].key_status = HAL_GPIO_ReadPin(Button2_GPIO_Port,Button2_Pin);
	Key[2].key_status = HAL_GPIO_ReadPin(Button3_GPIO_Port,Button3_Pin);
	Key[3].key_status = HAL_GPIO_ReadPin(Button4_GPIO_Port,Button4_Pin);
	for (i=0;i<4;++i) {
		switch(Key[i].judge_step) {
			case 0: {
				if (Key[i].key_status == 0) Key[i].judge_step = 1;
			} break;
			case 1: {
				if (Key[i].key_status == 0) {
					Key[i].judge_step = 2;
					Key[i].key_pressed_flag = click;
				}
				else Key[i].judge_step = 0;
			}break;
			case 2: {
				if (Key[i].key_status == 1) Key[i].judge_step = 0;
			} break;
			default:Key[i].judge_step = 0;break;
		}
	}

(2)按键单击事件与菜单链接

	功能描述:①如果key状态位为1,则触发事件并且清除状态位
void UI_link_KEY(void) {
	if (Key[0].key_pressed_flag == click) {
		UI_PressUp();
		Key[0].key_pressed_flag = 0;
	}
	if (Key[1].key_pressed_flag == click) {
		UI_PressDown();
		Key[1].key_pressed_flag = 0;
	}
	if (Key[2].key_pressed_flag == click) {
		UI_PressIn();
		Key[2].key_pressed_flag = 0;
	}
	if (Key[3].key_pressed_flag == click) {
		UI_PressOut();
		Key[3].key_pressed_flag = 0;
	}
}

2.四个按键的服务程序编写

屏幕单行刷新的代码:

uint8 UI_pointer_none[]="    ";
uint8 UI_pointer[]="<-- ";
uint8 UI_pointer_pressed[]="<==>";
void UI_line_fresh(uint8 c,uint8 p_type){
	uint8 fresh_info[20]={0};
	uint8 *pointer_type=UI_pointer_none;
	switch (p_type) {
		case 0:pointer_type=UI_pointer_none;break;
		case 1:pointer_type=UI_pointer;break;
		case 2:pointer_type=UI_pointer_pressed;break;
		default:break;
	};

	switch (menu_now->line_value_type[c]) {
		case type_NULL:snprintf(fresh_info,20,"%s %s",menu_now->line_name[c],pointer_type);break;
		case type_char:snprintf(fresh_info,20,"%s %s %d  ",menu_now->line_name[c],pointer_type,*(char*)(menu_now->line_value[c]));break;
		case type_int:snprintf(fresh_info,20,"%s %s %d  ",menu_now->line_name[c],pointer_type,*(int*)(menu_now->line_value[c]));break;
		case type_float:snprintf(fresh_info,20,"%s %s %.2f  ",menu_now->line_name[c],pointer_type,*(float*)(menu_now->line_value[c]));break;
		default:break;
	};

	LCD_DisplayStringLine(c * 24,fresh_info);

}

(1)上,对应的服务程序编写

void UI_PressUp(void)
{
	uint8 page_num=0;
	while(menu_now->line_name[page_num][0] != 0) {
		page_num++;
	}
	if (menu_now->cursor_pressed == false) {
		UI_line_fresh(menu_now->cursor,0);
		menu_now->cursor -= 1;
		if (menu_now->cursor == -1) menu_now->cursor = page_num - 1;
		UI_line_fresh(menu_now->cursor,1);
	} else {
		UI_data_change(menu_now->cursor,1);
		UI_line_fresh(menu_now->cursor,2);
	}
}

(2)下

void UI_PressDown(void)
{
	uint8 page_num=0;
	while(menu_now->line_name[page_num][0] != 0) {
		page_num++;
	}
	if (menu_now->cursor_pressed == false) {
		UI_line_fresh(menu_now->cursor,0);
		menu_now->cursor += 1;
		if (menu_now->cursor == page_num) menu_now->cursor = 0;
		UI_line_fresh(menu_now->cursor,1);
	} else {
		UI_data_change(menu_now->cursor,0);
		UI_line_fresh(menu_now->cursor,2);
	}
}

(3)确定

void UI_PressIn(void)
{
	uint8 i=1;
	if (menu_now->cursor_pressed == false) {
		if (menu_now->line_value_type[menu_now->cursor] != type_NULL) {

			menu_now->cursor_pressed = true;
			UI_line_fresh(menu_now->cursor,2);
		}
	}
}

(4)退出

void UI_PressOut(void)
{
	if (menu_now->cursor_pressed == true) {
		menu_now->cursor_pressed = false;
		UI_line_fresh(menu_now->cursor,1);
	}
}

3.使用结构体表达某个界面

typedef void (*UI_handler_def) (void);

struct UI_def {
	uint8 line_name[10][10];
	void *line_value[10];
	uint8 line_value_type[10];
	
	int8 cursor;
	volatile bool cursor_pressed;
	
	struct UI_def *next_menu[10];
	UI_handler_def function[10];
};
struct UI_def menu_main={
	{"   ","price","number",NULL},
	{NULL,NULL,NULL,NULL},
	{type_NULL,type_NULL,type_NULL,type_NULL},
	0,
	false,
    {NULL,&menu_price,&menu_number,NULL},
	{NULL,NULL,NULL,NULL}
};
char raw=1;
int cai=1;
float dan=1.1;

struct UI_def menu_price= {
	{"BACK","raw","cai","dan",NULL},
	{NULL,&raw,&cai,&dan,NULL},
	{type_NULL,type_char,type_int,type_float,type_NULL},
	0,
	false,
  {&menu_main,NULL,NULL,NULL,NULL},
	{NULL,NULL,NULL,NULL,NULL}
};

struct UI_def menu_number= {
	{"BACK","rou","cai","dan",NULL},
	{NULL,&raw,&cai,&dan,NULL},
	{type_NULL,type_char,type_int,type_float,type_NULL},
	0,
	false,
    {&menu_main,NULL,NULL,NULL,NULL},
	{NULL,NULL,NULL,NULL,NULL}	
};

4.使用单向链表链接下一个界面

void UI_PressIn(void)
{
	uint8 i=1;
	if (menu_now->cursor_pressed == false) {
		if (menu_now->line_value_type[menu_now->cursor] != type_NULL) {

			menu_now->cursor_pressed = true;
			UI_line_fresh(menu_now->cursor,2);
		}
		else if (menu_now->next_menu[menu_now->cursor] != NULL) {
			menu_now->cursor_pressed = false;
			menu_now=menu_now->next_menu[menu_now->cursor];
			menu_now->cursor = 0;
			LCD_Clear(White);					//ÇåÆÁ
			UI_line_fresh(menu_now->cursor,1);
			while(menu_now->line_name[i][0] != 0) {
				UI_line_fresh(i,0);
				i++;
			}
		}
	}
}

5.LCD屏幕显示界面

四.源码分享

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值