当前位置:首页 > 代码 > 正文

单片机多级菜单源代码(单片机 菜单)

admin 发布:2022-12-19 18:57 136


今天给各位分享单片机多级菜单源代码的知识,其中也会对单片机 菜单进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

用C语言写的多级菜单源程序(单片机),自己试验过,不要网上拷贝过来,谢谢。

先看第一层菜单

{ 0, 0, 0, 1, 0, MainJob1 }

菜单的索引号为0,这个是可以自己随便定义的,但不要超过255,因为你的索引已经声明uchar了,

第二个0,按下向上键的时候,跳到索引号为0的菜单,也就是,保持现在的界面,第三个0也是一样,第四个1,按下回车的时候,跟到索引号为1的菜单,MainJob1一般是一个当然按键的功能函数,或是界面显示函数

这样说,不知道你能明白不?

{1 ,7 ,2 ,8 ,0 , Dsp Point}

1------是当前的索引号

7------按下向上的时候,跳到7号索引的菜单

2------按下向下的时候,跳到2号索引的菜单

8------按下回车的时候,跳到8号索引的菜单

0------按下回车的时候,跳到0号索引菜单,也就是返回到主界面了

至于说,怎么赋值的,其实就是看你自己想怎么设计你的菜单了,

当前的索引号,你自己定义

按下什么按键时,想跳到哪一个索引的菜单,就是这样了

STM32的按键与液晶多级菜单怎么写呢?

百度文库里有很多教程的,比如下面这个,不过要提醒大家,这里边有个错误,它的结构体数组index_struct_code code index_struct[SIZE_OF_MENU]这句不对,应该去掉那个code直接是 index_struct_code index_struct[SIZE_OF_MENU],相当于定义了一个结构体后在定义一个结构体数组,希望能帮到你!有问题还可以向我提问,先好好看看这篇文章吧

51单片机的多级菜单问题,C语言的,汇编的看不懂~

这样的程序代码长度都较长,不可能贴在这里的。我有,都是几千行项目源程序。

Arduino 怎么写多级菜单

本帖最后由 qhdtc5 于 2015-3-25 08:00 编辑

说明:

使用了LCD5110作为显示屏,库为LCD5110_Basic

借鉴了其他程序的一些思路,用链表作为菜单结构,并使用Action概念来确定菜单项的动作

虽然动作类型设想有好几种,但我只写了设置逻辑值的菜单动作,其他的可自行完善(我也会继续写完)

代码未优化和未考虑内存占用等问题

请大家指教

先上图片和视频

[media][/media]

代码:

[mw_shl_code=bash,true]#include Wire.h

#include DS3231.h

#include LCD5110_Basic.h

#define LIGHT_PIN 3

#define LED_PIN 13

// 菜单最大显示行数

#define MENU_MAX_ROW 5

/**

* 以下定义菜单项类型

*/

// 具有子菜单的菜单项

#define MENU_SUBMENU 0

// 参数项(用于执行参数设置)

#define MENU_PARAM 1

// 无动作的菜单项

#define MENU_ACTION_NONE 101

// 执行逻辑参数设置的菜单项(开/关、真/假等设置)

#define MENU_ACTION_LOGIC 102

// 执行数值调整设置的菜单项(时间、音量等设置)

#define MENU_ACTION_NUMBER 103

// 执行字符串设置的菜单项(欢迎语、LED显示文字等设置)

#define MENU_ACTION_STRING 104

/**

* 以下定义按键引脚

* 设置上拉电阻,低电平有效

*/

#define KEY_UP 7

#define KEY_DOWN 6

#define KEY_ENTER 5

#define KEY_EXIT 4

// 定义按键消抖延时时间

#define KEY_TREMBLE_TIME 20

// DS3231时钟变量

DS3231 clock;

// LCD5110液晶屏变量

LCD5110 myGLCD(8, 9, 10, 11, 12);

// LCD5110使用的字体

extern unsigned char SmallFont[];

/**

* 菜单结构

* 一个数组既代表一级菜单,数组中的一个元素就是一个菜单项,就是一个单独的结构体,

* 数组中的第一个元素中的num值很重要,表示本级菜单具有多少个菜单项。

*

* @var int num 本级菜单数量,必须在第一项中设置正确的菜单项数量

* @var char* label 菜单文本

* @var int type 此项类型,参考宏定义

* @var void (*action)(const char *) 指向动作的函数指针,此项要执行的具体动作函数

* @var mymenu* next 下一级菜单,只需在菜单的第一项设置,其他项置空(NULL)即可

* @var mymenu* prev 上一级菜单,同上

*/

struct mymenu {

int num;

char *label; //display label

int type; //0:item, 1:submenu, 2:param

void (*action)(const char *);

mymenu * next;

mymenu * prev;

};

/**

* 逻辑参数设置菜单

* 逻辑菜单表示菜单项中的action函数要执行逻辑设置动作,即设置某个参数的逻辑值

* 逻辑菜单只需两个菜单项代表true和false

* 需要遵守的规则为:菜单中的文本需要设置为“ON”和“OFF”,

* 在执行动作函数的时候,可以将正确的参数传递过去,

* 动作函数的规则参照函数说明

*/

mymenu logic_menu[2] = {

{2, "ON", MENU_PARAM, NULL, NULL, NULL},

{2, "OFF", MENU_PARAM, NULL, NULL, NULL}

};

/**

* 下面定义了三级菜单说明了菜单应该如何个定义

*/

// 第二级菜单

mymenu light_menu[2] = {

//第一项什么也不做,所以设置了类型为MENU_ACTION_NONE

{2, "light 1", MENU_ACTION_NONE, NULL, NULL, NULL},

//第二项指向了下级菜单,所以设置了类型为MENU_SUBMENU

{2, "light submenu", MENU_SUBMENU, NULL, NULL, NULL}

};

// 第三级菜单

mymenu test_level3_menu[7] = {

{7, "level3menu-1", MENU_ACTION_NONE, NULL, NULL, NULL},

{7, "level3menu-2", MENU_ACTION_NONE, NULL, NULL, NULL},

{7, "level3menu-3", MENU_ACTION_NONE, NULL, NULL, NULL},

{7, "level3menu-4", MENU_ACTION_NONE, NULL, NULL, NULL},

//定义了一个逻辑动作,这里是控制PIN13脚的LED

{7, "LED TEST", MENU_ACTION_LOGIC, NULL, NULL, NULL},

{7, "level3menu-6", MENU_ACTION_NONE, NULL, NULL, NULL},

{7, "level3menu-7", MENU_ACTION_NONE, NULL, NULL, NULL}

};

// 第一级菜单

mymenu main_menu[4] = {

{4, "item 1", MENU_ACTION_NONE, NULL, NULL, NULL},

{4, "item 2", MENU_ACTION_NONE, NULL, NULL, NULL},

//指向下一级菜单

{4, "item 2.1", MENU_SUBMENU, NULL, NULL, NULL},

{4, "item 3", MENU_ACTION_NONE, NULL, NULL, NULL}

};

// 定义菜单操作需要的全局变量

// 分别为当前菜单、上一级菜单、当前菜单项索引和开始显示的菜单项索引

mymenu *cur_item, *prev_item;

int item_index, start_index;

bool stat;

/**

* DS3231需要的全局变量

*/

bool Century=false;

bool h12;

bool PM;

byte ADay, AHour, AMinute, ASecond, ABits;

bool ADy, A12h, Apm;

int second,minute,hour,date,month,year,temperature;

int oldsecond; //此变量用于判断是否更新显示内容

// 定义LCD背光显示计时变量,无按键操作超时就关闭背光

unsigned long starttime;

// 定义菜单的操作按键(上、下、进入和返回)状态变量

bool old_up_stat, old_down_stat, old_enter_stat, old_exit_stat;

void setup() {

//设置LCD背光引脚为输出

pinMode(LIGHT_PIN, OUTPUT);

//设置按键为上拉电阻输入(低电平有效)

for (int i=4; i=7; i++){

pinMode(i, INPUT_PULLUP);

}

//初始化时打开LCD背光

backlight("ON");

stat = false;

//初始化LCD5110

myGLCD.InitLCD();

myGLCD.setContrast(127);

myGLCD.setFont(SmallFont);

myGLCD.print("Initialize...", 0, 0);

/**

* 菜单的进一步设置

* 在这里将每一个菜单的关联设置好

* 对照每一个初始设置仔细填写它们之间的关系

*/

//第一级(main_menu)的第三项指向了下一级菜单(light_menu)

main_menu[2].next = light_menu;

//第二级(light_menu)的上一级(main_menu)

light_menu[0].prev = main_menu;

//第二级(light_menu)的第二项指向了下一级菜单(test_level3_menu)

light_menu[1].next = test_level3_menu;

//第三级(test_level3_menu)的上一级(light_menu)

test_level3_menu[0].prev = light_menu;

//第三级(test_level3_menu)的第五项定义了个逻辑动作

test_level3_menu[4].action = ledtest;

/**

* 初始化当前菜单为第一级(main_menu)

*/

cur_item = main_menu;

/**

* 上一级菜单为空

*/

prev_item = NULL;

/**

* 当前选择了第一项

*/

item_index = 0;

/**

* 从第一项开始显示菜单

*/

start_index = 0;

/**

* 设置DS3231的日期和时间,只需在需要调整的时候执行一次

*/

//clock.setClockMode(true);

//I2C总线库初始化

Wire.begin();

//一些状态变量的初始化

oldsecond = -1;

old_up_stat = HIGH;

old_down_stat = HIGH;

old_enter_stat = HIGH;

old_exit_stat = HIGH;

//为了视频中能看清楚,延时定义了3秒

delay(3000);

//所有初始化完成,清屏并关闭LCD背光

myGLCD.clrRow(0);

backlight("OFF");

starttime = millis();

}

void loop() {

//获取运行时间

unsigned long endtime = millis();

//获取当前菜单的项目数量

int menu_num = cur_item[0].num;

//定义一个临时变量

int idx;

//绘制菜单

renderMenu(cur_item[0], menu_numMENU_MAX_ROW ? MENU_MAX_ROW : menu_num);

//读取按键

int k_down = digitalRead(KEY_DOWN);

int k_up = digitalRead(KEY_UP);

int k_enter = digitalRead(KEY_ENTER);

int k_exit = digitalRead(KEY_EXIT);

//计算无按键时间,决定是否关闭LCD背光

if (endtime-starttime5000) {

//myGLCD.enableSleep();

backlight("OFF");

}

//有键按下,打开LCD背光,计时清零

if (k_up==LOW || k_down==LOW || k_enter==LOW || k_exit==LOW) {

//myGLCD.disableSleep();

backlight("ON");

starttime = endtime;

}

//检测按键,进入相应动作

if (k_up == LOW k_up!=old_up_stat){

//消抖

delay(KEY_TREMBLE_TIME);

if (k_up == LOW){

item_index --;

}

} else if (k_down == LOW k_down!=old_down_stat){

//消抖

delay(KEY_TREMBLE_TIME);

if (k_down == LOW){

item_index ++;

}

} else if (k_enter == LOW k_enter!=old_enter_stat){

//消抖

delay(KEY_TREMBLE_TIME);

if (k_enter == LOW){

//计算此时的菜单项索引值

idx = start_index+item_index;

if (cur_item[idx].next != NULL cur_item[idx].type == MENU_SUBMENU){

//条件成立说明此菜单项指向了下一级菜单

//此级菜单变成了上一级菜单

prev_item = cur_item;

//将指向的下一级菜单设置为当前菜单

cur_item = cur_item[idx].next;

//重置菜单项索引和绘制索引

item_index = 0;

start_index = 0;

//清屏

myGLCD.clrScr();

} else if (cur_item[idx].action != NULL cur_item[idx].type != MENU_PARAM){

//条件成立说明此项菜单是动作

//此级菜单变成上一级菜单

prev_item = cur_item;

//根据动作类型调用相应的下一级菜单

switch(cur_item[idx].type){

case MENU_ACTION_LOGIC:

//将动作函数传递给逻辑菜单,使逻辑菜单能够正确执行动作

logic_menu[0].action = cur_item[idx].action;

//设置当前菜单为逻辑菜单

cur_item = logic_menu;

//重置菜单项索引和绘制索引

item_index = 0;

start_index = 0;

break;

case MENU_ACTION_NUMBER:

break;

case MENU_ACTION_STRING:

break;

default:

break;

}

//清屏

myGLCD.clrScr();

} else if (cur_item[idx].type == MENU_PARAM){

//条件成立说明正在执行动作

//调用相应的动作函数,并传递参数(这里只举例逻辑设置)

cur_item[0].action((const char *)cur_item[idx].label);

}

}

} else if (k_exit == LOW k_exit!=old_exit_stat){

//消抖

delay(KEY_TREMBLE_TIME);

if (k_exit == LOW){

//返回上一级菜单的操作

if (prev_item != NULL){

//设置上一级菜单为当前菜单

cur_item = prev_item;

//设置当前菜单的上一级菜单

prev_item = cur_item[0].prev;

//重置菜单项索引和绘制索引

item_index = 0;

start_index = 0;

//清屏

myGLCD.clrScr();

}

}

}

/**

* 菜单项上下选择是否越界

*/

if (item_index0){

item_index = 0;

start_index --;

if (start_index0) start_index = 0;

}

if (item_index=MENU_MAX_ROW || item_index=menu_num){

if (item_index=menu_num) item_index = menu_num-1;

if (item_index=MENU_MAX_ROW) item_index = MENU_MAX_ROW-1;

if (start_index+MENU_MAX_ROWmenu_num) start_index ++;

}

//保存按键状态

old_up_stat = digitalRead(KEY_UP);

old_down_stat = digitalRead(KEY_DOWN);

old_enter_stat = digitalRead(KEY_ENTER);

old_exit_stat = digitalRead(KEY_EXIT);

//renderClock(0, 0);

}

/**

* 关闭LCD背光

* 此函数符合菜单动作定义规则,即无返回值、一个字符串参数

*

* @var const char* stat 值为“ON"打开背光,为“OFF”关闭背光

*/

void backlight(const char *stat)

{

//这里定义了一个逻辑动作

//根据参数决定LCD背光的开关

digitalWrite(LIGHT_PIN, strcmp(stat,"ON") ? LOW : HIGH);

}

/**

* 逻辑动作测试函数

*

* @var const char* stat 根据此参数来执行动作,这里测试PIN13的LED

*/

void ledtest(const char *stat)

{

//根据参数决定LED开关

digitalWrite(LED_PIN, strcmp(stat,"ON") ? LOW : HIGH);

}

/**

* 绘制单个菜单项

*

* @var struct mymenu item 要绘制的项目

* @var int row 绘制坐标(LCD5110绘制文字时只需一个行坐标即可,可根据实际显示设备调整)

* @var bool rev 是否反相绘制,默认为不反相绘制(用于当前选中项绘制,可根据实际显示设备调整)

*/

void renderItem(struct mymenu item, int row, bool rev = false)

{

char label[15];

//规范显示项目文字(左对齐,补空格)

sprintf(label, "%-14s", item.label);

if (rev){

//打开5110的反相绘制功能

myGLCD.invertText(true);

}

//绘制菜单项

myGLCD.print(label, 0, row);

if (rev){

//关闭5110的反相绘制功能

myGLCD.invertText(false);

}

}

/**

* 绘制某一级菜单

*

* @var struct mymenu* items 需要绘制的菜单

* @var int menu_num 菜单项目数量

*/

void renderMenu(struct mymenu *items, int menu_num)

{

//绘制数量不能超过每一屏的最大绘制数量

int num = menu_numMENU_MAX_ROW ? MENU_MAX_ROW : menu_num;

for (int i=0; inum; i++){

//绘制每个菜单项

renderItem(items[i+start_index], i*8, i==item_index ? true:false);

}

}

void renderClock(int row)

{

char s[12];

second = clock.getSecond();

minute = clock.getMinute();

hour = clock.getHour(h12, PM);

date = clock.getDate();

month = clock.getMonth(Century);

year = clock.getYear();

temperature = clock.getTemperature();

if (oldsecond!=second){

sprintf(s, "20%02d-%02d-%02d", year, month, date);

myGLCD.print(s, 0, row);

sprintf(s, "%02d:%02d:%02d", PM==0 ? hour:hour+12, minute, second);

myGLCD.print(s, 0, row+8);

sprintf(s, "%3d", sizeof(main_menu)/sizeof(mymenu));

myGLCD.print(s, 0, row+16);

oldsecond = second;

}

}

void clockSetting(int year, int month, int day, int hour, int minute, int second)

clock.setSecond(second);//配置秒

clock.setMinute(minute

关于单片机多级菜单源代码和单片机 菜单的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

版权说明:如非注明,本站文章均为 AH站长 原创,转载请注明出处和附带本文链接;

本文地址:http://ahzz.com.cn/post/18928.html


取消回复欢迎 发表评论:

分享到

温馨提示

下载成功了么?或者链接失效了?

联系我们反馈

立即下载