⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 multi_menu.c

📁 制作简易液晶多级菜单
💻 C
字号:
//Author--youlong
typedef char S8;
typedef unsigned char U8;
typedef short S16;
typedef unsigned short U16;
typedef long S32;
typedef unsigned long U32;
typedef void (*key_func)(U8 key);
typedef enum {
    KEY_YES = 0,
    KEY_NO,
    KEY_UP,
    KEY_DOWN,
    KEY_MAX
}KEY_VALUE;//按键值定义

#define ROWS_PER_PAGE 4 //一屏显示4行
#define MAX_MENU_ITEM 11 //总共11个菜单项



typedef enum {
    MENU_ID_IDLE,
    MENU_ID_MAIN_MENU,
    MENU_ID_UART_CONFIG,
    MENU_ID_UART_SELECT,
    MENU_ID_BAUDRATE_SETTING,
    MENU_ID_CALENDAR,
    MENU_ID_DATE_SETTING,
    MENU_ID_TIME_SETTING,
    MAX_MENU_ID,
    INVALID_MENU_ID
}MENU_ID;//菜单ID定义

typedef enum {
    STR_ID_IDLE,
    STR_ID_MAIN_MENU,
    STR_ID_UART_CONFIG,
    STR_ID_UART_SELECT,
    STR_ID_BAUDRATE_SETTING,
    STR_ID_CALENDAR,
    STR_ID_DATE_SETTING,
    STR_ID_TIME_SETTING,
    MAX_STR_ID,
    INVALID_STR_ID
}STRING_ID;//字符串ID定义

typedef struct {
    MENU_ID father;//上级菜单
    STRING_ID string_id;//字符串ID
    U8 total_son;//子菜单数目
    MENU_ID son[MAX_MENU_ITEM];//子菜单ID
    key_func key_exec;//菜单项高亮时的执行函数
}MENU_TBL;//菜单列表定义


typedef struct{
    MENU_ID curr_menu_id;
    U8 total_num; //总的菜单项
    U8 rows_per_page; //一屏显示的行数
    U8 first_display_row; //当前屏的起始行
    U8 highlight_row;//需要高亮显示的行
    MENU_TBL *item;//指向当前菜单项的结构指针
}LIST_MENU_STRUCT;


extern U8 get_key(void);
extern void get_char_array(S8 *str, S8 *array_buf);
extern U8 lcd_print_row(U8 row, U8 col, S8 *data);
extern void lcd_clear_screen(void);


MENU_ID get_highlight_menu_id(void);
S8 *get_menu_string(MENU_ID menu_id);
key_func get_key_handler(MENU_ID menu_id);
MENU_ID get_father_id(MENU_ID menu_id);
void uart_config_highlight_handler(U8 key);
void calendar_highlight_handler(U8 key);
void return_to_idle(void);
void do_nothing(void);
void go_to_next_item(void);
void go_to_prev_item(void);
void return_to_father(void);

LIST_MENU_STRUCT *current_menu,LIST_MENU ;


const S8 *str_tbl[MAX_STR_ID] = {
    "待机状态",
    "主菜单",
    "串口设置",
    "串口选择",
    "波特率选择",
    "日历设置",
    "日期设置",
    "时间设置"
};//字符串常量


const MENU_TBL user_menu[MAX_MENU_ID] = {//与菜单ID对应
	//father , string, number of son, son, key handler
    	{INVALID_MENU_ID, INVALID_STR_ID, 1, {MENU_ID_MAIN_MENU}, NULL},//待机状态
    	
    	{MENU_ID_IDLE, STR_ID_MAIN_MENU, 2, {MENU_ID_UART_CONFIG, MENU_ID_CALENDAR}, NULL},//主菜单
    	
    	{STR_ID_MAIN_MENU, STR_ID_UART_CONFIG, 2, {MENU_ID_UART_SELECT, MENU_ID_BAUDRATE_SETTING}, uart_config_highlight_handler},//串口设置
    	
    	{MENU_ID_UART_SELECT, STR_ID_UART_SELECT, 0, {INVALID_MENU_ID}, uart_select_highlight_handler},//串口选择
    	
    	{MENU_ID_BAUDRATE_SETTING, STR_ID_BAUDRATE_SETTING, 0, {INVALID_MENU_ID}, baudrate_setting_highlight_handler},//波特率选择
    	
    	{STR_ID_MAIN_MENU, STR_ID_CALENDAR, 2, {MENU_ID_DATE_SETTING, MENU_ID_TIME_SETTING}, calendar_highlight_handler},//日历设置
    	
    	{MENU_ID_DATE_SETTING, STR_ID_DATE_SETTING, 0, {INVALID_MENU_ID}, date_setting_highlight_handler},//日期设置
    	
    	{MENU_ID_TIME_SETTING, STR_ID_TIME_SETTING, 0, {INVALID_MENU_ID}, time_setting_highlight_handler}//时间设置
};

MENU_ID get_highlight_menu_id(void)
{
	return current_menu->item->son[current_menu->highlight_row];
}

S8 *get_menu_string(MENU_ID menu_id)
{
	STRING_ID str_id = user_menu[menu_id].string_id
	return str_tbl[str_id];
}

key_func get_key_handler(MENU_ID menu_id)
{
	return user_menu[menu_id].key_exec;
}

MENU_ID get_father_id(MENU_ID menu_id)
{
	return user_menu[menu_id].father;
}
void uart_select_highlight_handler(U8 key)
{
	switch(key)
	{
		case KEY_YES:
			do_nothing();
			break;
		case KEY_NO:
			return_to_father();
			break;
		case KEY_UP:
			go_to_prev_item();
			break;
		case KEY_DOWN:
			go_to_next_item();
			break;
		default:break;
	}
}
void baudrate_setting_highlight_handler(U8 key)
{
	switch(key)
	{
		case KEY_YES:
			do_nothing();
			break;
		case KEY_NO:
			return_to_father();
			break;
		case KEY_UP:
			go_to_prev_item();
			break;
		case KEY_DOWN:
			go_to_next_item();
			break;
		default:break;
	}
}
void uart_config_highlight_handler(U8 key)
{
	switch(key)
	{
		case KEY_YES:
			menu_init(MENU_ID_UART_CONFIG);
			break;
		case KEY_NO:
			return_to_father();
			break;
		case KEY_UP:
			go_to_prev_item();
			break;
		case KEY_DOWN:
			go_to_next_item();
			break;
		default:break;
	}
}
void date_setting_highlight_handler(U8 key)
{
	switch(key)
	{
		case KEY_YES:
			do_nothing();
			break;
		case KEY_NO:
			return_to_father();
			break;
		case KEY_UP:
			go_to_prev_item();
			break;
		case KEY_DOWN:
			go_to_next_item();
			break;
		default:break;
	}
}
void time_setting_highlight_handler(U8 key)
{
	switch(key)
	{
		case KEY_YES:
			do_nothing();
			break;
		case KEY_NO:
			return_to_father();
			break;
		case KEY_UP:
			go_to_prev_item();
			break;
		case KEY_DOWN:
			go_to_next_item();
			break;
		default:break;
	}
}
void calendar_highlight_handler(U8 key)
{
	switch(key)
	{
		case KEY_YES:
			menu_init(MENU_ID_CALENDAR);
			break;
		case KEY_NO:
			return_to_father();
			break;
		case KEY_UP:
			go_to_prev_item();
			break;
		case KEY_DOWN:
			go_to_next_item();
			break;
		default:break;
	}
}
void return_to_idle(void)
{
}
void do_nothing(void)
{
}

void list_menu_highlight(U8 row)
{
	MENU_ID curr_highlight_menu_id;
	U8 i;
	S8 *str;
	S8 buf[256];
	curr_highlight_menu_id = get_highlight_menu_id();
	if((curr_highlight_menu_id < MAX_MENU_ID) && (curr_highlight_menu_id > MENU_ID_MAIN_MENU))
		str = get_menu_string(curr_highlight_menu_id);
	get_char_array(str, buf);
	for(i=0; i<256; i++)
	{
		buf[i] ^= 0xff;
	}
	lcd_print_row(row, 0, buf);
}

void draw_list_menu(void)
{
	MENU_ID menu_id;
	U8 i;
	S8 *str;
	S8 buf[256];
	lcd_clear_screen();
	for(i=0; i<current_menu->rows_per_page; i++)
	{
		if((i+current_menu->first_display_row) >= current_menu->total_num)
			break;
		if((i+current_menu->first_display_row) == current_menu->highlight_row)
		{
			list_menu_highlight(i);
			continue;
		}
		menu_id = current_menu->item->son[i+current_menu->first_display_row];
		str = get_menu_string(menu_id);
		get_char_array(str, buf);
		lcd_print_row(i, 0, buf);
	}
}

void go_to_next_item(void) //向下按键处理函数
{
	current_menu->highlight_row++;
	if(current_menu->highlight_row >= (current_menu->total_num))
	{
		current_menu->highlight_row = 0;
		current_menu->first_display_row = 0;
	}
	else
	{
		if((current_menu->highlight_row%current_menu->rows_per_page) == 0)
			current_menu->first_display_row += current_menu->rows_per_page;
	}
	draw_list_menu();
}

void go_to_prev_item(void) //向上按键处理函数
{
	if(current_menu->highlight_row == 0)
	{
		current_menu->highlight_row = current_menu->total_num - 1;
		current_menu->first_display_row = (U8)((current_menu->total_num/current_menu->rows_per_page)*current_menu->rows_per_page);
	}
	else
	{
		current_menu->highlight_row--;
		if((current_menu->highlight_row%current_menu->rows_per_page) == (current_menu->rows_per_page-1))
			current_menu->first_display_row -= current_menu->rows_per_page;
	}
	draw_list_menu();
}

void return_to_father(void)
{
	MENU_ID curr_highlight_menu_id,father_id;
	curr_highlight_menu_id = get_highlight_menu_id();
	if((curr_highlight_menu_id < MAX_MENU_ID) && (curr_highlight_menu_id > MENU_ID_MAIN_MENU))
		father_id = get_father_id(curr_highlight_menu_id);
	if(father_id > MENU_ID_IDLE)
		menu_init(father_id);
}
void menu_init(MENU_ID menu_id) //菜单初始化
{
	current_menu = &LIST_MENU;
	current_menu->curr_menu_id = menu_id;
	current_menu->item = &user_menu[menu_id];
	current_menu->total_num = current_menu->item->total_son;
	current_menu->rows_per_page = ROWS_PER_PAGE;
	current_menu->first_display_row = 0;
	current_menu->highlight_row = 0;
	draw_list_menu();
}

void main_menu_entry(void)//主菜单入口
{
	U8 key;
	MENU_ID curr_highlight_menu_id;
	key_func curr_key_handler;
	menu_init(MENU_ID_MAIN_MENU);
	while(1)
	{
		key = get_key();
		if(key < KEY_MAX)
		{
			curr_highlight_menu_id = get_highlight_menu_id();
			if((curr_highlight_menu_id < MAX_MENU_ID) && (curr_highlight_menu_id > MENU_ID_MAIN_MENU))
				curr_key_handler = get_key_handler(curr_highlight_menu_id);
			if(curr_key_handler)
				(*curr_key_handler)(key);
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -