王昱顺
发表于 2024-12-10 14:23:05
vb2002 发表于 2024-12-10 14:13
或者说,长按和双击翻转P20 P21
短按在哪里执行哦?
双击是必定触发一次单击的,逻辑上就是这样。
所以我没放一块,单击和长按是可以共存的
vb2002
发表于 2024-12-10 14:25:19
王昱顺 发表于 2024-12-10 14:23
双击是必定触发一次单击的,逻辑上就是这样。
所以我没放一块,单击和长按是可以共存的 ...
难怪我在上面打印一个变量
每次都会触发单击
我好好琢磨一下先吧.
不懂再来请教
bkeuqoaq
发表于 2024-12-10 14:38:55
主循环对time的访问没有满足原子操作,存在BUG
bkeuqoaq
发表于 2024-12-10 14:43:04
这个双击不严谨,第一次长按多久也算是一击,一般双击必须是快速的双击
vb2002
发表于 2024-12-10 14:55:12
bkeuqoaq 发表于 2024-12-10 14:43
这个双击不严谨,第一次长按多久也算是一击,一般双击必须是快速的双击
有好的代码分享一下吗?
只要长按单击就行
bkeuqoaq
发表于 2024-12-10 15:24:27
vb2002 发表于 2024-12-10 14:55
有好的代码分享一下吗?
只要长按单击就行
这是真正项目使用的代码,部分宏定义没有列出,意思一看就明白
enum{
//不可修改
KEY1 = 0x0001,
KEY2 = 0x0002,
KEY3 = 0x0004,
//不可修改
KEY_EVENT__SDOWN = 0x0100, //短按按下
KEY_EVENT__LDOWN = 0x0200, //长按按下
KEY_EVENT__CDOWN = 0x0400, //连按按下
KEY_EVENT__SUP = 0x0800, //短按松开
KEY_EVENT__LUP = 0x1000, //长按松开
KEY_EVENT__CUP = 0x2000, //连按松开
//不可修改
KEY_NUM__ANY = (KEY1+KEY2+KEY3),
KEY_EVENT__DOWN = KEY_EVENT__SDOWN+KEY_EVENT__LDOWN+KEY_EVENT__CDOWN,
KEY_EVENT__UP = KEY_EVENT__SUP+KEY_EVENT__LUP+KEY_EVENT__CUP,
KEY_EVENT__ALL = KEY_EVENT__DOWN+KEY_EVENT__UP,
//_______________________________________
//指定按键事件
KEY1_SDOWN = (KEY1+KEY_EVENT__SDOWN),
KEY1_SUP = (KEY1+KEY_EVENT__SUP),
KEY1_LDOWN = (KEY1+KEY_EVENT__LDOWN),
KEY1_LUP = (KEY1+KEY_EVENT__LUP),
KEY2_SDOWN = (KEY2+KEY_EVENT__SDOWN),
KEY2_LDOWN = (KEY2+KEY_EVENT__LDOWN),
KEY2_LUP = (KEY2+KEY_EVENT__LUP),
KEY2_CDOWN = (KEY2+KEY_EVENT__CDOWN),
KEY2_SUP = (KEY2+KEY_EVENT__SUP),
KEY3_SDOWN = (KEY3+KEY_EVENT__SDOWN),
KEY3_LDOWN = (KEY3+KEY_EVENT__LDOWN),
KEY3_LUP = (KEY3+KEY_EVENT__LUP),
KEY3_SUP = (KEY3+KEY_EVENT__SUP),
KEY3_CDOWN = (KEY3+KEY_EVENT__CDOWN),
};
#define MS /10u
//请循环调用,建议10MS调用周期
void KEY_Scan(void)
{
Key_Typedef* pKey = &s_stKey;
u32 ulNum=0;
u32 ulTmpEvent = 0;
u32 ulGpio = 0;
pKey->usEventEx = 0;
if (!GPIO_VAL_GET(GPIO_S1))
{
ulGpio = KEY1;
ulNum++;
}
if (GPIO_VAL_GET(GPIO_S2)) //高电平有效
{
ulGpio = KEY2;
ulNum++;
}
if (!GPIO_VAL_GET(GPIO_S3))
{
ulGpio = KEY3;
ulNum++;
}
if (ulNum == 0)
{
//松开
u16 usTmp = pKey->usDeb;
pKey->usDeb = 0;
if (usTmp != 0xffff)
{
if (usTmp > 3000MS)
{
//此项目不需要此按键事件
//ulTmpEvent = pKey->ucBkpGpio + KEY_EVENT__CUP;
}
else
if (usTmp > 1000MS)
{
ulTmpEvent = pKey->usBkpGpio + KEY_EVENT__LUP;
}
else
if (usTmp > 50MS)
{
ulTmpEvent = pKey->usBkpGpio + KEY_EVENT__SUP;
}
}
}
else
if (ulNum > 1)
{
KEY_Hold();
return;
}
else
if (ulNum == 1)
{
//正常按下
if (pKey->usDeb != 0xffff)
{
pKey->usDeb++;
if (pKey->usDeb == 40MS)
{
ulTmpEvent = ulGpio + KEY_EVENT__SDOWN;
}
else
if (pKey->usDeb == 1000MS)
{
ulTmpEvent = ulGpio + KEY_EVENT__LDOWN;
}
else
{
bit bRepeat = (pKey->usDeb >= (3000MS+1000MS/5))?1:0;
if (bRepeat || pKey->usDeb == 3000MS)
{
ulTmpEvent = ulGpio + KEY_EVENT__CDOWN;
if (bRepeat)
{
pKey->usDeb = 3000MS + 1;
}
}
}
}
}
if (ulTmpEvent)
{
pKey->usBkpGpio = ulTmpEvent & KEY_NUM__ANY;
pKey->usEventEx = ulTmpEvent;
}
}
u32 KEY_GetEx(void)
{
return s_stKey.usEventEx;
}
//判断按键的代码必须每个循环周期调用,以确保同步
if (KEY_GetEx() == KEY1_SUP)
{
MF_Set2New(MF_INDEX__MENU0);
}
bkeuqoaq
发表于 2024-12-10 15:32:02
void KEY_Hold(void)
{
s_stKey.usBkpGpio = 0;
s_stKey.usDeb = 0xffff;
}
bkeuqoaq
发表于 2024-12-10 15:36:12
以上代码实际项目使用ARM-M0内核
vb2002
发表于 2024-12-10 16:46:34
弄好了. 仅保留单击和长按, 运行完美,可以唤醒掉电模式
if (t_10ms)
{
t_10ms = 0; // 10ms同步
val = Get_Key();
down = val & (val ^ old);
up = old & (val ^ old);
old = val;
if (down == 1)
{
l_key = time;
// if (time - d_key < 200)
// P54 = ~P54;
}
if (up == 1)
{
if (time - l_key > 100)
P55 = ~P55;
else
// d_key = time;
P54 = ~P54;
}
}
vb2002
发表于 2024-12-10 17:05:49
bkeuqoaq 发表于 2024-12-10 15:24
这是真正项目使用的代码,部分宏定义没有列出,意思一看就明白
enum{
c语言底子太差了. 这个我完全看不懂