搜索
ST MCU Finder
安装免费手机应用,
寻找理想的ST MCU

[STM32F1] 矩阵键盘程序问题

[复制链接]
943|43
 楼主 | 2020-6-18 09:34 | 显示全部楼层 |阅读模式
我写了个矩阵键盘程序,有点问题,有时按下一个按键,返回两次键值,有时返回0(没有检测到按键)
我调试,返回键值,通过网口发送到网络调试助手。
原理图:
5.jpg
程序:
  1. //初始化PA8和PD2为输出口.并使能这两个口的时钟                    
  2. //LED IO初始化
  3. void KEY_Init(void)
  4. {

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

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

  23. }
  24. void Hang_Output(void)
  25. {
  26.         GPIO_InitTypeDef  GPIO_InitStructure;
  27.        
  28. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);         //使能PA,PD端口时钟
  29.        


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


  47. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 ;                                 //LED0-->PA.8 端口配置
  48. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;                  //推挽输出
  49. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
  50. GPIO_Init(GPIOE, &GPIO_InitStructure);                                         //根据设定参数初始化GPIOA.8
  51.        
  52. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;                             //LED1-->PD.2 端口配置, 推挽输出
  53. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;                  //推挽输出
  54. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
  55. GPIO_Init(GPIOB, &GPIO_InitStructure);                                           //推挽输出 ,IO口速度为50MHz
  56.        
  57. }
  58. void Lie_Input(void)
  59. {
  60.         GPIO_InitTypeDef  GPIO_InitStructure;
  61.        
  62. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);         //使能PA,PD端口时钟
  63.        
  64. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;                                 //LED0-->PA.8 端口配置
  65. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;                  //推挽输出
  66. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
  67. GPIO_Init(GPIOE, &GPIO_InitStructure);                                         //根据设定参数初始化GPIOA.8
  68. }

  69. void Lie_Output(void)
  70. {
  71.         GPIO_InitTypeDef  GPIO_InitStructure;
  72.        
  73. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);         //使能PA,PD端口时钟
  74.        
  75. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;                                 //LED0-->PA.8 端口配置
  76. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
  77. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
  78. GPIO_Init(GPIOE, &GPIO_InitStructure);                                         //根据设定参数初始化GPIOA.8
  79. }
  80. unsigned char GetKey(void)
  81. {
  82.        
  83.         unsigned char keyvalue = 0;
  84.         uint16_t hangvalue=0,lievalue=0;
  85.        
  86. // 第1回合第1步
  87.         KEY_Init();
  88.         delay_us(20);
  89.         GPIO_ResetBits(GPIOE,GPIO_Pin_6);                                                  //PE.6 输出低
  90.         GPIO_ResetBits(GPIOE,GPIO_Pin_5);                                                  //PE.5 输出低
  91.         GPIO_ResetBits(GPIOE,GPIO_Pin_4);                                                  //PE.4 输出低
  92.         GPIO_ResetBits(GPIOE,GPIO_Pin_3);                                                  //PE.3 输出低
  93.        
  94.        
  95.         hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
  96.         if (hangvalue != 0x3f)// 从IO口输入,读IO口
  97.         {
  98.         // 读出的不是0x0f说明有按键被按下
  99.         // 第1回合第2步:读出端口从读出值来判断是哪一行
  100.                 delay_ms(20);
  101.                 GPIO_ResetBits(GPIOE,GPIO_Pin_6);                                                  //PE.6 输出低
  102.                 GPIO_ResetBits(GPIOE,GPIO_Pin_5);                                                  //PE.5 输出低
  103.                 GPIO_ResetBits(GPIOE,GPIO_Pin_4);                                                  //PE.4 输出低
  104.                 GPIO_ResetBits(GPIOE,GPIO_Pin_3);                                                  //PE.3 输出低
  105.                
  106.                
  107.                 hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
  108.                 if (hangvalue != 0x3f)// 从IO口输入,读IO口
  109.                 {
  110.                         Hang_Output();
  111.                         Lie_Input();
  112.                         delay_us(20);
  113.                 // 第一回合中算出行号
  114.                         switch (hangvalue)
  115.                         {
  116.                                 case 0x1F:
  117.                                                
  118.                                                 GPIO_ResetBits(GPIOB,GPIO_Pin_9);
  119.                                                 lievalue=((GPIO_ReadInputData(GPIOE)&0x78)>>3);
  120.                                                 switch(lievalue)
  121.                                                 {
  122.                                                         case 0x07:
  123.                                                                 keyvalue=4;
  124.                                                                 break;
  125.                                                         case 0x0b:
  126.                                                                 keyvalue=9;
  127.                                                                 break;
  128.                                                         case 0x0d:
  129.                                                                 keyvalue=14;
  130.                                                                 break;
  131.                                                         case 0x0e:
  132.                                                                 keyvalue=20;
  133.                                                                 break;
  134.                                                         default :
  135.                                                                 break;
  136.                                                 }
  137.                                         break;
  138.                                 case 0x2F:
  139.                                                
  140.                                                 GPIO_ResetBits(GPIOB,GPIO_Pin_8);
  141.                                                 lievalue=((GPIO_ReadInputData(GPIOE)&0x78)>>3);
  142.                                                 switch(lievalue)
  143.                                                 {
  144.                                                         case 0x07:
  145.                                                                 keyvalue=5;
  146.                                                                 break;
  147.                                                         case 0x0b:
  148.                                                                 keyvalue=10;
  149.                                                                 break;
  150.                                                         case 0x0d:
  151.                                                                 keyvalue=15;
  152.                                                                 break;
  153.                                                         case 0x0e:
  154.                                                                 keyvalue=21;
  155.                                                                 break;
  156.                                                         default :
  157.                                                                 break;
  158.                                                 }
  159.                                         break;
  160.                                 case 0x37:
  161.                                                
  162.                                                 GPIO_ResetBits(GPIOB,GPIO_Pin_7);
  163.                                                 lievalue=((GPIO_ReadInputData(GPIOE)&0x78)>>3);
  164.                                                 switch(lievalue)
  165.                                                 {
  166.                                                         case 0x07:
  167.                                                                 keyvalue=6;
  168.                                                                 break;
  169.                                                         case 0x0b:
  170.                                                                 keyvalue=11;
  171.                                                                 break;
  172.                                                         case 0x0d:
  173.                                                                 keyvalue=16;
  174.                                                                 break;
  175.                                                         case 0x0e:
  176.                                                                 keyvalue=22;
  177.                                                                 break;
  178.                                                         default :
  179.                                                                 break;
  180.                                                 }
  181.                                         break;
  182.                                 case 0x3B:
  183.                                                
  184.                                                 GPIO_ResetBits(GPIOE,GPIO_Pin_2);
  185.                                                 lievalue=((GPIO_ReadInputData(GPIOE)&0x78)>>3);
  186.                                                 switch(lievalue)
  187.                                                 {
  188.                                                         case 0x07:
  189.                                                                 keyvalue=1;
  190.                                                                 break;
  191.                                                         case 0x0b:
  192.                                                                 keyvalue=6;
  193.                                                                 break;
  194.                                                         case 0x0d:
  195.                                                                 keyvalue=11;
  196.                                                                 break;
  197.                                                         case 0x0e:
  198.                                                                 keyvalue=17;
  199.                                                                 break;
  200.                                                         default :
  201.                                                                 break;
  202.                                                 }
  203.                                         break;
  204.                                 case 0x3D:
  205.                                                
  206.                                                 GPIO_ResetBits(GPIOE,GPIO_Pin_1);
  207.                                                 lievalue=((GPIO_ReadInputData(GPIOE)&0x78)>>3);
  208.                                                 switch(lievalue)
  209.                                                 {
  210.                                                         case 0x07:
  211.                                                                 keyvalue=2;
  212.                                                                 break;
  213.                                                         case 0x0b:
  214.                                                                 keyvalue=7;
  215.                                                                 break;
  216.                                                         case 0x0d:
  217.                                                                 keyvalue=12;
  218.                                                                 break;
  219.                                                         case 0x0e:
  220.                                                                 keyvalue=18;
  221.                                                                 break;
  222.                                                         default :
  223.                                                                 break;
  224.                                                 }
  225.                                         break;
  226.                                 case 0x3E:
  227.                                                
  228.                                                 GPIO_ResetBits(GPIOE,GPIO_Pin_0);
  229.                                                 lievalue=((GPIO_ReadInputData(GPIOE)&0x78)>>3);
  230.                                                 switch(lievalue)
  231.                                                 {
  232.                                                         case 0x07:
  233.                                                                 keyvalue=3;
  234.                                                                 break;
  235.                                                         case 0x0b:
  236.                                                                 keyvalue=8;
  237.                                                                 break;
  238.                                                         case 0x0d:
  239.                                                                 keyvalue=13;
  240.                                                                 break;
  241.                                                         case 0x0e:
  242.                                                                 keyvalue=19;
  243.                                                                 break;
  244.                                                         default :
  245.                                                                 break;
  246.                                                 }
  247.                                         break;
  248.                                 default: break;
  249.                                
  250.                         }
  251.                         Hang_Input();
  252.                         Lie_Output();
  253.                         delay_us(20);
  254.                         GPIO_ResetBits(GPIOE,GPIO_Pin_6);                                                  //PE.6 输出低
  255.                         GPIO_ResetBits(GPIOE,GPIO_Pin_5);                                                  //PE.5 输出低
  256.                         GPIO_ResetBits(GPIOE,GPIO_Pin_4);                                                  //PE.4 输出低
  257.                         GPIO_ResetBits(GPIOE,GPIO_Pin_3);                                                  //PE.3 输出低
  258.                        
  259.                         hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
  260.                         while (hangvalue != 0x3f)
  261.                         {
  262.                                
  263.                                 hangvalue=(GPIO_ReadInputData(GPIOE)&0x07)+((GPIO_ReadInputData(GPIOB)&0x0380)>>4);
  264.                         }
  265.                         return keyvalue;
  266.                 }
  267.                 return 0;
  268.         }
  269.         return 0;
  270. }
复制代码
大神看看,哪里有问题?谢谢!

使用特权

评论回复
| 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.

使用特权

评论回复
 楼主 | 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了。
加延时消抖了。

使用特权

评论回复
 楼主 | 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;;
}

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

使用特权

评论回复
| 2020-6-18 14:27 | 显示全部楼层
这代码写的跟个diy似的
你老板会不会被你气到吐血

使用特权

评论回复
 楼主 | 2020-6-18 15:08 | 显示全部楼层
hwpga 发表于 2020-6-18 14:27
这代码写的跟个diy似的
你老板会不会被你气到吐血

我们老板不懂程序

使用特权

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

使用特权

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

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

使用特权

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

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

使用特权

评论回复
| 2020-6-18 16:17 | 显示全部楼层
Cjy_JDxy 发表于 2020-6-18 15:22
说实话,你说的我都能理解。可是程序有问题

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

使用特权

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

使用特权

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

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

使用特权

评论回复
| 2020-6-18 23:45 | 显示全部楼层
貌似比我当年写的 长啊。全部用准双向模式呢?

使用特权

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

使用特权

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

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

使用特权

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

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

使用特权

评论回复
| 2020-6-19 08:18 | 显示全部楼层
Cjy_JDxy 发表于 2020-6-18 18:35
谢谢!如果推挽输出有问题,那应该怎么配置呢?

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

使用特权

评论回复
| 2020-6-19 08:22 | 显示全部楼层
A1.PNG
矩形按键按下的有效时间是32MS-40MS
早期的硬件芯片都是这么设计的



使用特权

评论回复
| 2020-6-19 08:48 | 显示全部楼层
本帖最后由 hwpga 于 2020-6-19 08:50 编辑

A2.PNG

使用特权

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

谢谢!我试试

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 我要提问 投诉建议 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

在线客服 快速回复 返回顶部 返回列表