关于STemwin中,外部实体按键操作Spinbox控件(fishing_2)

    背景:参加了一个比赛,然后我们老师要求用STemwin做个界面,其中就涉及到外部按键要操作控件,主要有两个输入参数,我就用了两个Spinbox控件做的显示,两个外部按键进行控制,一个是Table键,一个增加键。Table键用来在两个Spinbox之间进行切换,增加键用来改变数值,当然,在增加键的时候,会在Spinbox控件下的回调函数设置一个极限值,到达极限值就置0。

    之前遇到的问题是,按照安富莱的这方面的参考资料,定时去读取按键是否按下,如果按下就压入键值,再在定时器回调函数里获取键值,根据键值发送不同的消息,界面做出不同的反应。我在界面实时刷新的时候,也就是1s刷新一次界面,这个是可以用的,然后老师觉得不要1s刷新一次,没有太大意义,就只刷一次就行,我就改程序,按键这块没动,结果改完后,按键就不能正常响应了,不知道是怎么回事,然后我感觉应该是按键用的定时器cbtimer那里有问题,于是我就打算不用定时去扫描按键的想法,想做成中断的方式,按键按下,产生中断,然后发送消息。

    接下来,就是重点了。改成中断后,在中断里压入键值,然后在main函数最后的while(1)里面,检测键值是否变化,如果有变化就用GUI_SendKeyMsg发送相应的消息,主要代码如下:

//增加建中断服务函数
void EXTI1_IRQHandler(void) 
{
    EXTI_ClearITPendingBit(EXTI_Line1);
    //delay_ms(10); 
    delay_us(10000);
    
    if(PA1==0)
    {    
        bsp_PutKey((uint8_t)(4));  //压入键值     
        //CHANGE_NUM();
    }
}

//Table键中断服务函数
void EXTI0_IRQHandler(void) 
{
    EXTI_ClearITPendingBit(EXTI_Line0);
    //delay_ms(10);  //
    delay_us(10000);
    
    if(PA0==0)
    {
        bsp_PutKey(1);  //压入键值
        //CHANGE_AIM();
    }
}


while(1)里面检测键值是否变化:

 while(1)

 {
    keycode(bsp_GetKey());               
  }

检测键值是否变化函数:

void keycode(int key_code)
{
    uint8_t  ucKeyCode;        
    ucKeyCode = key_code;//bsp_GetKey()
    if(ucKeyCode != KEY_NONE)
    {
        switch (ucKeyCode)
        {                
            case KEY_DOWN_K1:                           
                
                GUI_SendKeyMsg(GUI_KEY_TAB, 1);        
                GUI_Delay(5);            
                break;
                        
            case KEY_DOWN_K2:         

                GUI_SendKeyMsg(GUI_KEY_UP, 1);     
                GUI_Delay(5);                        
                break;
                        
            default:
                    break;        
            }            
        }
}
 

压入键值函数:

void bsp_PutKey(uint8_t _KeyCode)
{
    s_tKey.Buf[s_tKey.Write] = _KeyCode;

    if (++s_tKey.Write  >= KEY_FIFO_SIZE)
    {
        s_tKey.Write = 0;
    }
}

获取键值函数:

uint8_t bsp_GetKey(void)
{
    uint8_t ret;

    if (s_tKey.Read == s_tKey.Write)
    {
        return KEY_NONE;
    }
    else
    {
        ret = s_tKey.Buf[s_tKey.Read];

        if (++s_tKey.Read >= KEY_FIFO_SIZE)
        {
            s_tKey.Read = 0;
        }
        return ret;
    }
}
 

typedef enum
{
    KEY_NONE = 0,              /* 0 表示按键事件 */

    KEY_1_DOWN,                /*1键按下 */
    KEY_1_UP,                      /* 1键弹起*/
    KEY_1_LONG,                /* 1键长按*/

    KEY_2_DOWN,                /* 2键按下 */
    KEY_2_UP,                       /* 2键弹起*/
    KEY_2_LONG                  /* 2键长按 */
}KEY_ENUM;

 

       按照上面的逻辑以及代码来,按理说应该是没问题的,结果下到板子里去没反应,后来我在线调试一步一步的调试,发现中断是产生了的,键值也压入了,也检测到了键值变化,然后也发送了消息GUI_SendKeyMsg(GUI_KEY_TAB, 1); ,但显示屏上就是没反应,后来我灵机一现,感觉应该是没有界面重绘,也就是说界面是知道更改的,但是没有画出来,于是我就“自作主张“”的在发送消息后面加了一个界面重绘的命令,就是红色部分,然后就能正常工作了!!这个问题之前困扰我三四天,一直想不明白是哪儿出了问题,然后找遍了网上,各大教程都没有这方面的说明,都是利用emwin提供的定时器,在cbtimer的回调函数里面,定时去扫描键值,现在终于可以不用那个了,直接用中断了,其实也不叫中断,就伪中断吧。

       这其实也解释了,为什么用emwin 的cbtimer可以刷新,估计在cbtimer的哪个地方,是有一条刷新界面的指令的。感觉这个GUI_Delay很好用啊,哈哈 = =,当然这也是因为界面比较简单,可以刷一下,但是界面做的复杂的话,可能会比较麻烦。

        最后,总结下,现在网上关于实体按键操作控件的方式大部分都是利用emwin提供的Timer的回调函数cbtimer定时去查询键值是否变化,然后做相应的动作,这个的确能用起来,但是这个定时搞得我对程序的时序有点搞不明白= =,比如是在程序的什么时候定时去查询啊,会不会妨碍主程序,以及中断来了打断会怎样?等等。然后,这里我想分享的就是,我不用定时查询的改用“伪中断”的方式去操作控件,按键按下,中断里压入键值,while里面检测键值是否变化,然后发送消息,再加个GUI_Delay就能同样完成实体按键操作控件。

参考资料:安富莱_STM32-V6开发板emWin教程(V2.0)

                  安富莱_STM32-V5开发板_用户手册(V2.0) 

                  emWIN5.12中文手册

 

欢迎批评指正交流!

 

ps:隔了半个月才想着写下,哎,自己好懒啊  = =

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值