请教马老师一个菜单中状态转换问题,附代码,先谢谢了
本人是自学者,一直在学习马来是的第二版的书,但学习的很慢,可能有很多细节的问题自己找不出来,在此请马老师在百忙之中能点拨我一下,在此谢谢!以下是截取的其中菜单这块的代码,主要是按键和菜单切换这一块。实物测试时发现两个问题,
1.按键只有在某种情况下才有效(每次按下开发板上的电源供电按键后键盘接口PORTB会出现不同值,硬件上外围什么都没接),只有在电源按下后PORTB为0x7f时,再去按按键才有用。
2.再按键能使用时通过上下键(或跳键)切换显示状态,当执行到fun3()时会立马自动跳到fun1(),此后按键也失效;但只要不按到fun3,在fun0,fun1和fun2中来回切换显示和按键就没有问题。
另外当fun0,fun1,fun2和fun3中减少一些显示内容时(按键有效的情况下),菜单中4个状态切换没有发现有问题。
void fun0
(void)//菜单
{
LCD12864_init();
if(frist_clr12864==0)//只在第一次进入显示时清屏,不能一直清屏,会出现闪烁
LCD12864_CLR();
frist_clr12864=1;
LCD12864_CS2_CLR;
LCD12864_CS1_SET;
hz_disp16(0,48,iac);
hz_disp8(2,16,num);
hz_disp16(2,32,xi);
hz_disp16(2,48,tong);
hz_disp8(4,16,num);
hz_disp16(4,32,kong);
hz_disp16(4,48,zhi2);
hz_disp8(6,16,num);
hz_disp16(6,32,cha);
hz_disp16(6,48,xun);
LCD12864_CS1_CLR;
LCD12864_CS2_SET;
hz_disp16(0,0,nad);
hz_disp16(2,0,she);
hz_disp16(2,16,zhi);
hz_disp16(4,0,shi);
hz_disp16(4,16,jian);
hz_disp16(6,0,wen);
hz_disp16(6,16,du);
void fun1(void)
.。。。。。。。。。。。。。
void fun2(void)
.。。。。。。。。。。。。。
void fun3(void)
.。。。。。。。。。。。。。
}/***********下部分为矩阵按键程序**********/
#define key_DDR DDRB
#define key_input_PORT PORTB
#define key_input_PIN PINB
#define No_key 255
#define k1_1 0
#define k1_2 1
#define k1_3 2
#define k1_4 3
#define k2_1 4
#define k2_2 5
#define k2_3 6
#define k2_4 7
#define k3_1 8
#define k3_2 9
#define k3_3 10
#define k3_4 11
#define k4_1 12
#define k4_2 13
#define k4_3 14
#define k4_4 15
#define key_mask 0b00001111
uchar read_keyboard(void)
{
static uchar key_state=0,key_value,key_line,add=0;
uchar key_return=No_key,i;
key_DDR = 0xf0; //高位输出低位输入
key_input_PORT = 0x00; //先清零
switch(key_state)
{
case 0:
key_line=0b00010000;
for(i=1;i<=4;i++)
{
key_input_PORT=~key_line;
key_input_PORT=~key_line;//此处一定要写两次,由写到读需要时间
key_value=key_mask&key_input_PIN;
if(key_value==key_mask)//读出这一行(或列)没有按键按下
key_line<<=1;
else
{
key_state++;
break;
}
}
break;
case 1:
if(key_value==(key_mask&key_input_PIN))//读出低四位的0
{
switch(key_line|key_value)//将高位的1加上去
{
case 0b00011110://高位有1,低位有0表示有键按下
add++;
if(add>=2)//去抖动后开始每10ms读键值,连读5次都不变就认为此键按下
{
key_return=k1_1;
add=0;
}
break;
case 0b00011101:
add++;
if(add>=2)
{
key_return=k1_2;
add=0;
}
break;
case 0b00011011:
add++;
if(add>=2)
{
key_return=k1_3;
add=0;
}
break;
case 0b00010111:
add++;
if(add>=2)
{
key_return=k1_4;
add=0;
}
break;
case 0b00101110:
add++;
if(add>=2)//去抖动后开始每10ms读键值,连读200次都不变就认为此键按下
{
key_return=k2_1;
add=0;
}
break;
case 0b00101101:
add++;
if(add>=2)
{
key_return=k2_2;
add=0;
}
break;
case 0b00101011:
add++;
if(add>=2)
{
key_return=k2_3;
add=0;
}
break;
case 0b00100111:
add++;
if(add>=2)
{
key_return=k2_4;
add=0;
}
break;
case 0b01001110:
add++;
if(add>=2)
{
key_return=k3_1;
add=0;
}
break;
case 0b01001101:
add++;
if(add>=2)
{
key_return=k3_2;
add=0;
}
break;
case 0b01001011:
add++;
if(add>=2)
{
key_return=k3_3;
add=0;
}
break;
case 0b01000111:
add++;
if(add>=2)
{
key_return=k3_4;
add=0;
}
break;
case 0b10001110:
add++;
if(add>=2)
{
key_return=k4_1;
add=0;
}
break;
case 0b10001101:
add++;
if(add>=2)
{
key_return=k4_2;
add=0;
}
break;
case 0b10001011:
add++;
if(add>=2)
{
key_return=k4_3;
add=0;
}
break;
case 0b10000111:
add++;
if(add>=2)
{
key_return=k4_4;
add=0;
}
break;
}
if(add==0)
key_state=2;
}
else
key_state=0;
break;
case 2:
key_input_PORT=0b00001111;
key_input_PORT=0b00001111;//一定要写两次才能读
if((key_mask&key_input_PIN)==key_mask)
key_state=0;//按键释放了
break;
default:break;
}
return key_return;
}
int0_isr(void)//此处10ms
{
TCCR0=0x0B; // T/C0工作于CTC模式,64分频,
//定时器频率 = 1M/64 = 15.625KHz
TCNT0=0x00;
OCR0=0x9B; //定时时间0x9B==155,(155+1)/15.625=5ms
TIMSK=0x02; //允许比较匹配中断
SREG=0x80; //使能全局中断
}
#pragmainterrupt_handler t0_comp:20
void t0_comp(void)//中断一次10ms
{
time10msok=1;
//time10ms++;
// if(time10ms==50)
// {
///time10ms=0;
//time1s=1;
// }
}
typedef struct
{
uchar current;
uchar up;//
uchar down;//
uchar enter;
void (*current_operation)();
} key_table;
key_tabletable=
{
{0,3,1,2,(*fun0)},//按down to 1
{1,0,2,3,(*fun1)},//
{2,1,3,0,(*fun2)},//
{3,2,0,1,(*fun3)},//
};
void main(void)
{
uint temp_18B20;//
uchar keep=0,func_index=0;
int0_isr();
LCD12864_init();
ds1302_init();
ds1302_write_time();//写入时间初始值
while(1)
{
if(time10msok==1)
{
time10msok=0;
key_num=read_keyboard();
if(key_num!=255) //此句一定要,因为按键只出现唯一的一次按键按下的值
{
key_num_lock=key_num;//此处锁定取值,
frist_clr12864=0;//有按键按下就清除以前显示内容,准备显示本次内容
// ds1302_read_time(); //读时间值
//此处目的就是让12864写之前的清屏,在没有按键按下的时候不清屏
//清屏显示一直循环会看的屏上的字在显示
//}
switch(key_num_lock)
{
// hz_disp8(0,35,num);
case 0:
func_index=0;
break;
case 1:
func_index=table.up; //向下翻
break;
case 2:
func_index=table.down; //向上翻
break;
case 3:
func_index=table.enter; //间隔翻
default:
break;
}
}
current_operation_index=table.current_operation;
(*current_operation_index)();//执行当前操作函数
//
}
}
}
楼主这连接发三个帖子,莫老大的规则里面说着这个!楼主看看
怎么取消啊
怎么删除啊,没注意,都发来三个一样的了 key_tabletable=
{
{0,3,1,2,(*fun0)},//按down to 1
{1,0,2,3,(*fun1)},//
{2,1,3,0,(*fun2)},//
{3,2,0,1,(*fun3)},//
};
对你这段比较感兴趣。。能否解释一下。谢谢 定义结构体,每一行是一个状态一个整体,根据结构体定义的每行第一个数字是当前状态号,第二个数字是在按下up后转入的状态,三四依此类推,最后是这一行状态的执行函数。这是前人的智慧 liuxiaohui17 发表于 2014-12-20 09:06
定义结构体,每一行是一个状态一个整体,根据结构体定义的每行第一个数字是当前状态号,第二个数字是在按下 ...
1、 这个函数指针没见你定义呀 current_operation_index
他是不是这么定义的 void(* current_operation_index)(void)
2、
current_operation_index=table.current_operation;
(*current_operation_index)();//执行当前操作函数
这行的代码是不是也可以这么写
table.current_operation();
指针定义是7楼这样的,我只截取了部分的代码,那行没截上去。结构体查询成员时不能table.current_operation();这样写,因为current_operation是结构体的成员,只是这个成员是个指针变量。“.”是成员运算符,后面跟的必须是成员,current_operation()不是定义的那个结构体的成员,
typedef struct
{
uchar current;
uchar up;//
uchar down;//
uchar enter;
void (*current_operation)();
} key_table;
这是定义了一个current_operation指针变量(不是定义了一个函数),只不过这个变量是指向一个函数的。
鄙人愚见,敬请参考。 liuxiaohui17 发表于 2014-12-20 11:47
指针定义是7楼这样的,我只截取了部分的代码,那行没截上去。结构体查询成员时不能table.curre ...
1、 try it
2 、我见过这样的用法。所以才提出了这个问题。。
3 、对于ANICC标准 (*funcpointer)() 和 (funcpointer) 都是认同的。 谢谢你啊。试了,那样出现dug,我用的ICCAVR,说非法的指针类型。 试过了,出现bug,我用的ICCAVR,说非法的类型。谢谢你啊 仔细看了9楼的文档,table.current_operation();这样这样直接执行函数是可以的,这样更好,学习了{:lol:},。但问题不是出在这,还得慢慢找啊。
页:
[1]