用的stm8s105k4 矩阵按键检测时好像产生了冲突,大牛赐教一波

2019-08-14 06:09发布

下面先上源程序

#define key_1 GPIO_ReadInputPin(GPIOB, GPIO_PIN_3)
#define key_2 GPIO_ReadInputPin(GPIOB, GPIO_PIN_2)
#define key_double 2
#define key_thirple 3

#define N_key 0//无键按下
#define S_key 1//单击按下
#define D_key 2//双击按下
#define L_key 3//长按
#define key_state_0 0
#define key_state_1 1
#define key_state_2 2
#define key_state_3 3


void Delay(uint16_t nCount)
{
  /* Decrement nCount value */
  while (nCount !=0)
  {   
    nCount++;
  }

}

这个是按键初始化 ,PB2或PB3输入低电平即代表按下

void key_init()
{
  GPIO_DeInit(GPIOC);//清除其到默认状态
  GPIO_DeInit(GPIOB);
  GPIO_Init(GPIOC, GPIO_PIN_2, GPIO_MODE_OUT_PP_LOW_FAST);//初始化配置
  GPIO_Init(GPIOC, GPIO_PIN_1, GPIO_MODE_OUT_PP_LOW_FAST);
  GPIO_Init(GPIOC, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_FAST);;
  GPIO_Init(GPIOB, GPIO_PIN_2,  GPIO_MODE_IN_PU_NO_IT);
  GPIO_Init(GPIOB, GPIO_PIN_3,  GPIO_MODE_IN_PU_NO_IT);
   //GPIO_Init(GPIOB, GPIO_PIN_ALL,GPIO_MODE_IN_PU_NO_IT);//B端口配制成上拉输入模式,默认情况下为高电平
}


这个是检测按键 长按 短按 和双击的的 之所以有两个KEY—driver 是因为想同时检测PB2和PB3,因为试过了driver()里面直接用或运算把key-1和key-2或起来 但是结果总是错的,所以只能采用这种笨拙的办法 ,但下面的才是重点不懂的问题。

*按键长按 单击 双击*/
u8  key_scan(u8 mode)
{
      static u8 key_up= 1;//按键松开标志
      if (mode) key_up=1;//支持连按
       if(key_up&&key_1==0||key_2==0)
       {
         Delay(0xff);//去抖动
         key_up=0;
         if(key_1==0)  return  key_double;
         else if(key_2==0)  return key_thirple;
       }
       else if (key_1==1&&key_2==1)  key_up=1;
       return 0;//无按键按下
  }
       unsigned char key_driver(void)
       {
         static unsigned char key_state = key_state_0, key_time = 0;
         unsigned char key_press, key_return = N_key;//N_key等于0
         key_press=key_1;

         switch(key_state)
                {
                case  key_state_0:
                  if(!key_press) key_state = key_state_1;
                 break;
                case key_state_1:
                   if(!key_press)
                   {  
                     key_time = 0;
                     key_state = key_state_2;
                   }
                  else
                     key_state = key_state_0;
                   break;   
                 case key_state_2:
                 if(key_press)
                 {
                      key_return=S_key;//按键释放,单击操作,返回s_key
                      key_state = key_state_0;
                 }
                   else if(++key_time >= 50)
                        {
                                key_return = L_key;//按下时间为1000ms,长按操作
                                key_state = key_state_3;
                        }
                    break;
                case key_state_3://等待按键释放状态,此状态只返回无按键时间
                     if(key_press)   key_state = key_state_0;//按键已释放,转换到初始按键状态     
                     break;
        }
        return key_return;
}
unsigned char key_driver2(void)
       {
         static unsigned char key_state = key_state_0, key_time = 0;
         unsigned char key_press, key_return = N_key;//N_key等于0
         key_press=key_2;

         switch(key_state)
                {
                case  key_state_0:
                  if(!key_press) key_state = key_state_1;
                 break;
                case key_state_1:
                   if(!key_press)
                   {  
                     key_time = 0;
                     key_state = key_state_2;
                   }
                  else
                     key_state = key_state_0;
                   break;   
                 case key_state_2:
                 if(key_press)
                 {
                      key_return=S_key;//按键释放,单击操作,返回s_key
                      key_state = key_state_0;
                 }
                   else if(++key_time >= 50)
                        {
                                key_return = L_key;//按下时间为1000ms,长按操作
                                key_state = key_state_3;
                        }
                    break;
                case key_state_3://等待按键释放状态,此状态只返回无按键时间
                     if(key_press)   key_state = key_state_0;//按键已释放,转换到初始按键状态     
                     break;
        }
        return key_return;
}
/*对于长键,按下1s后马上响应,反应最快
  对于单键,第2次按键释放后马上得到反应
  对于单键,释放后延时拖后500ms后才能响应,反应最慢*/
unsigned char key_read(void)
{
        static unsigned char key_m = key_state_0, key_time_1 = 0;
        unsigned char key_return=N_key,key_temp;
       key_temp=key_driver();
     // if(key_driver(key_1)==S_key)&&(key_driver(key_2)==S_key)

        switch(key_m)
        {
        case key_state_0:

                        if(key_temp == S_key)
                        // if((key_driver(key_1)==S_key)||(key_driver(key_2)==S_key))
                        {
                                key_time_1 = 0;//第一次单击 不返回,到下个状态判断后面是否有出现双击
                               key_m= key_state_1;
                        }
                        else

                                key_return = key_temp;
                         break;
                case   key_state_1:

                       if(key_temp == S_key)//又一次单击(间隔小于500ms)
                     //if((key_driver(key_1)==S_key)||(key_driver(key_2)==S_key))
                        {
                                key_return = D_key;//返回双击事件,回初始状态
                                key_m= key_state_0;
                        }
                        else
                        {      
                          if(++key_time_1>=30)//这里返回的都是无键事件
                        {
                           key_return = S_key;
                           key_m = key_state_0;
                        }
                }
                break;
        }
        return key_return;
                }  
unsigned char key_read2(void)
{
        static unsigned char key_m = key_state_0, key_time_1 = 0;
        unsigned char key_return=N_key,key_temp;
       key_temp=key_driver2();
     // if(key_driver(key_1)==S_key)&&(key_driver(key_2)==S_key)

        switch(key_m)
        {
        case key_state_0:

                        if(key_temp == S_key)
                        // if((key_driver(key_1)==S_key)||(key_driver(key_2)==S_key))
                        {
                                key_time_1 = 0;//第一次单击 不返回,到下个状态判断后面是否有出现双击
                               key_m= key_state_1;
                        }
                        else

                                key_return = key_temp;
                         break;
                case   key_state_1:

                       if(key_temp == S_key)//又一次单击(间隔小于500ms)
                     //if((key_driver(key_1)==S_key)||(key_driver(key_2)==S_key))
                        {
                                key_return = D_key;//返回双击事件,回初始状态
                                key_m= key_state_0;
                        }
                        else
                        {      
                          if(++key_time_1>=30)//这里返回的都是无键事件
                        {
                           key_return = S_key;
                           key_m = key_state_0;
                        }
                }
                break;
        }
        return key_return;
                }


下面是检测第二行和第三行的 按键程序,按下即发送相应字符

*按键长按 单击 双击*/
u8  key_scan(u8 mode)
{
      static u8 key_up= 1;//按键松开标志
      if (mode) key_up=1;//支持连按
       if(key_up&&key_1==0||key_2==0)
       {
         Delay(0xff);//去抖动
         key_up=0;
         if(key_1==0)  return  key_double;
         else if(key_2==0)  return key_thirple;
       }
       else if (key_1==1&&key_2==1)  key_up=1;
       return 0;//无按键按下
  }
       unsigned char key_driver(void)
       {
         static unsigned char key_state = key_state_0, key_time = 0;
         unsigned char key_press, key_return = N_key;//N_key等于0
         key_press=key_1;

         switch(key_state)
                {
                case  key_state_0:
                  if(!key_press) key_state = key_state_1;
                 break;
                case key_state_1:
                   if(!key_press)
                   {  
                     key_time = 0;
                     key_state = key_state_2;
                   }
                  else
                     key_state = key_state_0;
                   break;   
                 case key_state_2:
                 if(key_press)
                 {
                      key_return=S_key;//按键释放,单击操作,返回s_key
                      key_state = key_state_0;
                 }
                   else if(++key_time >= 50)
                        {
                                key_return = L_key;//按下时间为1000ms,长按操作
                                key_state = key_state_3;
                        }
                    break;
                case key_state_3://等待按键释放状态,此状态只返回无按键时间
                     if(key_press)   key_state = key_state_0;//按键已释放,转换到初始按键状态     
                     break;
        }
        return key_return;
}
unsigned char key_driver2(void)
       {
         static unsigned char key_state = key_state_0, key_time = 0;
         unsigned char key_press, key_return = N_key;//N_key等于0
         key_press=key_2;

         switch(key_state)
                {
                case  key_state_0:
                  if(!key_press) key_state = key_state_1;
                 break;
                case key_state_1:
                   if(!key_press)
                   {  
                     key_time = 0;
                     key_state = key_state_2;
                   }
                  else
                     key_state = key_state_0;
                   break;   
                 case key_state_2:
                 if(key_press)
                 {
                      key_return=S_key;//按键释放,单击操作,返回s_key
                      key_state = key_state_0;
                 }
                   else if(++key_time >= 50)
                        {
                                key_return = L_key;//按下时间为1000ms,长按操作
                                key_state = key_state_3;
                        }
                    break;
                case key_state_3://等待按键释放状态,此状态只返回无按键时间
                     if(key_press)   key_state = key_state_0;//按键已释放,转换到初始按键状态     
                     break;
        }
        return key_return;
}
/*对于长键,按下1s后马上响应,反应最快
  对于单键,第2次按键释放后马上得到反应
  对于单键,释放后延时拖后500ms后才能响应,反应最慢*/
unsigned char key_read(void)
{
        static unsigned char key_m = key_state_0, key_time_1 = 0;
        unsigned char key_return=N_key,key_temp;
       key_temp=key_driver();
     // if(key_driver(key_1)==S_key)&&(key_driver(key_2)==S_key)

        switch(key_m)
        {
        case key_state_0:

                        if(key_temp == S_key)
                        // if((key_driver(key_1)==S_key)||(key_driver(key_2)==S_key))
                        {
                                key_time_1 = 0;//第一次单击 不返回,到下个状态判断后面是否有出现双击
                               key_m= key_state_1;
                        }
                        else

                                key_return = key_temp;
                         break;
                case   key_state_1:

                       if(key_temp == S_key)//又一次单击(间隔小于500ms)
                     //if((key_driver(key_1)==S_key)||(key_driver(key_2)==S_key))
                        {
                                key_return = D_key;//返回双击事件,回初始状态
                                key_m= key_state_0;
                        }
                        else
                        {      
                          if(++key_time_1>=30)//这里返回的都是无键事件
                        {
                           key_return = S_key;
                           key_m = key_state_0;
                        }
                }
                break;
        }
        return key_return;
                }  
unsigned char key_read2(void)
{
        static unsigned char key_m = key_state_0, key_time_1 = 0;
        unsigned char key_return=N_key,key_temp;
       key_temp=key_driver2();
     // if(key_driver(key_1)==S_key)&&(key_driver(key_2)==S_key)

        switch(key_m)
        {
        case key_state_0:

                        if(key_temp == S_key)
                        // if((key_driver(key_1)==S_key)||(key_driver(key_2)==S_key))
                        {
                                key_time_1 = 0;//第一次单击 不返回,到下个状态判断后面是否有出现双击
                               key_m= key_state_1;
                        }
                        else

                                key_return = key_temp;
                         break;
                case   key_state_1:

                       if(key_temp == S_key)//又一次单击(间隔小于500ms)
                     //if((key_driver(key_1)==S_key)||(key_driver(key_2)==S_key))
                        {
                                key_return = D_key;//返回双击事件,回初始状态
                                key_m= key_state_0;
                        }
                        else
                        {      
                          if(++key_time_1>=30)//这里返回的都是无键事件
                        {
                           key_return = S_key;
                           key_m = key_state_0;
                        }
                }
                break;
        }
        return key_return;
                }

下面是检测第二行和第三行 四个按键的程序,很奇怪同意的两个按键一起检测就没问题,比如vol1和vol2  和spk和mic 但是同一列的检测如 vol+和spk就不行 什么都发不出来

void KEY_VOL1()
{  

  u8 key;
  GPIO_WriteLow(GPIOC, GPIO_PIN_2);
  GPIO_WriteHigh(GPIOC, GPIO_PIN_1);
  GPIO_WriteHigh(GPIOC, GPIO_PIN_3);
    key=key_read();
if(key== S_key)
Send_Str( "u");
else if(key== L_key)
  Send_Str( "p");

   Delay(0xff);

}
void KEY_VOL2()
{  

  u8 key;
  GPIO_WriteLow(GPIOC, GPIO_PIN_2);
  GPIO_WriteHigh(GPIOC, GPIO_PIN_1);
  GPIO_WriteHigh(GPIOC, GPIO_PIN_3);
    key=key_read2();
if(key== S_key)
Send_Str( "v");
else if(key== L_key)
  Send_Str( "n");

   Delay(0xff);

}
void KEY_mic()
{
  u8 key;
  GPIO_WriteLow(GPIOC, GPIO_PIN_3);
  GPIO_WriteHigh(GPIOC, GPIO_PIN_1);
  GPIO_WriteHigh(GPIOC, GPIO_PIN_2);

   key=key_read2();

     if(key== S_key)  Send_Str( "");
     else if (key== L_key)  Send_Str( "s");
     Delay(0xff);
}
void KEY_spk()
{
  u8 key;
  GPIO_WriteLow(GPIOC, GPIO_PIN_3);
  GPIO_WriteHigh(GPIOC, GPIO_PIN_1);
  GPIO_WriteHigh(GPIOC, GPIO_PIN_2);
  key=key_read();

  if(key== S_key)  Send_Str( "R");
  else if(key== L_key)  Send_Str( "S");
  Delay(0xff);
}


主函数是这样的 4个一起放进去 什么都发不出来,单独放vol+和vol-即同一行的就行 vol+和spk同一列的就不行
void main(void)
{  
   u8 key;
   ii2_init();
   Init_UART2();
   led_init();
   key_init();
   enableInterrupts();
while(1)
   {

   KEY_VOL1();
  KEY_VOL2();
   KEY_mic();
  KEY_spk();

}
}     

看不破是为什么了?希望有人能分享一下  

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。