最近有个需求:检测琴键的按键速度。一个琴键有两个轻触开关,检测这两个轻触开关的时差就能实现按键速度。
用GD32F350CPU,50us定时扫描键盘,把按下的按键对应的速度通过USB发出去,裸机代码只做这两件事情。
实际测试扫描键盘的时间不到40us,现在的问题是:当同时按下全部的按键时,有时会扫描不到部分按键。同时按下的按键数比较少时,就不会发生上述问题。
洗耳恭听大家的建议和指导!
代码如下:
void Martrix_KB_Handle(void)
{
uint8 idx;
for(idx=0;idx<Matrix_KB_KeyNum;idx++)
{
switch (Keys[idx].State)
{
case State_NoteOFF:
if ( PRE_NOTE_ON == Keys[idx].Cur_KeyStatus )
{
Keys[idx].State = State_PreNoteON;
}
break;
case State_PreNoteON://Front键先按下,velocity开始计数
Keys[idx].Note_Velocity.u32_velocity++;
if ( NOTE_ON == Keys[idx].Cur_KeyStatus )
{
Keys[idx].State = State_NoteON;
#ifdef JLINK_RTT_DEBUG
SEGGER_RTT_printf(0,"%2d: ON%5d\r\n",idx+1,Keys[idx].Note_Velocity.u32_velocity);
#endif
if(Sys_Flag.Upload_Enable)
{
ON_FIFO.Note_Buffer[ON_FIFO.Idx_IN].num = idx;
ON_FIFO.Note_Buffer[ON_FIFO.Idx_IN].velocity.u32_velocity = Keys[idx].Note_Velocity.u32_velocity;
ON_FIFO.Idx_IN++;
if(ON_FIFO.Idx_IN==Buffer_Size) ON_FIFO.Idx_IN = 0;
}
Keys[idx].Note_Velocity.u32_velocity = 0;
}
else if ( NOTE_OFF == Keys[idx].Cur_KeyStatus ) //按下一半就松开的情况
{
Keys[idx].Note_Velocity.u32_velocity = 0;
Keys[idx].State = State_NoteOFF;
}
break;
case State_NoteON:
if ( PRE_NOTE_OFF == Keys[idx].Cur_KeyStatus )
{
Keys[idx].State = State_PreNoteOFF;
}
break;
case State_PreNoteOFF:
Keys[idx].Note_Velocity.u32_velocity++;
if ( NOTE_OFF == Keys[idx].Cur_KeyStatus )
{
Keys[idx].State = State_NoteOFF;
#ifdef JLINK_RTT_DEBUG
SEGGER_RTT_printf(0,"%2d:OFF%5d\r\n",idx+1,Keys[idx].Note_Velocity.u32_velocity);
#endif
if(Sys_Flag.Upload_Enable)
{
OFF_FIFO.Note_Buffer[OFF_FIFO.Idx_IN].num = idx;
OFF_FIFO.Note_Buffer[OFF_FIFO.Idx_IN].velocity.u32_velocity = Keys[idx].Note_Velocity.u32_velocity;
OFF_FIFO.Idx_IN++;
if(OFF_FIFO.Idx_IN==Buffer_Size) OFF_FIFO.Idx_IN = 0;
}
Keys[idx].Note_Velocity.u32_velocity = 0;
}
break;
default:
break;
}
}
}
void Martrix_KB_Handle(void)
{
uint8 idx;
for(idx=0;idx<Matrix_KB_KeyNum;idx++)
{
switch (Keys[idx].State)
{
case State_NoteOFF:
if ( PRE_NOTE_ON == Keys[idx].Cur_KeyStatus )
{
Keys[idx].State = State_PreNoteON;
}
break;
case State_PreNoteON://Front键先按下,velocity开始计数
Keys[idx].Note_Velocity.u32_velocity++;
if ( NOTE_ON == Keys[idx].Cur_KeyStatus )
{
Keys[idx].State = State_NoteON;
#ifdef JLINK_RTT_DEBUG
SEGGER_RTT_printf(0,"%2d: ON%5d\r\n",idx+1,Keys[idx].Note_Velocity.u32_velocity);
#endif
if(Sys_Flag.Upload_Enable)
{
ON_FIFO.Note_Buffer[ON_FIFO.Idx_IN].num = idx;
ON_FIFO.Note_Buffer[ON_FIFO.Idx_IN].velocity.u32_velocity = Keys[idx].Note_Velocity.u32_velocity;
ON_FIFO.Idx_IN++;
if(ON_FIFO.Idx_IN==Buffer_Size) ON_FIFO.Idx_IN = 0;
}
Keys[idx].Note_Velocity.u32_velocity = 0;
}
else if ( NOTE_OFF == Keys[idx].Cur_KeyStatus ) //按下一半就松开的情况
{
Keys[idx].Note_Velocity.u32_velocity = 0;
Keys[idx].State = State_NoteOFF;
}
break;
case State_NoteON:
if ( PRE_NOTE_OFF == Keys[idx].Cur_KeyStatus )
{
Keys[idx].State = State_PreNoteOFF;
}
break;
case State_PreNoteOFF:
Keys[idx].Note_Velocity.u32_velocity++;
if ( NOTE_OFF == Keys[idx].Cur_KeyStatus )
{
Keys[idx].State = State_NoteOFF;
#ifdef JLINK_RTT_DEBUG
SEGGER_RTT_printf(0,"%2d:OFF%5d\r\n",idx+1,Keys[idx].Note_Velocity.u32_velocity);
#endif
if(Sys_Flag.Upload_Enable)
{
OFF_FIFO.Note_Buffer[OFF_FIFO.Idx_IN].num = idx;
OFF_FIFO.Note_Buffer[OFF_FIFO.Idx_IN].velocity.u32_velocity = Keys[idx].Note_Velocity.u32_velocity;
OFF_FIFO.Idx_IN++;
if(OFF_FIFO.Idx_IN==Buffer_Size) OFF_FIFO.Idx_IN = 0;
}
Keys[idx].Note_Velocity.u32_velocity = 0;
}
break;
default:
break;
}
}
}