50us内扫描74个按键的问题

2019-12-11 18:17发布

本帖最后由 eagle_avr 于 2019-7-26 14:39 编辑

最近有个需求:检测琴键的按键速度。一个琴键有两个轻触开关,检测这两个轻触开关的时差就能实现按键速度。

用GD32F350CPU,50us定时扫描键盘,把按下的按键对应的速度通过USB发出去,裸机代码只做这两件事情。

实际测试扫描键盘的时间不到40us,现在的问题是:当同时按下全部的按键时,有时会扫描不到部分按键。同时按下的按键数比较少时,就不会发生上述问题。

代码如下:

  1. void Scan_MatrixKB ( void )
  2. {
  3.         uint8 idx,temp;
  4.         uint8 i=0,shift_num=0;
  5.         uint64 Row_data=0;
  6.        
  7.         FrontKeyStu = BackKeyStu = 0;
  8.        
  9.         // Back依次输出低电平,读取Row的值
  10.         for ( idx=0; idx<B_ColumnNum; idx++ )
  11.         {               
  12.                 GPIO_BC(Col_Port) = Back[idx].Column_GPIO; // 拉低Column
  13.                
  14.                 for(temp=0;temp<0x10;temp++);//延时一会儿

  15.                 //读取Row
  16.                 if(Back[idx].RowsInColumn == 4)
  17.                         Row_data = (uint64)GET_BITS(GPIO_ISTAT(Row_Port),Back[idx].RowsInColumn,7);
  18.                 else
  19.                         Row_data = (uint64)GET_BITS(GPIO_ISTAT(Row_Port),0,Back[idx].RowsInColumn-1 );

  20.                
  21.                 // 处理数据
  22.                 Row_data = (uint64)Row_data<<shift_num;
  23.                
  24.                 BackKeyStu += Row_data;               
  25.                
  26.                 shift_num += Front[idx].RowsInColumn;               
  27.                
  28.                 for(;i<shift_num;i++)
  29.                 {
  30.                         Keys[i].Cur_KeyStatus = (0x01&(BackKeyStu>>i))<<1;
  31.                 }
  32.                
  33.                 GPIO_BOP(Col_Port) = Back[idx].Column_GPIO; // 恢复高电平
  34.                
  35.         }
  36.         shift_num = i = 0;
  37.        
  38.         for ( idx=0; idx<F_ColumnNum; idx++ )
  39.         {
  40.                 GPIO_BC(Col_Port) = Front[idx].Column_GPIO; //输出低电平
  41.                
  42.                 for(temp=0;temp<0x10;temp++);// 延时一段时间
  43.                
  44.                 if(Back[idx].RowsInColumn==4)
  45.                         Row_data = GET_BITS(GPIO_ISTAT(Row_Port),Front[idx].RowsInColumn,7 );// 四个键分别接Row4、Row5、Row6、Row7
  46.                
  47.                 else
  48.                         Row_data = GET_BITS(GPIO_ISTAT(Row_Port),0,Front[idx].RowsInColumn-1 );
  49.                

  50.                 // 处理数据
  51.                 Row_data = (uint64)Row_data<<shift_num;
  52.                
  53.                 FrontKeyStu += Row_data;
  54.                
  55.                 shift_num += Front[idx].RowsInColumn;
  56.                
  57.                 for(;i<shift_num;i++)
  58.                 {
  59.                         Keys[i].Cur_KeyStatus |= 0x01&(FrontKeyStu>>i);
  60.                 }

  61.                 GPIO_BOP (Col_Port) = Front[idx].Column_GPIO; //恢复高电平       
  62.                
  63.         }
  64.        
  65. }
复制代码

  1. void Martrix_KB_Handle(void)
  2. {
  3.         uint8 idx;
  4.        
  5.         for(idx=0;idx<Matrix_KB_KeyNum;idx++)
  6.         {
  7.                 switch (Keys[idx].State)
  8.                 {
  9.             case State_NoteOFF:
  10.                
  11.                 if ( PRE_NOTE_ON == Keys[idx].Cur_KeyStatus )
  12.                 {
  13.                     Keys[idx].State = State_PreNoteON;
  14.                 }
  15.                 break;

  16.            case State_PreNoteON://Front键先按下,velocity开始计数
  17.                                
  18.                 Keys[idx].Note_Velocity.u32_velocity++;
  19.                                
  20.                 if ( NOTE_ON == Keys[idx].Cur_KeyStatus )
  21.                 {
  22.                         Keys[idx].State = State_NoteON;
  23.                         #ifdef JLINK_RTT_DEBUG
  24.                         SEGGER_RTT_printf(0,"%2d: ON%5d ",idx+1,Keys[idx].Note_Velocity.u32_velocity);
  25.                         #endif
  26.                         if(Sys_Flag.Upload_Enable)
  27.                         {
  28.                                 ON_FIFO.Note_Buffer[ON_FIFO.Idx_IN].num = idx;
  29.                                     ON_FIFO.Note_Buffer[ON_FIFO.Idx_IN].velocity.u32_velocity  = Keys[idx].Note_Velocity.u32_velocity;
  30.                                     ON_FIFO.Idx_IN++;
  31.                                     if(ON_FIFO.Idx_IN==Buffer_Size) ON_FIFO.Idx_IN = 0;
  32.                         }
  33.                         Keys[idx].Note_Velocity.u32_velocity = 0;
  34.                   }
  35.                   else if ( NOTE_OFF == Keys[idx].Cur_KeyStatus ) //按下一半就松开的情况
  36.                   {
  37.                         Keys[idx].Note_Velocity.u32_velocity = 0;
  38.                         Keys[idx].State = State_NoteOFF;
  39.                   }
  40.                   break;

  41.                 case State_NoteON:
  42.                                
  43.                         if ( PRE_NOTE_OFF == Keys[idx].Cur_KeyStatus )
  44.                         {
  45.                                 Keys[idx].State = State_PreNoteOFF;
  46.                         }
  47.                         break;
  48.                                
  49.                 case State_PreNoteOFF:
  50.                        
  51.                         Keys[idx].Note_Velocity.u32_velocity++;
  52.                                
  53.                         if ( NOTE_OFF == Keys[idx].Cur_KeyStatus )
  54.                         {
  55.                                 Keys[idx].State = State_NoteOFF;
  56.                                        
  57.                                 #ifdef JLINK_RTT_DEBUG
  58.                                 SEGGER_RTT_printf(0,"%2d:OFF%5d ",idx+1,Keys[idx].Note_Velocity.u32_velocity);
  59.                                 #endif

  60.                                 if(Sys_Flag.Upload_Enable)
  61.                                 {
  62.                                         OFF_FIFO.Note_Buffer[OFF_FIFO.Idx_IN].num = idx;
  63.                                             OFF_FIFO.Note_Buffer[OFF_FIFO.Idx_IN].velocity.u32_velocity  = Keys[idx].Note_Velocity.u32_velocity;
  64.                                             OFF_FIFO.Idx_IN++;
  65.                                             if(OFF_FIFO.Idx_IN==Buffer_Size) OFF_FIFO.Idx_IN = 0;
  66.                                 }
  67.                                 Keys[idx].Note_Velocity.u32_velocity = 0;                                       
  68.                         }
  69.                         break;
  70.                                
  71.                        
  72.                 default:
  73.                         break;
  74.                 }
  75.                
  76.         }
  77. }
复制代码

兄弟们帮我看看,能不能找到原因。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
49条回答
eagle_avr
1楼-- · 2019-12-16 06:06
 精彩回答 2  元偷偷看……
xyz.543
2楼-- · 2019-12-16 10:38
eagle_avr 发表于 2019-7-29 10:25
其实这个50us是我们软件部门经理提出的指标。就不多说了。能不能实现他心里应该有谱。
下面是按键的波形 ...

这台示波器也是公司的设备吗?若是的话,那一切也都不用再说了!...
dukelec
3楼-- · 2019-12-16 11:36
takashiki 发表于 2019-7-29 09:31
您要要实现的是实际功能,而不是您同事的代码。50us是什么概念您知道不,相当于20kHz。20kHz的机械振动您 ...

很多人都沒搞清楚應用。

這個是測量琴鍵單次敲擊的速度。按下一個琴鍵會閉合兩個開關。

最快速度到最慢速度的時間差要分級,譬如 8 位 256 級別。(實際估計沒這麼多。)
那麼,採樣自身的頻率和抖動,相對於分級不能太大。
eagle_avr
4楼-- · 2019-12-16 13:07
本帖最后由 eagle_avr 于 2019-7-29 13:34 编辑

把代码做了一些改动,增加了类似初态和次态的操作,目前测试很完美:
  1. 扫描:
  2. void Scan_MatrixKB ( void )
  3. {
  4.         uint8 idx,i=0,shift_num=0;
  5.        
  6.         FrontKeyStu = BackKeyStu = 0;
  7.        
  8.         for (idx=0;idx<B_ColumnNum;idx++)
  9.         {       
  10.                 GPIO_BC(Col_Port) = Back[idx].Column_GPIO;

  11.                 BackKeyStu += ((uint64)Back[idx].Row_Value)<<shift_num;
  12.                
  13.                 shift_num += Back[idx].RowsInColumn;
  14.                
  15.                 for(;i<shift_num;i++)
  16.                 {
  17.                         Keys[i].Cur_KeyStatus = (0x01&(BackKeyStu>>i))<<1;        
  18.                 }
  19.                
  20.                 Back[idx].Row_Value = GET_BITS(GPIO_ISTAT(Row_Port),0,Back[idx].RowsInColumn-1);

  21.                 GPIO_BOP(Col_Port) = Back[idx].Column_GPIO;
  22.            
  23.     }
  24.    
  25.         shift_num = i = 0;
  26.        
  27.         for ( idx=0; idx<F_ColumnNum; idx++ )
  28.         {               
  29.                 GPIO_BC(Col_Port) = Front[idx].Column_GPIO;

  30.                 FrontKeyStu += ((uint64)Front[idx].Row_Value)<<shift_num;
  31.         
  32.                 shift_num += Front[idx].RowsInColumn;
  33.                
  34.                 for(;i<shift_num;i++)
  35.                 {
  36.                         Keys[i].Cur_KeyStatus |= 0x01&(FrontKeyStu>>i);
  37.                         Keys[i].Pre_KeyStatus = Keys[i].Cur_KeyStatus;
  38.                 }
  39.                                
  40.                 Front[idx].Row_Value = GET_BITS(GPIO_ISTAT(Row_Port),0,Front[idx].RowsInColumn-1 );
  41.                
  42.                 GPIO_BOP(Col_Port) = Front[idx].Column_GPIO;
  43.         }
  44. }
复制代码
  1. 处理:
  2. void Martrix_KB_Handle(void)
  3. {
  4.         uint8 i;
  5.        
  6.         for ( i=0; i<Matrix_KB_KeyNum; i++ )
  7.         {
  8.                 switch (Keys[i].State)
  9.                 {
  10.                         case State_NoteOFF:

  11.                                 if ( PRE_NOTE_ON == Keys[i].Pre_KeyStatus )
  12.                                 {
  13.                                         Keys[i].State = State_PreNoteON;
  14.                                 }
  15.                                 break;
  16.                     
  17.                         case State_PreNoteON:
  18.                                    
  19.                                 Keys[i].NoteON_Velocity.u32_velocity++;
  20.                                    
  21.                                 if ( NOTE_ON == Keys[i].Pre_KeyStatus )
  22.                                 {
  23.                                         Keys[i].State = State_NoteON;
  24.                                         Keys[i].NoteON_Velocity.u32_velocity = 0;
  25.                                 }
  26.                                 else if ( NOTE_OFF == Keys[i].Pre_KeyStatus )
  27.                                 {
  28.                                         Keys[i].NoteON_Velocity.u32_velocity = 0;
  29.                                         Keys[i].State = State_NoteOFF;
  30.                                 }
  31.                                 break;

  32.                         case State_NoteON:
  33.                                    
  34.                                 if ( PRE_NOTE_OFF == Keys[i].Pre_KeyStatus )
  35.                                 {
  36.                                         Keys[i].State = State_PreNoteOFF;
  37.                                 }
  38.                                 break;
  39.                                    
  40.                         case State_PreNoteOFF:
  41.                                    
  42.                                 Keys[i].NoteOFF_Velocity.u32_velocity++;
  43.                                 if ( NOTE_OFF == Keys[i].Pre_KeyStatus )
  44.                                 {
  45.                                         Keys[i].State = State_NoteOFF;
  46.                                         Keys[i].NoteOFF_Velocity.u32_velocity = 0;                                       
  47.                                 }
  48.                                 break;

  49.                         default:
  50.                                 break;
  51.                 }
  52.         }
  53.    
  54. }
复制代码
huangqi412
5楼-- · 2019-12-16 17:10
好多人没明白琴键是有力度或者叫速度分辨的  机械化数字化最简单做法就是类似测子弹速度双光电触发算时间差  这里是直接双机械按键  楼主先贴出电路图吧
huangqi412
6楼-- · 2019-12-16 20:32
 精彩回答 2  元偷偷看……

一周热门 更多>