本帖最后由 eagle_avr 于 2019-7-26 14:39 编辑
最近有个需求:检测琴键的按键速度。一个琴键有两个轻触开关,检测这两个轻触开关的时差就能实现按键速度。
用GD32F350CPU,50us定时扫描键盘,把按下的按键对应的速度通过USB发出去,裸机代码只做这两件事情。
实际测试扫描键盘的时间不到40us,现在的问题是:当同时按下全部的按键时,有时会扫描不到部分按键。同时按下的按键数比较少时,就不会发生上述问题。
代码如下:
- void Scan_MatrixKB ( void )
- {
- uint8 idx,temp;
- uint8 i=0,shift_num=0;
- uint64 Row_data=0;
-
- FrontKeyStu = BackKeyStu = 0;
-
- // Back依次输出低电平,读取Row的值
- for ( idx=0; idx<B_ColumnNum; idx++ )
- {
- GPIO_BC(Col_Port) = Back[idx].Column_GPIO; // 拉低Column
-
- for(temp=0;temp<0x10;temp++);//延时一会儿
- //读取Row
- if(Back[idx].RowsInColumn == 4)
- Row_data = (uint64)GET_BITS(GPIO_ISTAT(Row_Port),Back[idx].RowsInColumn,7);
- else
- Row_data = (uint64)GET_BITS(GPIO_ISTAT(Row_Port),0,Back[idx].RowsInColumn-1 );
-
- // 处理数据
- Row_data = (uint64)Row_data<<shift_num;
-
- BackKeyStu += Row_data;
-
- shift_num += Front[idx].RowsInColumn;
-
- for(;i<shift_num;i++)
- {
- Keys[i].Cur_KeyStatus = (0x01&(BackKeyStu>>i))<<1;
- }
-
- GPIO_BOP(Col_Port) = Back[idx].Column_GPIO; // 恢复高电平
-
- }
- shift_num = i = 0;
-
- for ( idx=0; idx<F_ColumnNum; idx++ )
- {
- GPIO_BC(Col_Port) = Front[idx].Column_GPIO; //输出低电平
-
- for(temp=0;temp<0x10;temp++);// 延时一段时间
-
- if(Back[idx].RowsInColumn==4)
- Row_data = GET_BITS(GPIO_ISTAT(Row_Port),Front[idx].RowsInColumn,7 );// 四个键分别接Row4、Row5、Row6、Row7
-
- else
- Row_data = GET_BITS(GPIO_ISTAT(Row_Port),0,Front[idx].RowsInColumn-1 );
-
- // 处理数据
- Row_data = (uint64)Row_data<<shift_num;
-
- FrontKeyStu += Row_data;
-
- shift_num += Front[idx].RowsInColumn;
-
- for(;i<shift_num;i++)
- {
- Keys[i].Cur_KeyStatus |= 0x01&(FrontKeyStu>>i);
- }
- GPIO_BOP (Col_Port) = Front[idx].Column_GPIO; //恢复高电平
-
- }
-
- }
复制代码
- 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
",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
",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;
- }
-
- }
- }
复制代码
兄弟们帮我看看,能不能找到原因。
记得以前弄STM8时就碰到过,慢速的IO要稍稍延时几个空操作
如果是我,我不会一个一个去检测按键。而是,软硬结合,如果是矩阵按键的话,Col用PA端口,Line用PB端口,不熟悉GD32,以STM32为例,PA和PB端口为16bit。PA全部输出High,读取PB,之后PB全部High输出读取PA。这样两步就可以检测所有按键。
以上读写PA、PB用InData和OutData寄存器,不使用bit操作。
一周热门 更多>