找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3301|回复: 9
收起左侧

单片机多级菜单+按键,子函数中有按键如何处理?

[复制链接]
ID:743654 发表于 2021-1-5 17:32 | 显示全部楼层 |阅读模式
50黑币
本帖最后由 cheney03 于 2021-1-5 19:48 编辑

程序是网上的例程,已实现多级菜单显示。现在有个问题:当进入函数fun1中,fun1函数中也有按键需要处理(通过up down键对变量temp实现加 减),这样按键有冲突,要怎么实现不冲突呢?按键为4*4矩阵按键,通过行列扫描获取键值判断哪个键按下。



#include <reg52.h>
#include "fun.h"
#include "lcd12864.h"
#include "delay.h"
#define uchar unsigned char
uchar func_index=0;
void (*current_operation_index)();
typedef struct
   {
         uchar current;
         uchar up;//向上翻索引号
         uchar down;//向下翻索引号
         uchar enter;//确认索引号
         void (*current_operation)();
         } key_table;
key_table code table[3]=
{
        {0,3,1,3,(*fun1)},
         {1,0,2,2,(*fun2)},
         {2,1,3,1,(*fun3)} ,
         {3,2,0,0,(*fun3)}

void main()
{  
    init_lcd(); //初始化LCD模块  
    while(1)
       
  {  
         Key_scan();
         if(KeyState)
          {
           KeyState=0;
           if(KEY==KEY_OK)
           {
             func_index=table[func_index].enter;
           }
           if(KEY==KEY_DOWN)
           {
             func_index=table[func_index].down;
           }
           if(KEY==KEY_UP)
           {
             func_index=table[func_index].up;
           }  
                   current_operation_index=table[func_index].current_operation;
           (*current_operation_index)();//执行当前操作函数
          
          
//           flag=0;
          }
                
        }
}      

回复

使用道具 举报

ID:739545 发表于 2021-1-5 17:55 | 显示全部楼层
利用标志位进行操作,例如在一级菜单中用标志位F1,按键操作F1中的函数,进入二级菜单设置为F2,按键操作F2中的函数

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:517466 发表于 2021-1-5 18:57 | 显示全部楼层
怎么会有冲突呢?主函数中的按键处理和子函数中的按键处理完全不需要特殊处理啊。他们在各自的函数中正常判断就行。
main() {
    while(1) {
        if (KeyUp按下) {
            延迟20ms,消抖动;
            if (KeyUp按下) {
                while(KeyUp仍处于按下状态) ;
                调用子函数1的处理;
            }
        }
    }
}

void 子函数1() {
        if (KeyUp按下) {
            延迟20ms,消抖动;
            if (KeyUp按下) {
                while(KeyUp仍处于按下状态) ;
                调用子函数2的处理;
            }
}

你看,KeyUp键在主函数和子函数中,互相不影响,是可以正常工作的。
就像windows操作系统里F1是获得帮助,在Windows的应用程序里一样可以使用F1,获得应用程序的帮助。道理是一样的。

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:743654 发表于 2021-1-5 19:20 | 显示全部楼层
lovezjf234 发表于 2021-1-5 17:55
利用标志位进行操作,例如在一级菜单中用标志位F1,按键操作F1中的函数,进入二级菜单设置为F2,按键操作F2 ...

谢谢,这个有想过
回复

使用道具 举报

ID:743654 发表于 2021-1-5 19:25 | 显示全部楼层
本帖最后由 cheney03 于 2021-1-5 19:39 编辑
suncat0504 发表于 2021-1-5 18:57
怎么会有冲突呢?主函数中的按键处理和子函数中的按键处理完全不需要特殊处理啊。他们在各自的函数中正常判 ...

我用的是行列扫描按键,通过键值来判断哪个键按下。若要按键操作子函数,每次都要重新扫描按键,并且要放在while(1)函数中,不然按键操作无效,不知道怎么退出回到主程序中。
回复

使用道具 举报

ID:743654 发表于 2021-1-5 19:26 | 显示全部楼层
按键扫描函数
void Key_scan(void)
{
        char a;
        GPIO_KEY=0x0f;
        if(GPIO_KEY!=0x0f)
        {
                Delay10ms();
                if(GPIO_KEY!=0x0f)
                {
                        KeyState=1;
                        //测试列
                        GPIO_KEY=0X0F;
                        Delay10ms();
                        switch(GPIO_KEY)
                        {
                                case(0X07):        KEY=1;break;
                                case(0X0b):        KEY=2;break;
                                case(0X0d): KEY=3;break;
                                case(0X0e):        KEY=4;break;

                        }
                        //测试行
                        GPIO_KEY=0XF0;
                        Delay10ms();
                        switch(GPIO_KEY)
                        {
                                case(0X70):KEY=KEY;break;
                                case(0Xb0):KEY=KEY+4;break;
                                case(0Xd0):KEY=KEY+8;break;
                                case(0Xe0):KEY=KEY+12;break;

                        }
                        while((a<50)&&(GPIO_KEY!=0xf0))         //检测按键松手检测
                        {
                                Delay10ms();
                                a++;
                        }
                       
                }
        }
}
回复

使用道具 举报

ID:743654 发表于 2021-1-5 19:36 | 显示全部楼层
本帖最后由 cheney03 于 2021-1-5 20:34 编辑

fun1()
{
  unsigned char temp;
  bit flag;
  while(1)        
   {  
          Key_scan();
          if(KeyState)
          {
           KeyState=0;
           if((KEY==KEY_UP)&&(temp<255))
           {
        
           temp++;Datapros(temp);//按一次up键 数值加1,并数据处理显示

           }
           if((KEY==KEY_DOWN)&&(temp>0))
           {
         
            temp--;Datapros(temp);//按一次down键 数值减1,并数据处理显示

           }  
            if((KEY==KEY_OK))
           {
            write24C02(0x01,temp);//数据保持到24C02存储芯片
            这边要怎么操作,才能回到main主函数中

           }
//           flag=0;
           
          }
         
   }
回复

使用道具 举报

ID:213173 发表于 2021-1-6 13:38 | 显示全部楼层
cheney03 发表于 2021-1-5 19:36
fun1()
{
  unsigned char temp;

按键扫描函数只负责输出键值,由按键服务函数根据目前所处工作状态对键值做相应的响应。简单的说,同一个键值在不同的工作状态所执行的任务完全不同,不存在有冲突问题。你在fun1()中不恰当使用while(1) 会玩死的。
回复

使用道具 举报

ID:235954 发表于 2021-1-6 13:48 | 显示全部楼层
按下设置相应的标志位,根据标志位显示不同的内容
回复

使用道具 举报

ID:517466 发表于 2021-1-8 11:12 | 显示全部楼层
cheney03 发表于 2021-1-5 19:25
我用的是行列扫描按键,通过键值来判断哪个键按下。若要按键操作子函数,每次都要重新扫描按键,并且要放 ...

我做的一个简单控制系统中,对键盘有一个默认的设置。比如某些键是作为上下调节数据用的,有的当做“确认”键,有的当做“取消”键。在子函数中的键盘扫描处理中,检测到“确认键”,相当于保存当前设置数据,并退出子函数,返回主函数。如果扫描到“取消键”,表示抛弃当前设置数据,返回主函数。
某个按键,在主程序中可以作为“菜单键”处理,而在子函数中当做“返回上级菜单”、“返回上级父函数”处理,既然程序是你自己编的,怎么定,自由度很大。想统一安排,也可以固定设定某个键为固定功能,比如固定当做“退出当前函数”的按键。
常见的电脑显示器中,一般都有几个按钮。你做程序时 ,完全可以参照显示器按钮的使用方式。道理是一样的。
又比如,在操作系统的资源管理器中,“A”可以用于快速查找打头字母为“A”的文件。在文字编辑软件中,“A”表示输的文字。而在CS游戏中,“A”默认是角色左移。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表