|
本人是自学者,一直在学习马来是的第二版的书,但学习的很慢,可能有很多细节的问题自己找不出来,在此请马老师在百忙之中能点拨我一下,在此谢谢!
以下是截取的其中菜单这块的代码,主要是按键和菜单切换这一块。实物测试时发现两个问题,
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[1]);
hz_disp16(2,32,xi);
hz_disp16(2,48,tong);
hz_disp8(4,16,num[2]);
hz_disp16(4,32,kong);
hz_disp16(4,48,zhi2);
hz_disp8(6,16,num[3]);
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; //使能全局中断
}
#pragma interrupt_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_table table[4]=
{
{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[temp_18B20%1000/100]);
case 0:
func_index=0;
break;
case 1:
func_index=table[func_index].up; //向下翻
break;
case 2:
func_index=table[func_index].down; //向上翻
break;
case 3:
func_index=table[func_index].enter; //间隔翻
default:
break;
}
}
current_operation_index=table[func_index].current_operation;
(*current_operation_index)();//执行当前操作函数
//
}
}
}
|
阿莫论坛20周年了!感谢大家的支持与爱护!!
月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!
|