打印
[STM32F1]

矩阵键盘程序问题

[复制链接]
楼主: Cjy_JDxy
手机看帖
扫描二维码
随时随地手机跟帖
21
kingkits| | 2020-6-19 13:19 | 只看该作者 回帖奖励 |倒序浏览
你可以考虑这样,先一组线A全拉低(置0)读另一组线B,然后把另一组线B拉低,读先一组线A,两个数据就能解析到按键,为防止抖动,需要记录解析的按键,然后间隔4-10ms,再检测一次,两次的数据相同才能确认按键按下,按键按下后,如果需要检测释放,就需要连续检测,间隔相同。还可以增加一个变量记录按键按下的时间(检测的数据连续相同的次数)。就可以区分长按键了。

使用特权

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

开漏的话,列线接上拉电阻啦。行线没接上拉电阻,怎么办呀?谢谢

使用特权

评论回复
23
gx_huang| | 2020-6-19 14:54 | 只看该作者
Cjy_JDxy 发表于 2020-6-19 13:56
开漏的话,列线接上拉电阻啦。行线没接上拉电阻,怎么办呀?谢谢

假设行是输出,列是输入,输出OD,输入上拉,这你好好理解。
按键按下,有输出0,相关的输入也是0,这难道还不理解?

使用特权

评论回复
24
gx_huang| | 2020-6-19 14:56 | 只看该作者

凡事不能靠试呀,都可以预先想好的,不知道原理,不知道要试多少回

使用特权

评论回复
25
Cjy_JDxy|  楼主 | 2020-6-19 16:13 | 只看该作者
gx_huang 发表于 2020-6-19 14:54
假设行是输出,列是输入,输出OD,输入上拉,这你好好理解。
按键按下,有输出0,相关的输入也是0,这难 ...

第2句我理解。
第一句,行没接上拉,可以输出低,无法输出高。

使用特权

评论回复
26
Cjy_JDxy|  楼主 | 2020-6-19 16:14 | 只看该作者
gx_huang 发表于 2020-6-19 14:56
凡事不能靠试呀,都可以预先想好的,不知道原理,不知道要试多少回

我只写过51的矩阵键盘,STM32的没写过,不太一样。

使用特权

评论回复
27
gx_huang| | 2020-6-19 16:45 | 只看该作者
Cjy_JDxy 发表于 2020-6-19 16:13
第2句我理解。
第一句,行没接上拉,可以输出低,无法输出高。

线与,当然不需要输出高,如何可以输出高,不就打架了,一个高一个低打架呀。
输出高就是高阻。

使用特权

评论回复
28
gx_huang| | 2020-6-19 16:45 | 只看该作者
Cjy_JDxy 发表于 2020-6-19 16:14
我只写过51的矩阵键盘,STM32的没写过,不太一样。

有些51也有推挽输出,也会打架的,51和STM32没有本质区别

使用特权

评论回复
29
Cjy_JDxy|  楼主 | 2020-6-19 17:56 | 只看该作者
gx_huang 发表于 2020-6-19 16:45
线与,当然不需要输出高,如何可以输出高,不就打架了,一个高一个低打架呀。
输出高就是高阻。 ...

谢谢!我再想想

使用特权

评论回复
30
Cjy_JDxy|  楼主 | 2020-6-19 18:48 | 只看该作者
gx_huang 发表于 2020-6-19 16:45
有些51也有推挽输出,也会打架的,51和STM32没有本质区别
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_OD;                  //推挽输出

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_OD;                  //推挽输出
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_OD;                  //推挽输出
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_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_OD;                  //推挽输出
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_Pin_4 | 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_Pin_4 | 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_Pin_4 | 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);
                        }
                        delay_ms(2);
                        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_ResetBits(GPIOE, GPIO_Pin_5 );
        GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_4 | 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_5 );
                GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_4 | 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_ResetBits(GPIOE, GPIO_Pin_5 );
                        GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_4 | 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_ResetBits(GPIOE, GPIO_Pin_4 );
        GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_3 | GPIO_Pin_5);
       
       
        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_4 );
                GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_3 | GPIO_Pin_5);
               
                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_ResetBits(GPIOE, GPIO_Pin_4 );
                        GPIO_SetBits(GPIOE,GPIO_Pin_6 | GPIO_Pin_3 | GPIO_Pin_5);
                       
                       
                       
                        hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
                        while (hangvalue != 0x3f)
                        {
                               
                                hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
                        }
                        delay_ms(2);
                        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 | GPIO_Pin_4 | GPIO_Pin_5);
        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 | GPIO_Pin_4 | GPIO_Pin_5);
                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 | GPIO_Pin_4 | GPIO_Pin_5);
                        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 0;
}
输出模式都改成开漏了。大神帮我看看,那儿还有问题?谢谢!

使用特权

评论回复
31
gx_huang| | 2020-6-20 10:10 | 只看该作者
1、没看以前的代码,既然是OD输出,就不需要行列一会输出一会输入的,也不需要在按键判断过程中反复初始化。
   主要主程序中初始化了行是OD输出,列是输入即可,其它地方无需再次初始化。
  其它地方需要的操作就是行输出,读出列输入即可,不需要反复初始化。
2、代码和注释要一致,这是对自己的尊重,也是对别人的尊重。不要的代码删除掉,很多冗余代码。
   行已经输出0111了,延时后又输出0111,这是画蛇添足。
   已经得到了键值,又判断是否有按键,并延时,不知道啥目的。

使用特权

评论回复
32
gx_huang| | 2020-6-20 10:16 | 只看该作者
从逻辑上考虑,你这个程序不适合实时多任务,延时20毫秒,影响多少其它任务呀。
要考虑程序效率,按键扫描程序,要去掉所有行列初始化的代码。
平时所有行输出为0,进入按键程序,判断是否有列输入被拉低,没有立即退出,这样效率最高。
有列输入别拉低,才0111、1011、1101、1110依次行输出,判断列输入。
退出行列扫描程序,行输出0000,方便下次按键判断,或者中断唤醒。
你的程序,像女人的裹脚布呀。

使用特权

评论回复
33
gx_huang| | 2020-6-20 10:23 | 只看该作者
你本来行输出0111,中途又初始化了行列端口,还得分析行输出是否变化了,没有必要插入无关的、没有必要的代码。
难道你怕GPIO状态中途紊乱了,需要反复初始化?

使用特权

评论回复
34
gx_huang| | 2020-6-20 10:24 | 只看该作者
不同初始化代码,列输入,一会高阻输入一会上拉输入。
混乱不堪!

使用特权

评论回复
35
Cjy_JDxy|  楼主 | 2020-6-20 11:04 | 只看该作者
gx_huang 发表于 2020-6-20 10:10
1、没看以前的代码,既然是OD输出,就不需要行列一会输出一会输入的,也不需要在按键判断过程中反复初始化 ...

谢谢!
2.
我是一行一行判断的。

使用特权

评论回复
36
Cjy_JDxy|  楼主 | 2020-6-20 11:05 | 只看该作者
gx_huang 发表于 2020-6-20 10:16
从逻辑上考虑,你这个程序不适合实时多任务,延时20毫秒,影响多少其它任务呀。
要考虑程序效率,按键扫描 ...

我是菜鸟

使用特权

评论回复
37
一叶倾城wwq| | 2020-6-20 14:00 | 只看该作者
本帖最后由 一叶倾城wwq 于 2020-6-20 14:10 编辑

直接讨论思路就好了,周末实在看不了代码楼主用的中断法吗?没怎么看代码,建议分时查询就好了,有确定的输出行,检测列上的电平来判断键值,很清晰明了的思路,IO口也不用反复在输出和输入之间切换,我看这个原理图,你可以一行一行的调试先,代码逻辑出问题的话把多余的屏蔽掉,先一点点调

使用特权

评论回复
评论
一叶倾城wwq 2020-6-20 14:01 回复TA
惭愧,刚进论坛时也很受大家的帮助 
38
keaibukelian| | 2020-7-9 14:04 | 只看该作者
延时去抖是一个经验值?会不会不可靠

使用特权

评论回复
39
labasi| | 2020-7-9 14:04 | 只看该作者
讨论的非常热烈

使用特权

评论回复
40
paotangsan| | 2020-7-9 14:04 | 只看该作者
硬件去抖比较好

使用特权

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

本版积分规则