打印
[STM32F1]

矩阵键盘程序问题

[复制链接]
1588|43
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
我写了个矩阵键盘程序,有点问题,有时按下一个按键,返回两次键值,有时返回0(没有检测到按键)
我调试,返回键值,通过网口发送到网络调试助手。
原理图:

程序:
//初始化PA8和PD2为输出口.并使能这两个口的时钟                    
//LED IO初始化
void KEY_Init(void)
{

GPIO_InitTypeDef  GPIO_InitStructure;
       
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);         //使能PA,PD端口时钟
       
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;                                 //LED0-->PA.8 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOE, &GPIO_InitStructure);                                         //根据设定参数初始化GPIOA.8

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 ;                                 //LED0-->PA.8 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;                  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOE, &GPIO_InitStructure);                                         //根据设定参数初始化GPIOA.8
       
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;                             //LED1-->PD.2 端口配置, 推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;                  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);                                           //推挽输出 ,IO口速度为50MHz
       

}
void Hang_Output(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
       
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);         //使能PA,PD端口时钟
       


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 ;                                 //LED0-->PA.8 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOE, &GPIO_InitStructure);                                         //根据设定参数初始化GPIOA.8
       
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;                             //LED1-->PD.2 端口配置, 推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);                                           //推挽输出 ,IO口速度为50MHz
       
}
void Hang_Input(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
       
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);         //使能PA,PD端口时钟
       


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 ;                                 //LED0-->PA.8 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;                  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOE, &GPIO_InitStructure);                                         //根据设定参数初始化GPIOA.8
       
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;                             //LED1-->PD.2 端口配置, 推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;                  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);                                           //推挽输出 ,IO口速度为50MHz
       
}
void Lie_Input(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
       
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);         //使能PA,PD端口时钟
       
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;                                 //LED0-->PA.8 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;                  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOE, &GPIO_InitStructure);                                         //根据设定参数初始化GPIOA.8
}

void Lie_Output(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
       
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);         //使能PA,PD端口时钟
       
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;                                 //LED0-->PA.8 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOE, &GPIO_InitStructure);                                         //根据设定参数初始化GPIOA.8
}
unsigned char GetKey(void)
{
       
        unsigned char keyvalue = 0;
        uint16_t hangvalue=0,lievalue=0;
       
// 第1回合第1步
        KEY_Init();
        delay_us(20);
        GPIO_ResetBits(GPIOE,GPIO_Pin_6);                                                  //PE.6 输出低
        GPIO_ResetBits(GPIOE,GPIO_Pin_5);                                                  //PE.5 输出低
        GPIO_ResetBits(GPIOE,GPIO_Pin_4);                                                  //PE.4 输出低
        GPIO_ResetBits(GPIOE,GPIO_Pin_3);                                                  //PE.3 输出低
       
       
        hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
        if (hangvalue != 0x3f)// 从IO口输入,读IO口
        {
        // 读出的不是0x0f说明有按键被按下
        // 第1回合第2步:读出端口从读出值来判断是哪一行
                delay_ms(20);
                GPIO_ResetBits(GPIOE,GPIO_Pin_6);                                                  //PE.6 输出低
                GPIO_ResetBits(GPIOE,GPIO_Pin_5);                                                  //PE.5 输出低
                GPIO_ResetBits(GPIOE,GPIO_Pin_4);                                                  //PE.4 输出低
                GPIO_ResetBits(GPIOE,GPIO_Pin_3);                                                  //PE.3 输出低
               
               
                hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
                if (hangvalue != 0x3f)// 从IO口输入,读IO口
                {
                        Hang_Output();
                        Lie_Input();
                        delay_us(20);
                // 第一回合中算出行号
                        switch (hangvalue)
                        {
                                case 0x1F:
                                               
                                                GPIO_ResetBits(GPIOB,GPIO_Pin_9);
                                                lievalue=((GPIO_ReadInputData(GPIOE)&0x78)>>3);
                                                switch(lievalue)
                                                {
                                                        case 0x07:
                                                                keyvalue=4;
                                                                break;
                                                        case 0x0b:
                                                                keyvalue=9;
                                                                break;
                                                        case 0x0d:
                                                                keyvalue=14;
                                                                break;
                                                        case 0x0e:
                                                                keyvalue=20;
                                                                break;
                                                        default :
                                                                break;
                                                }
                                        break;
                                case 0x2F:
                                               
                                                GPIO_ResetBits(GPIOB,GPIO_Pin_8);
                                                lievalue=((GPIO_ReadInputData(GPIOE)&0x78)>>3);
                                                switch(lievalue)
                                                {
                                                        case 0x07:
                                                                keyvalue=5;
                                                                break;
                                                        case 0x0b:
                                                                keyvalue=10;
                                                                break;
                                                        case 0x0d:
                                                                keyvalue=15;
                                                                break;
                                                        case 0x0e:
                                                                keyvalue=21;
                                                                break;
                                                        default :
                                                                break;
                                                }
                                        break;
                                case 0x37:
                                               
                                                GPIO_ResetBits(GPIOB,GPIO_Pin_7);
                                                lievalue=((GPIO_ReadInputData(GPIOE)&0x78)>>3);
                                                switch(lievalue)
                                                {
                                                        case 0x07:
                                                                keyvalue=6;
                                                                break;
                                                        case 0x0b:
                                                                keyvalue=11;
                                                                break;
                                                        case 0x0d:
                                                                keyvalue=16;
                                                                break;
                                                        case 0x0e:
                                                                keyvalue=22;
                                                                break;
                                                        default :
                                                                break;
                                                }
                                        break;
                                case 0x3B:
                                               
                                                GPIO_ResetBits(GPIOE,GPIO_Pin_2);
                                                lievalue=((GPIO_ReadInputData(GPIOE)&0x78)>>3);
                                                switch(lievalue)
                                                {
                                                        case 0x07:
                                                                keyvalue=1;
                                                                break;
                                                        case 0x0b:
                                                                keyvalue=6;
                                                                break;
                                                        case 0x0d:
                                                                keyvalue=11;
                                                                break;
                                                        case 0x0e:
                                                                keyvalue=17;
                                                                break;
                                                        default :
                                                                break;
                                                }
                                        break;
                                case 0x3D:
                                               
                                                GPIO_ResetBits(GPIOE,GPIO_Pin_1);
                                                lievalue=((GPIO_ReadInputData(GPIOE)&0x78)>>3);
                                                switch(lievalue)
                                                {
                                                        case 0x07:
                                                                keyvalue=2;
                                                                break;
                                                        case 0x0b:
                                                                keyvalue=7;
                                                                break;
                                                        case 0x0d:
                                                                keyvalue=12;
                                                                break;
                                                        case 0x0e:
                                                                keyvalue=18;
                                                                break;
                                                        default :
                                                                break;
                                                }
                                        break;
                                case 0x3E:
                                               
                                                GPIO_ResetBits(GPIOE,GPIO_Pin_0);
                                                lievalue=((GPIO_ReadInputData(GPIOE)&0x78)>>3);
                                                switch(lievalue)
                                                {
                                                        case 0x07:
                                                                keyvalue=3;
                                                                break;
                                                        case 0x0b:
                                                                keyvalue=8;
                                                                break;
                                                        case 0x0d:
                                                                keyvalue=13;
                                                                break;
                                                        case 0x0e:
                                                                keyvalue=19;
                                                                break;
                                                        default :
                                                                break;
                                                }
                                        break;
                                default: break;
                               
                        }
                        Hang_Input();
                        Lie_Output();
                        delay_us(20);
                        GPIO_ResetBits(GPIOE,GPIO_Pin_6);                                                  //PE.6 输出低
                        GPIO_ResetBits(GPIOE,GPIO_Pin_5);                                                  //PE.5 输出低
                        GPIO_ResetBits(GPIOE,GPIO_Pin_4);                                                  //PE.4 输出低
                        GPIO_ResetBits(GPIOE,GPIO_Pin_3);                                                  //PE.3 输出低
                       
                        hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
                        while (hangvalue != 0x3f)
                        {
                               
                                hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
                        }
                        return keyvalue;
                }
                return 0;
        }
        return 0;
}
大神看看,哪里有问题?谢谢!

使用特权

评论回复
沙发
LcwSwust| | 2020-6-18 11:26 | 只看该作者
本帖最后由 LcwSwust 于 2020-6-18 11:28 编辑

代码写得太冗长了。
比如:GPIO_ResetBits(GPIOE,GPIO_Pin_6);      GPIO_ResetBits(GPIOE,GPIO_Pin_5);......
可以写成一句:GPIO_ResetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_5 | GPIO_Pin_4 | GPIO_Pin_3);
有时候还可以直接操作寄存器提高效率。
你的思路是:所有行(行和列好像是反的)置低,检测列线有变低就进行下一步,检测是哪一行;
问题在于如果进行下一步前按键放开了,case不成立keyvalue就为0。

其实我更喜欢这种方式:定时查询,逐行置低,检测列线的电平。按键还是要注意加消抖的,比如检测到多次keyvalue为0才认为它真的是0.

使用特权

评论回复
板凳
Cjy_JDxy|  楼主 | 2020-6-18 11:49 | 只看该作者
LcwSwust 发表于 2020-6-18 11:26
代码写得太冗长了。
比如:GPIO_ResetBits(GPIOE,GPIO_Pin_6);      GPIO_ResetBits(GPIOE,GPIO_Pin_5);... ...

谢谢!初始化时keyvalue赋初值0了。
加延时消抖了。

使用特权

评论回复
地板
Cjy_JDxy|  楼主 | 2020-6-18 11:50 | 只看该作者
我又改了一下:
#include "key.h"
#include "delay.h"

//////////////////////////////////////////////////////////////////////////////////         
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK miniSTM32开发板
//LED驱动代码          
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/9/2
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved                                                                          
//////////////////////////////////////////////////////////////////////////////////           

//初始化PA8和PD2为输出口.并使能这两个口的时钟                    
//LED IO初始化
void KEY_Init(void)
{

GPIO_InitTypeDef  GPIO_InitStructure;
       
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);         //使能PA,PD端口时钟
       
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;                                 //LED0-->PA.8 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOE, &GPIO_InitStructure);                                         //根据设定参数初始化GPIOA.8

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 ;                                 //LED0-->PA.8 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;                  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOE, &GPIO_InitStructure);                                         //根据设定参数初始化GPIOA.8
       
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;                             //LED1-->PD.2 端口配置, 推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;                  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);                                           //推挽输出 ,IO口速度为50MHz
       

}
void Hang_Output(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
       
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);         //使能PA,PD端口时钟
       


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 ;                                 //LED0-->PA.8 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOE, &GPIO_InitStructure);                                         //根据设定参数初始化GPIOA.8
       
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;                             //LED1-->PD.2 端口配置, 推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);                                           //推挽输出 ,IO口速度为50MHz
       
}
void Hang_Input(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
       
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);         //使能PA,PD端口时钟
       


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 ;                                 //LED0-->PA.8 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;                  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOE, &GPIO_InitStructure);                                         //根据设定参数初始化GPIOA.8
       
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;                             //LED1-->PD.2 端口配置, 推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;                  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);                                           //推挽输出 ,IO口速度为50MHz
       
}
void Lie_Input(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
       
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);         //使能PA,PD端口时钟
       
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;                                 //LED0-->PA.8 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;                  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOE, &GPIO_InitStructure);                                         //根据设定参数初始化GPIOA.8
}

void Lie_Output(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
       
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);         //使能PA,PD端口时钟
       
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;                                 //LED0-->PA.8 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOE, &GPIO_InitStructure);                                         //根据设定参数初始化GPIOA.8
}
unsigned char GetKey(void)
{
       
        unsigned char keyvalue = 0;
        uint16_t hangvalue=0;
       
// 第1回合第1步
        KEY_Init();
        delay_us(20);
        GPIO_ResetBits(GPIOE,GPIO_Pin_6);                                                  //PE.6,5,4,3 输出低
        GPIO_SetBits(GPIOE,GPIO_Pin_5);                
        GPIO_SetBits(GPIOE,GPIO_Pin_4);                
        GPIO_SetBits(GPIOE,GPIO_Pin_3);                
       
       
        hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0300)>>5);
        if (hangvalue != 0x1f)// 从IO口输入,读IO口
        {
        // 读出的不是0x0f说明有按键被按下
        // 第1回合第2步:读出端口从读出值来判断是哪一行
                delay_ms(20);
                GPIO_ResetBits(GPIOE,GPIO_Pin_6);                                                  //PE.6,5,4,3 输出低
                GPIO_SetBits(GPIOE,GPIO_Pin_5);                
                GPIO_SetBits(GPIOE,GPIO_Pin_4);                
                GPIO_SetBits(GPIOE,GPIO_Pin_3);                                          
               
               
                hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0300)>>5);
                if (hangvalue != 0x1f)// 从IO口输入,读IO口
                {
                        Hang_Output();
                        Lie_Input();
                        delay_us(20);
                // 第一回合中算出行号
                        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;
                               
                        }
                        Hang_Input();
                        Lie_Output();
                        delay_us(20);
                        GPIO_ResetBits(GPIOE,GPIO_Pin_6 );                                                  //PE.6,5,4,3 输出低
                        GPIO_SetBits(GPIOE, GPIO_Pin_5 );
                        GPIO_SetBits(GPIOE, GPIO_Pin_4 );
                        GPIO_SetBits(GPIOE, GPIO_Pin_3 );
                        hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0300)>>5);
                        while (hangvalue != 0x1f)
                        {
                               
                                hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0300)>>5);
                        }
                       
                        //return keyvalue;
                }
               
        }
        KEY_Init();
        delay_us(20);
        GPIO_SetBits(GPIOE,GPIO_Pin_6 );                                                  //PE.6,5,4,3 输出低
        GPIO_ResetBits(GPIOE, GPIO_Pin_5 );
        GPIO_SetBits(GPIOE, GPIO_Pin_4 );
        GPIO_SetBits(GPIOE, GPIO_Pin_3 );
       
        hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0300)>>5);
        if (hangvalue != 0x1f)// 从IO口输入,读IO口
        {
        // 读出的不是0x0f说明有按键被按下
        // 第1回合第2步:读出端口从读出值来判断是哪一行
                delay_ms(20);
                GPIO_SetBits(GPIOE,GPIO_Pin_6 );                                                  //PE.6,5,4,3 输出低
                GPIO_ResetBits(GPIOE, GPIO_Pin_5 );
                GPIO_SetBits(GPIOE, GPIO_Pin_4 );
                GPIO_SetBits(GPIOE, GPIO_Pin_3 );
               
               
                hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0300)>>5);
                if (hangvalue != 0x1f)// 从IO口输入,读IO口
                {
                        Hang_Output();
                        Lie_Input();
                        delay_us(20);
                // 第一回合中算出行号
                        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;
                               
                        }
                        Hang_Input();
                        Lie_Output();
                        delay_us(20);
                        GPIO_SetBits(GPIOE,GPIO_Pin_6 );                                                  //PE.6,5,4,3 输出低
                        GPIO_ResetBits(GPIOE, GPIO_Pin_5 );
                        GPIO_SetBits(GPIOE, GPIO_Pin_4 );
                        GPIO_SetBits(GPIOE, GPIO_Pin_3 );
                        hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0300)>>5);
                        while (hangvalue != 0x1f)
                        {
                               
                                hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0300)>>5);
                        }
                       
                       
                        //return keyvalue;
                }
               
        }
        KEY_Init();
        delay_us(20);
       
        GPIO_SetBits(GPIOE,GPIO_Pin_6 );                                                  //PE.6,5,4,3 输出低
        GPIO_SetBits(GPIOE, GPIO_Pin_5 );
        GPIO_ResetBits(GPIOE, GPIO_Pin_4 );
        GPIO_SetBits(GPIOE, GPIO_Pin_3 );
       
       
        hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
        if (hangvalue != 0x3f)// 从IO口输入,读IO口
        {
        // 读出的不是0x0f说明有按键被按下
        // 第1回合第2步:读出端口从读出值来判断是哪一行
                delay_ms(20);
                GPIO_SetBits(GPIOE,GPIO_Pin_6 );                                                  //PE.6,5,4,3 输出低
                GPIO_SetBits(GPIOE, GPIO_Pin_5 );
                GPIO_ResetBits(GPIOE, GPIO_Pin_4 );
                GPIO_SetBits(GPIOE, GPIO_Pin_3 );
               
                hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
                if (hangvalue != 0x3f)// 从IO口输入,读IO口
                {
                        Hang_Output();
                        Lie_Input();
                        delay_us(20);
                // 第一回合中算出行号
                        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;
                               
                        }
                        Hang_Input();
                        Lie_Output();
                        delay_us(20);
                        GPIO_SetBits(GPIOE,GPIO_Pin_6 );                                                  //PE.6,5,4,3 输出低
                        GPIO_SetBits(GPIOE, GPIO_Pin_5 );
                        GPIO_ResetBits(GPIOE, GPIO_Pin_4 );
                        GPIO_SetBits(GPIOE, GPIO_Pin_3 );
                       
                       
                       
                        hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
                        while (hangvalue != 0x3f)
                        {
                               
                                hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
                        }
                       
                        //return keyvalue;
                }
               
        }
        KEY_Init();
        delay_us(20);
        GPIO_SetBits(GPIOE,GPIO_Pin_6 );                                                  //PE.6,5,4,3 输出低
        GPIO_SetBits(GPIOE, GPIO_Pin_5 );
        GPIO_SetBits(GPIOE, GPIO_Pin_4 );
        GPIO_ResetBits(GPIOE, GPIO_Pin_3 );
                       
       
        hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
        if (hangvalue != 0x3f)// 从IO口输入,读IO口
        {
        // 读出的不是0x0f说明有按键被按下
        // 第1回合第2步:读出端口从读出值来判断是哪一行
                delay_ms(20);
                GPIO_SetBits(GPIOE,GPIO_Pin_6 );                                                  //PE.6,5,4,3 输出低
                GPIO_SetBits(GPIOE, GPIO_Pin_5 );
                GPIO_SetBits(GPIOE, GPIO_Pin_4 );
                GPIO_ResetBits(GPIOE, GPIO_Pin_3 );
               
                hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
                if (hangvalue != 0x3f)// 从IO口输入,读IO口
                {
                        Hang_Output();
                        Lie_Input();
                        delay_us(20);
                // 第一回合中算出行号
                        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;
                               
                        }
                        Hang_Input();
                        Lie_Output();
                        delay_us(20);
                        GPIO_SetBits(GPIOE,GPIO_Pin_6 );                                                  //PE.6,5,4,3 输出低
                        GPIO_SetBits(GPIOE, GPIO_Pin_5 );
                        GPIO_SetBits(GPIOE, GPIO_Pin_4 );
                        GPIO_ResetBits(GPIOE, GPIO_Pin_3 );
                       
                       
                        hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
                        while (hangvalue != 0x3f)
                        {
                               
                                hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
                        }
                       
                        //return keyvalue;
                }
               
        }
        return keyvalue;;
}

好了一点,没那么频繁了,还有点问题。

使用特权

评论回复
5
hwpga| | 2020-6-18 14:27 | 只看该作者
这代码写的跟个diy似的
你老板会不会被你气到吐血

使用特权

评论回复
6
Cjy_JDxy|  楼主 | 2020-6-18 15:08 | 只看该作者
hwpga 发表于 2020-6-18 14:27
这代码写的跟个diy似的
你老板会不会被你气到吐血

我们老板不懂程序

使用特权

评论回复
7
gx_huang| | 2020-6-18 15:20 | 只看该作者
可怜的老板!
按键扫描判断键值,教科书上有典型例子,不过实际使用,大家肯定会修改,适合实时多任务。
我一般是定时调用按键程序,比如5毫秒调用一次,状态机方式判断当前状态,判断是否有键按下,按下时间是否达到消抖时间,是否有按键松开,判断后赋键值。
按键定时处理程序,只要定时调用即可(可以大循环调用,也可以定时器中断调用),执行完本次任务立即退出,和其它程序无关,其它程序只要判断键值即可。

使用特权

评论回复
8
Cjy_JDxy|  楼主 | 2020-6-18 15:21 | 只看该作者
gx_huang 发表于 2020-6-18 15:20
可怜的老板!
按键扫描判断键值,教科书上有典型例子,不过实际使用,大家肯定会修改,适合实时多任务。
我 ...

谢谢!你能给我一个例子吗?

使用特权

评论回复
9
Cjy_JDxy|  楼主 | 2020-6-18 15:22 | 只看该作者
gx_huang 发表于 2020-6-18 15:20
可怜的老板!
按键扫描判断键值,教科书上有典型例子,不过实际使用,大家肯定会修改,适合实时多任务。
我 ...

说实话,你说的我都能理解。可是程序有问题

使用特权

评论回复
10
gx_huang| | 2020-6-18 16:17 | 只看该作者
Cjy_JDxy 发表于 2020-6-18 15:22
说实话,你说的我都能理解。可是程序有问题

其实按键扫描,先要理解硬件原理,先后顺序的逻辑。
你的扫描输入是外接上拉的,扫描输出,我粗看是推挽输出的,就这个细节,就是有问题的,如果多个按键按下,很容逻辑冲突的,搞不好硬件都容易坏。
如果不理解硬件原理,不了解MCU内部中断原理,很容易出现问题,比如反复多次进入中断。

使用特权

评论回复
11
gx_huang| | 2020-6-18 16:24 | 只看该作者
如果你的按键程序里包含延时函数,而且延时达到20毫秒,则这个程序就不是很好的程序。
这样的程序,很可能影响其它程序的实时运行。
如果不考虑功耗,不考虑按键唤醒,直接周期检测按键即可。这个周期等于消抖时间即可。

使用特权

评论回复
12
Cjy_JDxy|  楼主 | 2020-6-18 18:35 | 只看该作者
gx_huang 发表于 2020-6-18 16:17
其实按键扫描,先要理解硬件原理,先后顺序的逻辑。
你的扫描输入是外接上拉的,扫描输出,我粗看是推挽 ...

谢谢!如果推挽输出有问题,那应该怎么配置呢?

使用特权

评论回复
13
mintspring| | 2020-6-18 23:45 | 只看该作者
貌似比我当年写的 长啊。全部用准双向模式呢?

使用特权

评论回复
14
dog_xin| | 2020-6-19 07:31 | 只看该作者
一个键盘程序没有这么长的程序的。我的经验:在大循环中,10ms运行一个键盘程序,对每个键进行扫描,某一时间,必须是唯一的一个键才有效,防止误判,一次扫描后得到键值。20ms后运行两次,与后,就是按键了。更进一步,记录前一次的按键,现在的按键,可以判断刚按键和刚释放键,有几个键同时按下了,加入计时,可以判断短按长按和双击。

使用特权

评论回复
15
Cjy_JDxy|  楼主 | 2020-6-19 08:01 | 只看该作者
mintspring 发表于 2020-6-18 23:45
貌似比我当年写的 长啊。全部用准双向模式呢?

准双向模式是哪种模式呀,开漏吗?
STM32哪种模式是准双向啊?

使用特权

评论回复
16
Cjy_JDxy|  楼主 | 2020-6-19 08:03 | 只看该作者
dog_xin 发表于 2020-6-19 07:31
一个键盘程序没有这么长的程序的。我的经验:在大循环中,10ms运行一个键盘程序,对每个键进行扫描,某一时 ...

谢谢!那你说键盘程序应该怎么写呢?我这个22个按键。

使用特权

评论回复
17
gx_huang| | 2020-6-19 08:18 | 只看该作者
Cjy_JDxy 发表于 2020-6-18 18:35
谢谢!如果推挽输出有问题,那应该怎么配置呢?

扫描输出要线与的,那肯定是OD输出了。
无论什么样的按键程序,我全是自己编的,根据系统需要编程,从来没有啥问题的。
关键是要知道硬件原理,如何消抖,波形关系。这个软件并不难,只要理解硬件原理。
你4个扫描输出全是推挽输出,就知道你不懂硬件,搞单片机,不懂硬件是硬伤。

使用特权

评论回复
18
hwpga| | 2020-6-19 08:22 | 只看该作者

矩形按键按下的有效时间是32MS-40MS
早期的硬件芯片都是这么设计的



使用特权

评论回复
19
hwpga| | 2020-6-19 08:48 | 只看该作者
本帖最后由 hwpga 于 2020-6-19 08:50 编辑

使用特权

评论回复
20
Cjy_JDxy|  楼主 | 2020-6-19 12:02 | 只看该作者
gx_huang 发表于 2020-6-19 08:18
扫描输出要线与的,那肯定是OD输出了。
无论什么样的按键程序,我全是自己编的,根据系统需要编程,从来 ...

谢谢!我试试

使用特权

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

本版积分规则

个人签名:绿水本无忧因风皱面,青山原不老为雪白头。

553

主题

3520

帖子

19

粉丝