标题: 单片机多级菜单+按键,子函数中有按键如何处理? [打印本页]
作者: cheney03 时间: 2021-1-5 17:32
标题: 单片机多级菜单+按键,子函数中有按键如何处理?
本帖最后由 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;
}
}
}
作者: lovezjf234 时间: 2021-1-5 17:55
利用标志位进行操作,例如在一级菜单中用标志位F1,按键操作F1中的函数,进入二级菜单设置为F2,按键操作F2中的函数
作者: suncat0504 时间: 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,获得应用程序的帮助。道理是一样的。
作者: cheney03 时间: 2021-1-5 19:20
谢谢,这个有想过
作者: cheney03 时间: 2021-1-5 19:25
本帖最后由 cheney03 于 2021-1-5 19:39 编辑
我用的是行列扫描按键,通过键值来判断哪个键按下。若要按键操作子函数,每次都要重新扫描按键,并且要放在while(1)函数中,不然按键操作无效,不知道怎么退出回到主程序中。
作者: cheney03 时间: 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++;
}
}
}
}
作者: cheney03 时间: 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;
}
}
作者: wulin 时间: 2021-1-6 13:38
按键扫描函数只负责输出键值,由按键服务函数根据目前所处工作状态对键值做相应的响应。简单的说,同一个键值在不同的工作状态所执行的任务完全不同,不存在有冲突问题。你在fun1()中不恰当使用while(1) 会玩死的。
作者: 梁廷明 时间: 2021-1-6 13:48
按下设置相应的标志位,根据标志位显示不同的内容
作者: suncat0504 时间: 2021-1-8 11:12
我做的一个简单控制系统中,对键盘有一个默认的设置。比如某些键是作为上下调节数据用的,有的当做“确认”键,有的当做“取消”键。在子函数中的键盘扫描处理中,检测到“确认键”,相当于保存当前设置数据,并退出子函数,返回主函数。如果扫描到“取消键”,表示抛弃当前设置数据,返回主函数。
某个按键,在主程序中可以作为“菜单键”处理,而在子函数中当做“返回上级菜单”、“返回上级父函数”处理,既然程序是你自己编的,怎么定,自由度很大。想统一安排,也可以固定设定某个键为固定功能,比如固定当做“退出当前函数”的按键。
常见的电脑显示器中,一般都有几个按钮。你做程序时 ,完全可以参照显示器按钮的使用方式。道理是一样的。
又比如,在操作系统的资源管理器中,“A”可以用于快速查找打头字母为“A”的文件。在文字编辑软件中,“A”表示输的文字。而在CS游戏中,“A”默认是角色左移。
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |