Re: 【求助】【TuyaOS】配置按键时程序跑飞
我有一个按键是长按需要判断长按抬起的,这个按键的应用场景是按下后2s执行一个操作,一直执行到按键抬起,期间可能会有几分钟的时间,这个时间说不准
这套按键例程里面也不适用
我有一个按键是长按需要判断长按抬起的,这个按键的应用场景是按下后2s执行一个操作,一直执行到按键抬起,期间可能会有几分钟的时间,这个时间说不准
这套按键例程里面也不适用
joey_nobug 2023年 Dec 27日 15:56你这个定位不对啊,并不是在 init_config() 里啊,你搜索的这个是注释啊。 看前面你的截图,你要关注的是的 PC 寄存器的 0x1FFFD358 这个地址是在哪个函数里,如果没有这个范围可能是跑飞了,要再看 LR 寄存器的值 0x1102CAA9。 这几个值并不一定就直接能搜索到,要根据汇编中函数左侧的地址范围去判断
按照你的说法,我定位PC值定位不到,但是定位到了LR的值,由于我换了一个SDK单独拎出来了,所以这个值发生了变化,但是不影响我找它
sandia 2023年 Dec 27日 17:39joey_nobug 2023年 Dec 27日 15:56你这个定位不对啊,并不是在 init_config() 里啊,你搜索的这个是注释啊。 看前面你的截图,你要关注的是的 PC 寄存器的 0x1FFFD358 这个地址是在哪个函数里,如果没有这个范围可能是跑飞了,要再看 LR 寄存器的值 0x1102CAA9。 这几个值并不一定就直接能搜索到,要根据汇编中函数左侧的地址范围去判断
按照你的说法,我定位PC值定位不到,但是定位到了LR的值,由于我换了一个SDK单独拎出来了,所以这个值发生了变化,但是不影响我找它tal_sw_time.png
这个看起来跟你 app_key.c 中 tal_sw_timer 接口的用法有关系,可以调整下你的 timer 使用,调整下 timer 周期与 触发方式,应该是 中断或者 timer 回调里操作 sw timer 时在一些临界的情况下导致了数组越界,跑飞了。
逻辑的院子 2023年 Dec 27日 15:49功能描述
支持按下防抖,松开防抖,防抖参数可设定
支持单击,多次长按,释放,很容易扩展成双击,三击……依赖条件
外部中断
定时器
设计细节
实现原理
按下按键后,启动一个周期为 t 的定时器
如果按键不松开,依次到达 T1=tcount1, T2=tcount2, T3=t*count3 (release) 时间点
如果按键松开,可能会触发 release0, release1, release2
press0:可能是抖动,抛弃不用
release0:为了消抖和短按的响应及时,count1 设置较小(例如50ms),所以很难触发 release0
press1:按下按键累计时间到达 count1 设置的时间
release1:松开按键的时间处于 count1 和 count2 之间
press2:按下按键累计时间到达 count2 设置的时间
release2:松开按键的时间处于 count2 和 count3 之间
release:按下按键累计时间到达 count3 设置的时间,由于count3是最后一个count,所以即使按键没有释放,也认为按键释放,即按键超时释放
结构体
Code: Select all
typedef struct { UINT32_T count; UINT32_T check_idx; UINT32_T check_record; UINT32_T state; } tal_key_inter_param_t; typedef struct { UINT32_T pin; //按键对应的引脚 tal_key_level_t valid_level; //有效电平 UINT8_T count_len; //按键状态数 UINT32_T count_array[10]; //按键状态时间枚举 tal_key_handler_t handler; //按键结果处理 tal_key_inter_param_t inter; //内部变量,不用赋值 } tal_key_param_t;
使用场景
场景1
Code: Select all
//(1)定义静态全局变量 STATIC tal_key_param_t key_press_param = { .pin = APP_KEY_PIN, .valid_level = TUYA_KEY_LEVEL_LOW, .count_len = 3, .count_array = {5, 300, 500}, .handler = app_key_handler, }; //(2)初始化 tal_key_init(&key_press_param); //(3)启动一个循环定时器(建议10ms),tal_key_timeout_handler() 放到定时器处理函数中 if(!tal_key_timeout_handler(&key_press_param)) { //停止循环定时器 } //(4)实现 tal_key_get_pin_level() // Weak function instance UINT32_T tal_key_get_pin_level(UINT32_T pin) { //实现虚函数 } //(5)在各种 state 中加上自定义处理功能即可 STATIC VOID_T app_key_handler(UINT32_T state) { // TAL_PR_INFO("Key state: %d", state); switch(state) { //Short press case 1: { } break; //Long press case 2: { } break; //Long long press timeout case 3: { } break; //Short press release case 5: { } break; //Long press release case 6: { } break; default: { } break; } }
仔细看一下这个教程,你的这个需求
“我有一个按键是长按需要判断长按抬起的,这个按键的应用场景是按下后2s执行一个操作,一直执行到按键抬起,期间可能会有几分钟的时间,这个时间说不准
这套按键例程里面也不适用”
已经满足了
joey_nobug 2023年 Dec 27日 17:52sandia 2023年 Dec 27日 17:39joey_nobug 2023年 Dec 27日 15:56你这个定位不对啊,并不是在 init_config() 里啊,你搜索的这个是注释啊。 看前面你的截图,你要关注的是的 PC 寄存器的 0x1FFFD358 这个地址是在哪个函数里,如果没有这个范围可能是跑飞了,要再看 LR 寄存器的值 0x1102CAA9。 这几个值并不一定就直接能搜索到,要根据汇编中函数左侧的地址范围去判断
按照你的说法,我定位PC值定位不到,但是定位到了LR的值,由于我换了一个SDK单独拎出来了,所以这个值发生了变化,但是不影响我找它tal_sw_time.png
这个看起来跟你 app_key.c 中 tal_sw_timer 接口的用法有关系,可以调整下你的 timer 使用,调整下 timer 周期与 触发方式,应该是 中断或者 timer 回调里操作 sw timer 时在一些临界的情况下导致了数组越界,跑飞了。
我注意到,特别是在时间为33和69的时候,按按键就会跑飞
问题是我这代码也没几行,没发现哪里有问题啊?
逻辑的院子 2023年 Dec 27日 18:03逻辑的院子 2023年 Dec 27日 15:49功能描述
支持按下防抖,松开防抖,防抖参数可设定
支持单击,多次长按,释放,很容易扩展成双击,三击……依赖条件
外部中断
定时器
设计细节
实现原理
按下按键后,启动一个周期为 t 的定时器
如果按键不松开,依次到达 T1=tcount1, T2=tcount2, T3=t*count3 (release) 时间点
如果按键松开,可能会触发 release0, release1, release2
press0:可能是抖动,抛弃不用
release0:为了消抖和短按的响应及时,count1 设置较小(例如50ms),所以很难触发 release0
press1:按下按键累计时间到达 count1 设置的时间
release1:松开按键的时间处于 count1 和 count2 之间
press2:按下按键累计时间到达 count2 设置的时间
release2:松开按键的时间处于 count2 和 count3 之间
release:按下按键累计时间到达 count3 设置的时间,由于count3是最后一个count,所以即使按键没有释放,也认为按键释放,即按键超时释放
结构体
Code: Select all
typedef struct { UINT32_T count; UINT32_T check_idx; UINT32_T check_record; UINT32_T state; } tal_key_inter_param_t; typedef struct { UINT32_T pin; //按键对应的引脚 tal_key_level_t valid_level; //有效电平 UINT8_T count_len; //按键状态数 UINT32_T count_array[10]; //按键状态时间枚举 tal_key_handler_t handler; //按键结果处理 tal_key_inter_param_t inter; //内部变量,不用赋值 } tal_key_param_t;
使用场景
场景1
Code: Select all
//(1)定义静态全局变量 STATIC tal_key_param_t key_press_param = { .pin = APP_KEY_PIN, .valid_level = TUYA_KEY_LEVEL_LOW, .count_len = 3, .count_array = {5, 300, 500}, .handler = app_key_handler, }; //(2)初始化 tal_key_init(&key_press_param); //(3)启动一个循环定时器(建议10ms),tal_key_timeout_handler() 放到定时器处理函数中 if(!tal_key_timeout_handler(&key_press_param)) { //停止循环定时器 } //(4)实现 tal_key_get_pin_level() // Weak function instance UINT32_T tal_key_get_pin_level(UINT32_T pin) { //实现虚函数 } //(5)在各种 state 中加上自定义处理功能即可 STATIC VOID_T app_key_handler(UINT32_T state) { // TAL_PR_INFO("Key state: %d", state); switch(state) { //Short press case 1: { } break; //Long press case 2: { } break; //Long long press timeout case 3: { } break; //Short press release case 5: { } break; //Long press release case 6: { } break; default: { } break; } }
仔细看一下这个教程,你的这个需求
“我有一个按键是长按需要判断长按抬起的,这个按键的应用场景是按下后2s执行一个操作,一直执行到按键抬起,期间可能会有几分钟的时间,这个时间说不准
这套按键例程里面也不适用”
已经满足了
我需要判断抬起后的状态,这个例程中短按抬起后的状态值5经过了1s多才触发,能不能修改成即时触发?
count_array对应的三个值就是count1、count2、count3的时间,可以调整的
调整这三个时间只是调整短按长按的触发时间,例如第一个5是消抖时间,按下按键之后大于5会直接触发state=1,如果按下的时间大于第二个值300的话,就会判断为长按,触发state=2,如果按下的时间大于第三个值500就判断为长按超时释放触发state=3;
但是短按释放跟长按释放的state值应该为5,6。而我在实际的测试中,无论修改哪个值,触发释放的时间都是比实际的时间长1s以上,大概在1200ms左右;
以下是我实际操作的反馈打印log,我每次按下按键都是立即松开的,而state=5这个反馈是过了1s+才出现
我实测了下并不会出现您描述的这种现象,如图所示:
建议您检查下硬件,看看按键旁边是否存在大电容,大电容会影响电平变化时间
我用的是PHY622X_V1.8的开发板