项目场景:
在STM32F401RET6中使用lvgl库,需要使用外部按键及编码器作为输入设备。
采用裸机编程,采用双缓存加DMAspi的屏幕刷新方式,系统主频84M,屏幕帧率20帧
问题描述
当页面数据刷新量大时,编码器旋转的信号很难被捕捉并执行,旋转了但没有反应
static void encoder_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
static uint32_t last_key = 0;
uint32_t act_key= ECO_Scan();
act_key = 0;
if(act_key != 0)
{
switch(act_key)
{
case 1:
encoder_diff = 1;
break;
case 2:
encoder_diff = -1;
break;
}
last_key = act_key;
}
else
{
encoder_diff =0;
encoder_state = LV_INDEV_STATE_REL;
}
data->state = encoder_state;
data->enc_diff = encoder_diff;
// encoder_diff =0;
}
原因分析:
1、输入设备读取时间设置的太长了导致的,就将时间修改为了1ms,测试之后没有效果。
2、分析可能是数据更新量太大,导致CPU被大量抢占,不能及时采集到编码器信号的输入。将数据更新的代码注释掉后情况得到改善;将系统主频超频后,改善效果明显,但是这不是解决的办法,超频后MCU容易死机。
3、之后发现按键设备的输入好像不受影响,思考了一下,可能是按键按下时长比编码器旋转得到得信号时长长,这可能是导致为什么编码器信号无法被扑捉得根本原因。因为在MCU执行lv_timer_handler();
时消耗了大量时间,导致错过了编码器的读取。
解决方案:
解决办法:将编码器信号采集放在定时器中,设置一个全局变量去存储编码器采集到的信号,在keypad_read
中处理这个全局变量,并将此变量清零。 这样也不用去注册indev_drv_ender
设备了。只用到了keypad设备。
static void keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
旋转编码器扫描:
uint8_t ECO_Scan(void)
{
static uint8_t state,key_A,key_B;
key_A = EC11_A_Now; //读取按键状态
key_B = EC11_B_Now;
if(0 == state) //空闲状态
{
if(0 == key_A) //无需消抖算法
{
state = 1;
}
else if(0 == key_B)
{
state = 2;
}
return 0;
}
else if(1 == state) //A按键先拉低
{
if(0 == key_B)
{
state = 3;
return 1; //正转返回1
}
else if(key_A)
{
state = 0;
return 0;
}
else return 0;
}
else if(2 == state) //B按键先拉低
{
if(0 == key_A)
{
state = 3;
return 2; //反转返回2
}
else if(key_B)
{
state = 0;
return 0;
}
else return 0;
}
else if(3 == state) //等待按键释放
{
if(key_A && key_B) //双键释放,回到状态0
{
state = 0;
}
return 0;
}
else
return 0;
}