单片机按键菜单实现

menu.h

# ifndef __MENU_H_
# define __MENU_H_

# define Menu_len 57        //定义结构体数组大小;

/*-------------------------函数声明----------------------*/
void Key_response(void);


/*--------------------------变量------------------------*/
extern unsigned char Index_num;             //索引号;

extern void (*Key_function)(void);  //按键函数;


# endif

 

menu.c

# include<msp430f149.h>
# include "lcd12864_application.h"
# include "menu.h"
# include "display.h"

unsigned char Index_num = 0;
void (*Key_function)(void);

struct Menu 
{
    unsigned char Current_state;              //当前状态索引;
    unsigned char Up_index;                   //按上键的状态索引;
    unsigned char Down_index;                 //按下键的状态索引;
    unsigned char Left_index;                 //按左键的状态索引;
    unsigned char Right_index;                //按右键的状态索引;
    unsigned char Enter_index;                //按确认键的状态索引;
    unsigned char Exit_index;                 //按返回键的状态索引;
    void (*Current_operate)(void);            //当前状态所执行的操作;
};

const struct Menu Menu_Index[]=
{
    {0, 1, 1, 1, 1, 1, 1,  (*Init_interface)}, //开机菜单;
    
    {1, 3, 2, 1, 1, 4, 2,  (*First_menu)},     //电机测速        //第一层
    {2, 3, 3, 2, 2, 4, 2,  (*First_menu)},     //电机正转        //第一层
    {3, 2, 2, 3, 3, 4, 2,  (*First_menu)},     //电机反转        //第一层
    
    {4, 5, 5, 4, 4, 6, 2,  (*Second1_menu)},    //转速设置     //第二层菜单--状态2的子项;
    {5, 4, 4, 5, 5, 8, 2,  (*Second1_menu)},    //转速显示     
    
    {6, 7, 7, 6, 6, 6, 4,  (*Second2_menu)},     //设定的转速      //第二层菜单--状态4的子项
    {7, 6, 6, 7, 7, 12, 4, (*Second2_menu)},     //       (r/s)
    
    {8, 11, 9, 8, 8, 8, 5, (*Second3_menu)},        //转速显示值  
    {9, 8, 10, 9, 9, 9, 5,  (*Second3_menu)},       //        (r/s)   
    {10, 9, 11, 10, 10, 10, 5, (*Second3_menu)},    //转速设置显示       //第二层菜单--状态3的子项
    {11, 10, 8, 11, 11, 11, 5, (*Second3_menu)},    //        (r/s)    //第三层菜单--第二层菜单状态2的子项;

    {12, 12, 12, 12, 12, 7, 7, (*Third1_menu)},    // (r/s)
/*    {13, 12, 8, 50, 1, (*Second1_menu)},          //         
    {14, 19, 15, 50, 2, (*Second2_menu)},           //
    
    {15, 14, 16, 50, 2, (*Second2_menu)},          //      
    {16, 15, 17, 50, 2, (*Second2_menu)},          //
    {17, 16, 18, 50, 2, (*Second2_menu)},          //
    {18, 17, 19, 50, 2, (*Second2_menu)},          //
    {19, 18, 14, 50, 2, (*Second2_menu)},          //第二层菜单--状态2的子项;            
    
    {20, 25, 21, 50, 3, (*Second3_menu)},
    {21, 20, 22, 50, 3, (*Second3_menu)},
    {22, 21, 23, 50, 3, (*Second3_menu)},
    {23, 22, 24, 50, 3, (*Second3_menu)},      
    {24, 23, 25, 50, 3, (*Second3_menu)},
    {25, 24, 20, 50, 3, (*Second3_menu)},          //第二层菜单--状态3的子项;
    
    {26, 31, 27, 50, 4, (*Second4_menu)},
    {27, 26, 28, 50, 4, (*Second4_menu)},    
    {28, 27, 29, 50, 4, (*Second4_menu)},
    {29, 28, 30, 50, 4, (*Second4_menu)},
    {30, 29, 31, 50, 4, (*Second4_menu)},
    {31, 30, 26, 50, 4, (*Second4_menu)},       //第二层菜单--状态4的子项;   
    
    {32, 37, 33, 50, 5, (*Second5_menu)},
    {33, 32, 34, 50, 5, (*Second5_menu)},
    {34, 33, 35, 50, 5, (*Second5_menu)},
    {35, 34, 36, 50, 5, (*Second5_menu)}, 
    {36, 35, 37, 50, 5, (*Second5_menu)},
    {37, 36, 32, 50, 5, (*Second5_menu)},       //第二层菜单--状态5的子项;
    
    {38, 43, 39, 50, 6, (*Second6_menu)},
    {39, 38, 40, 50, 6, (*Second6_menu)}, 
    {40, 39, 41, 50, 6, (*Second6_menu)},
    {41, 40, 42, 50, 6, (*Second6_menu)},
    {42, 41, 43, 50, 6, (*Second6_menu)},
    {43, 42, 38, 50, 6, (*Second6_menu)},       //第二层菜单--状态6的子项;
    
    {44, 49, 45, 50, 7, (*Second7_menu)},
    {45, 44, 46, 50, 7, (*Second7_menu)},
    {46, 45, 47, 50, 7, (*Second7_menu)},
    {47, 46, 48, 50, 7, (*Second7_menu)}, 
    {48, 47, 49, 50, 7, (*Second7_menu)},
    {49, 48, 44, 50, 7, (*Second7_menu)},       //第二层菜单--状态7的子项;
*/    
};

/*------------------------按键响应-----------------------*/

void Key_response(void)
{
    switch(Key_value)
    {
        case Up:
            Index_num = Menu_Index[Index_num].Up_index;
            break;
        case Down:
            Index_num = Menu_Index[Index_num].Down_index;
            break;
        case Left:
            Index_num = Menu_Index[Index_num].Left_index;
            break;    
        case Right:
            Index_num = Menu_Index[Index_num].Right_index;
            break;                         
        case Enter:
            Index_num = Menu_Index[Index_num].Enter_index;
            break;
        case Exit:
            Index_num = Menu_Index[Index_num].Exit_index;
            break;
        default:
            return;
            break;         
    }
    Key_function = Menu_Index[Index_num].Current_operate;
    (*Key_function)();
}


 

  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是基于51单片机按键控制多级菜单代码示例: ```c #include <reg51.h> #define KEY_SCAN_INTERVAL 100 typedef struct MenuItem { char* name; unsigned char value; struct MenuItem* sub_menu; } MenuItem; MenuItem main_menu[] = { {"Option 1", 1, NULL}, {"Option 2", 2, NULL}, {"Option 3", 3, NULL}, {"Submenu", 4, (MenuItem[]) { {"Suboption 1", 1, NULL}, {"Suboption 2", 2, NULL}, {"Submenu 2", 3, (MenuItem[]) { {"Subsuboption 1", 1, NULL}, {"Subsuboption 2", 2, NULL}, {NULL, 0, NULL} }}, {NULL, 0, NULL} }}, {NULL, 0, NULL} }; unsigned char key_code = 0; void main() { while (1) { key_code = read_key(); if (key_code != 0) { unsigned char value = menu_select(main_menu); process_option(value); } } } unsigned char read_key() { // Read key code from hardware } unsigned char menu_select(MenuItem* menu) { unsigned char index = 0; while (1) { display_menu(menu, index); unsigned char key_code = read_key(); if (key_code == KEY_UP) { if (menu[index - 1].name != NULL) { index--; } else { index = menu_length(menu) - 1; } } else if (key_code == KEY_DOWN) { if (menu[index + 1].name != NULL) { index++; } else { index = 0; } } else if (key_code == KEY_SELECT) { if (menu[index].sub_menu != NULL) { return menu_select(menu[index].sub_menu); } else { return menu[index].value; } } else { // Invalid key code, ignore } delay(KEY_SCAN_INTERVAL); } } void display_menu(MenuItem* menu, unsigned char index) { // Display menu on LCD with current selection highlighted } unsigned char menu_length(MenuItem* menu) { unsigned char length = 0; while (menu[length].name != NULL) { length++; } return length; } void process_option(unsigned char value) { // Handle selected menu option } ``` 这个代码示例定义了一个MenuItem结构体,包含菜单名称、对应的数值和子菜单列表。主菜单和子菜单都由MenuItem数组表示。在主循环中,读取按键输入,并通过menu_select函数选择菜单选项。menu_select函数递归地显示菜单,并根据按键输入选择当前菜单项或进入子菜单。display_menu函数在LCD上显示菜单,并使用当前选择项进行高亮显示。menu_length函数计算MenuItem数组的长度。最后,process_option函数处理选择的菜单选项。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值