amoBBS 阿莫电子论坛

 找回密码
 注册
搜索
bottom↓
查看: 898|回复: 3

请教马老师一个菜单中状态转换问题,附代码,先谢谢了

[复制链接]
发表于 2014-12-19 22:05:26 | 显示全部楼层 |阅读模式
本人是自学者,一直在学习马来是的第二版的书,但学习的很慢,可能有很多细节的问题自己找不出来,在此请马老师在百忙之中能点拨我一下,在此谢谢!
以下是截取的其中菜单这块的代码,主要是按键和菜单切换这一块。实物测试时发现两个问题,
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)();//执行当前操作函数
                //
    }
}
}


发表于 2014-12-19 22:31:42 | 显示全部楼层
重复多次发帖,先后间隔不到一分钟,也许是失误吧
 楼主| 发表于 2014-12-19 22:14:15 | 显示全部楼层
是想不明白,越看越看不出问题
发表于 2014-12-19 22:08:12 | 显示全部楼层
你是失误还是故意呢
友情提示:标题不合格、重复发帖,将会被封锁ID。详情请参考:论坛通告:封锁ID、获得注册邀请码、恢复被封ID、投诉必读
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|阿莫电子论坛(原ourAVR/ourDEV) ( 公安备案:44190002001997(交互式论坛) 工信部备案:粤ICP备09047143号 )

GMT+8, 2019-12-15 02:01

阿莫电子论坛, 原"中国电子开发网"

© 2004-2018 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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