打印
[STM32]

再问矩阵键盘的问题

[复制链接]
790|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
我用STM32写了个矩阵键盘的程序,原来是查询方式,现在改成定时器方式。
原理图:

程序:
void KEY_Init(void)
{

GPIO_InitTypeDef  GPIO_InitStructure;
       
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);         //使能PB,PE端口时钟
       
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;                                 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;                  //开漏输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOE, &GPIO_InitStructure);                                         

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 ;                                 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;                  //浮空输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOE, &GPIO_InitStructure);                                         
       
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;                             
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;                  //浮空输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);                                            
       

}
/*******************************************************************************
* 函数名  : Timer4_Init_Config
* 描述    : Timer4初始化配置
* 输入    : 无
* 输出    : 无
* 返回    : 无
* 说明    : 无
*******************************************************************************/
void Timer4_Init_Config(void)
{
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);                //使能Timer1时钟
        //设置在下一个更新事件装入活动的自动重装载寄存器周期的值(计数到200为20ms)
        TIM_TimeBaseStructure.TIM_Period = 199;                                               
        TIM_TimeBaseStructure.TIM_Prescaler = 7199;                                        //设置用来作为TIMx时钟频率除数的预分频值(10KHz的计数频率)
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;                //设置时钟分割:TDTS = TIM_CKD_DIV1
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;        //TIM向上计数模式
        TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);                                //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
         
        TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE );                                 //使能TIM2指定的中断
       
        TIM_Cmd(TIM4, ENABLE);                                                                          //使能TIMx外设
}


/*******************************************************************************
* 函数名  : TIM4_IRQHandler
* 描述    : 定时器2中断断服务函数
* 输入    : 无
* 输出    : 无
* 返回    : 无
* 说明    : 无
*******************************************************************************/
void TIM4_IRQHandler(void)
{
       
        if(TIM_GetITStatus(TIM4, TIM_IT_Update) == SET)
        {
                TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
                if(KeyFlag == 1)
                {
                       
                        hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
                        if (hangvalue != 0x3f)        // 读出的不是0x3f说明有按键被按下
                        {
                                keynum = 0;
                                keyvalue = 0;
                                KeyFlag = 2;
                               
                                GPIO_ResetBits(GPIOE,GPIO_Pin_6);                                                  //PE.6输出低
                                GPIO_SetBits(GPIOE,GPIO_Pin_5 | GPIO_Pin_4 | GPIO_Pin_3);                                         
                               
                                delay_us(XD);                               
                                hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0300)>>5);
                               
                                switch (hangvalue)
                                {
                                        case 0x0F:

                                                                        keyvalue=4;

                                                break;
                                        case 0x17:
                                                       
                                                                        keyvalue=5;
                       
                                                break;
                                        case 0x1b:
                                                                        keyvalue=1;
                                                break;
                                        case 0x1d:
                                                       
                                                       
                                                                        keyvalue=2;
                                                                       
                                                break;
                                        case 0x1e:
                                                       
                                                       
                                                                        keyvalue=3;
                                                                       
                                                break;
                                       
                                        default: break;
                                       
                                }
                               
                        if(keyvalue==0)
                        {
                                GPIO_ResetBits(GPIOE, GPIO_Pin_5 );
                                GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_4 | GPIO_Pin_3);
                               
                                delay_us(XD);       
                                hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0300)>>5);
                               
                               
                                switch (hangvalue)
                                {
                                        case 0x0F:
                                                       
                                                       
                                                       
                                                                        keyvalue=9;
                                                               
                                                break;
                                        case 0x17:
                                                       
                                                       
                                                                        keyvalue=10;
                                               
                                                break;
                                        case 0x1b:
                                                       
                                                       
                                                                        keyvalue=6;
                                                       
                                                break;
                                        case 0x1d:
                                                       
                                                       
                                                                        keyvalue=7;
                                               
                                                break;
                                        case 0x1e:
                                                       
                                                       
                                                                        keyvalue=8;
                                                       
                                                break;
                                       
                                               
                                        default: break;
                                       
                                }
                        }
               
                if(keyvalue==0)
                {
                        GPIO_ResetBits(GPIOE, GPIO_Pin_4 );
                        GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_3 | GPIO_Pin_5);
                       
                        delay_us(XD);       
                        hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
               
                       
                       
                        // 第一回合中算出行号
                                switch (hangvalue)
                                {
                                        case 0x1F:
                                                       
                                                       
                                               
                                                                        keyvalue=14;
                                               
                                                break;
                                        case 0x2F:
                                                       
                                                       
                                                                        keyvalue=15;
                                       
                                                break;
                                        case 0x37:
                                                       
                                                       
                                                                        keyvalue=16;
                                               
                                                break;
                                        case 0x3B:
                                                       
                                                       
                                                                        keyvalue=11;
                                               
                                                break;
                                        case 0x3D:
                                                       
                                                       
                                                                        keyvalue=12;
                                                       
                                                break;
                                        case 0x3E:
                                                       
                                                       
                                                                        keyvalue=13;
                                       
                                                break;
                                        default: break;
                                       
                                }
                        }       
                        if(keyvalue==0)
                        {
                                GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_4 | GPIO_Pin_5);
                                GPIO_ResetBits(GPIOE, GPIO_Pin_3 );
                                delay_us(XD);       
                                hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
                       
                                switch (hangvalue)
                                {
                                        case 0x1F:
                                                       
                                                       
                                                       
                                                                        keyvalue=20;
                                               
                                                break;
                                        case 0x2F:
                                                       
                                                       
                                                                        keyvalue=21;
                                               
                                                break;
                                        case 0x37:
                                                       
                                                       
                                                                        keyvalue=22;
                                                       
                                                break;
                                        case 0x3B:
                                                       
                                                       
                                                                        keyvalue=17;
                                               
                                                break;
                                        case 0x3D:
                                                       
                                                                        keyvalue=18;
                                               
                                                break;
                                        case 0x3E:
                                                       
                                                       
                                                                        keyvalue=19;
                                                       
                                                break;
                                        default: break;
                                       
                                }
                        }
                                GPIO_ResetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_5 | GPIO_Pin_4 | GPIO_Pin_3);          //PE.6,5,4,3 输出低
                                delay_us(XD);
                                hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
                                while (hangvalue != 0x3f)
                                {
                                        delay_us(20);
                                        hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
                                }
                                KeyFlag=0;
                                keynum = keyvalue;
                                if(S0_State == (S_INIT|S_CONN))
                                {
                                        S0_Data&=~S_TRANSMITOK;
                                       
                                        Write_SOCK_Data_Buffer(0, &keynum, 1);//指定Socket(0~7)发送数据处理,端口0发送23字节数据
                                }
                        }
                        else
                                KeyFlag = 0;
                }
                GPIO_ResetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_5 | GPIO_Pin_4 | GPIO_Pin_3);          //PE.6,5,4,3 输出低
                delay_us(XD);
                hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
                if (hangvalue != 0x3f)        // 读出的不是0x3f说明有按键被按下
                {
                        KeyFlag = 1;
                }
                else
                        KeyFlag = 0;
//                led^=0x01;
//                GPIO_WriteBit(GPIOE,GPIO_Pin_7,led);
        }
}
按下按键测试,通过网口打印出来:

可以看到,有的按键打印两次,实际按下一次。
还有的正确键值后面跟着一个0.
请高手指教,如何解决?谢谢!

使用特权

评论回复

相关帖子

沙发
elife| | 2020-7-11 23:36 | 只看该作者
中断中等待按键释放,按键时间在几百ms,这样很耗时间,会引起定时中断丢失。如果STM32的中断能够记住多个丢失的中断,会导致快速多次进入中断,在按键释放的抖动阶段,会出现多次按键或奇怪按键。可以在中断中设置标志,表示按键按下,在下次中断中判断按键释放,20mS的中断间隔,可以避开按键抖动阶段。

使用特权

评论回复
板凳
比神乐|  楼主 | 2020-7-12 10:14 | 只看该作者
elife 发表于 2020-7-11 23:36
中断中等待按键释放,按键时间在几百ms,这样很耗时间,会引起定时中断丢失。如果STM32的中断能够记住多个丢 ...

谢谢!我试试

使用特权

评论回复
地板
比神乐|  楼主 | 2020-7-13 08:36 | 只看该作者
elife 发表于 2020-7-11 23:36
中断中等待按键释放,按键时间在几百ms,这样很耗时间,会引起定时中断丢失。如果STM32的中断能够记住多个丢 ...

我改了一下,没有那种多一个0的情况了,不过还有打印两次相同键值的情况。
程序如下:
/*******************************************************************************
* 函数名  : TIM4_IRQHandler
* 描述    : 定时器4中断断服务函数
* 输入    : 无
* 输出    : 无
* 返回    : 无
* 说明    : 无
*******************************************************************************/
void TIM4_IRQHandler(void)
{
       
        if(TIM_GetITStatus(TIM4, TIM_IT_Update) == SET)
        {
                TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
                if(KeyFlag == 2)
                {
                                GPIO_ResetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_5 | GPIO_Pin_4 | GPIO_Pin_3);          //PE.6,5,4,3 输出低
                                delay_us(XD);
                                hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);

                                if(hangvalue == 0x3f)
                                {
                                        KeyFlag=0;
                                        keynum = keyvalue;
                                        if(S0_State == (S_INIT|S_CONN))
                                        {
                                                S0_Data&=~S_TRANSMITOK;
                                               
                                                Write_SOCK_Data_Buffer(0, &keynum, 1);//指定Socket(0~7)发送数据处理,端口0发送23字节数据
                                        }
                                }
                }
                if(KeyFlag == 1)
                {
                        GPIO_ResetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_5 | GPIO_Pin_4 | GPIO_Pin_3);          //PE.6,5,4,3 输出低
                        delay_us(XD);
                        hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
                        if (hangvalue != 0x3f)        // 读出的不是0x3f说明有按键被按下
                        {
                                keynum = 0;
                                keyvalue = 0;
                                KeyFlag = 2;
                               
                                GPIO_ResetBits(GPIOE,GPIO_Pin_6);                                                  //PE.6输出低
                                GPIO_SetBits(GPIOE,GPIO_Pin_5 | GPIO_Pin_4 | GPIO_Pin_3);                                         
                               
                                delay_us(XD);                               
                                hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0300)>>5);
                               
                                switch (hangvalue)
                                {
                                        case 0x0F:

                                                                        keyvalue=4;

                                                break;
                                        case 0x17:
                                                       
                                                                        keyvalue=5;
                       
                                                break;
                                        case 0x1b:
                                                                        keyvalue=1;
                                                break;
                                        case 0x1d:
                                                       
                                                       
                                                                        keyvalue=2;
                                                                       
                                                break;
                                        case 0x1e:
                                                       
                                                       
                                                                        keyvalue=3;
                                                                       
                                                break;
                                       
                                        default: break;
                                       
                                }
                               
                        if(keyvalue==0)
                        {
                                GPIO_ResetBits(GPIOE, GPIO_Pin_5 );
                                GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_4 | GPIO_Pin_3);
                               
                                delay_us(XD);       
                                hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0300)>>5);
                               
                               
                                switch (hangvalue)
                                {
                                        case 0x0F:
                                                       
                                                       
                                                       
                                                                        keyvalue=9;
                                                               
                                                break;
                                        case 0x17:
                                                       
                                                       
                                                                        keyvalue=10;
                                               
                                                break;
                                        case 0x1b:
                                                       
                                                       
                                                                        keyvalue=6;
                                                       
                                                break;
                                        case 0x1d:
                                                       
                                                       
                                                                        keyvalue=7;
                                               
                                                break;
                                        case 0x1e:
                                                       
                                                       
                                                                        keyvalue=8;
                                                       
                                                break;
                                       
                                               
                                        default: break;
                                       
                                }
                        }
               
                if(keyvalue==0)
                {
                        GPIO_ResetBits(GPIOE, GPIO_Pin_4 );
                        GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_3 | GPIO_Pin_5);
                       
                        delay_us(XD);       
                        hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
               
                       
                       
                        // 第一回合中算出行号
                                switch (hangvalue)
                                {
                                        case 0x1F:
                                                       
                                                       
                                               
                                                                        keyvalue=14;
                                               
                                                break;
                                        case 0x2F:
                                                       
                                                       
                                                                        keyvalue=15;
                                       
                                                break;
                                        case 0x37:
                                                       
                                                       
                                                                        keyvalue=16;
                                               
                                                break;
                                        case 0x3B:
                                                       
                                                       
                                                                        keyvalue=11;
                                               
                                                break;
                                        case 0x3D:
                                                       
                                                       
                                                                        keyvalue=12;
                                                       
                                                break;
                                        case 0x3E:
                                                       
                                                       
                                                                        keyvalue=13;
                                       
                                                break;
                                        default: break;
                                       
                                }
                        }       
                        if(keyvalue==0)
                        {
                                GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_4 | GPIO_Pin_5);
                                GPIO_ResetBits(GPIOE, GPIO_Pin_3 );
                                delay_us(XD);       
                                hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
                       
                                switch (hangvalue)
                                {
                                        case 0x1F:
                                                       
                                                       
                                                       
                                                                        keyvalue=20;
                                               
                                                break;
                                        case 0x2F:
                                                       
                                                       
                                                                        keyvalue=21;
                                               
                                                break;
                                        case 0x37:
                                                       
                                                       
                                                                        keyvalue=22;
                                                       
                                                break;
                                        case 0x3B:
                                                       
                                                       
                                                                        keyvalue=17;
                                               
                                                break;
                                        case 0x3D:
                                                       
                                                                        keyvalue=18;
                                               
                                                break;
                                        case 0x3E:
                                                       
                                                       
                                                                        keyvalue=19;
                                                       
                                                break;
                                        default: break;
                                       
                                }
                        }
                               
                        }
                        else
                                KeyFlag = 0;
                }
                if(KeyFlag == 0)
                {
                        GPIO_ResetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_5 | GPIO_Pin_4 | GPIO_Pin_3);          //PE.6,5,4,3 输出低
                        delay_us(XD);
                        hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
                        if (hangvalue != 0x3f)        // 读出的不是0x3f说明有按键被按下
                        {
                                KeyFlag = 1;
                        }
                        else
                                KeyFlag = 0;
                }
//                led^=0x01;
//                GPIO_WriteBit(GPIOE,GPIO_Pin_7,led);
        }
}












使用特权

评论回复
5
一事无成就是我| | 2020-7-14 16:47 | 只看该作者
/*******************************************************************************
* 函数名  : TIM4_IRQHandler
* 描述    : 定时器4中断断服务函数
* 输入    : 无
* 输出    : 无
* 返回    : 无
* 说明    : 无
*******************************************************************************/
void TIM4_IRQHandler(void)
{
       static uint8_t    key_Pace = 0;
       static uint32_t  old_KeyVal;
       uint32_t           new_KeyVal;

        if(TIM_GetITStatus(TIM4, TIM_IT_Update) == SET)
        {   //设定4ms中断一次
                TIM_ClearITPendingBit(TIM4, TIM_IT_Update);

               //键盘检测可以做成for循环4次
               // PE.6,5,4设施成输入 ,PE3输出L
               new_KeyVal = (~(GPIO_ReadInputData(GPIOE) & 7) + (GPIO_ReadInputData(GPIOB) >>4))) & 0x3f ;
               //PE.3输入,PE4输出L
               new_KeyVal |= ((~(GPIO_ReadInputData(GPIOE) & 7) + (GPIO_ReadInputData(GPIOB) >>4))) & 0x3f) << 6;
               //PE.4输入,PE5输出L
               new_KeyVal |= ((~(GPIO_ReadInputData(GPIOE) & 7) + (GPIO_ReadInputData(GPIOB) >>4))) & 0x3f) << 12;
               //PE.5输入,PE6输出L
               new_KeyVal |= ((~(GPIO_ReadInputData(GPIOE) & 7) + (GPIO_ReadInputData(GPIOB) >>4))) & 0x3f ) << 18;
               //恢复键盘待机,PE.6,5,4,  3全部输出L

                key_Pace ++;
                if(key_Pace < 6)
                {  //键盘按下去抖, 时间4ms×6 = 24ms ,也可以设置6~8ms中断一次,响应该值调整
                    if((new_KeyVal == 0) || new_KeyVal != old_KeyVal)  //无键操作或者键值不对应
                       {old_KeyVal = new_KeyVal;  key_Pace = 0;}                      //返回等待键盘状态
                }
                else if(key_Pace == 6)
                {  //键值处理,或启动发送
                     switch(old_KeyVal)
                    {  //键盘比较离散或允许组合键采用这个方法
                    case   0x000001:        //键盘1
                              break;
                    case   0x000002:        //键盘2
                              break;
                    case   0x000004:        //键盘3
                              break;
                    case   0x000008:        //键盘4
                              break;
                    case   0x000010:        //键盘5
                              break;
                    case   0x000020:        //键盘6
                              break;
                    case   0x000040:        //键盘7
                              break;
                    case   0x000080:        //键盘8
                              break;
                    case   0x000100:        //键盘9
                              break;
                    case   0x000200:        //键盘10
                              break;
                    case   0x000400:        //键盘11
                              break;
                    case   0x000800:        //键盘12
                              break;
                    case   0x001000:        //键盘13
                              break;
                    case   0x002000:        //键盘14
                              break;
                    case   0x004000:        //键盘15
                              break;
                    case   0x008000:        //键盘16
                              break;
                    case   0x010000:        //键盘17
                              break;
                    case   0x020000:        //键盘18
                              break;
                    case   0x040000:        //键盘19
                              break;
                    case   0x080000:        //键盘20
                              break;
                    case   0x100000:        //键盘21
                              break;
                    case   0x200000:        //键盘22
                              break;
                    case   0x400000:        //键盘23
                              break;
                    case   0x800000:        //键盘24
                              break;
                    case   0xXXXXXX:        //其它组合键盘
                              break;
                    }
// 可以用统筹方法组合好后统一发送数据到通讯口
                    old_KeyVal = 0;
                }
                else if(key_Pace < 20)
                {   //键盘释放去抖
                    if(new_KeyVal != 0)  key_Pace = 6;    //等待键盘释放
                }
                else    key_Pace = 0;                               //键盘释放
        }
}

参考一下

使用特权

评论回复
6
比神乐|  楼主 | 2020-7-14 17:05 | 只看该作者
一事无成就是我 发表于 2020-7-14 16:47
/*******************************************************************************
* 函数名  : TIM4_IR ...

谢谢!我试一下。

使用特权

评论回复
7
一事无成就是我| | 2020-7-14 17:13 | 只看该作者
一般我们不在定时器里做这些事情,只是在中断里设置状态位,而是在主程序里不断扫描状态位,有效则执行,执行后清除,那样不影响多任务实时性

使用特权

评论回复
8
比神乐|  楼主 | 2020-7-15 09:20 | 只看该作者
一事无成就是我 发表于 2020-7-14 17:13
一般我们不在定时器里做这些事情,只是在中断里设置状态位,而是在主程序里不断扫描状态位,有效则执行,执 ...

搞好了,谢谢

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

435

主题

3407

帖子

7

粉丝