STM32基础实验:矩阵按键

2023-10-06 02:28

文章目录

  • 1。组件矩阵键盘说明
  • 2。基于stm32f10c8t6基础实验矩阵按钮
  • (1)实验功能实现说明
  • (2) 矩阵键盘原理
  • (3) 代码部分
  • (4)效果展示
  • 3。总结与拓展
  • 附上参考链接和视频链接
  • 1。组件矩阵键盘说明

    本实验使用4*4矩阵键盘进行应用。为了节省引脚占用,矩阵键盘提供了多行多列排列成矩形组合的按键,因此它是矩阵按键或矩阵键盘。如图:
    矩阵键盘

    2。基于stm32f10c8t6基础实验矩阵按钮

    (1)实验功能实现说明

    本实验使用stm32和矩阵按钮来点亮LED并以二进制显示。例如,二进制的 0000 表示所有四个 LED 均关闭;二进制0001表示第四个LED亮,其他三个灭,以此类推;即1为开,0为关。 0.96英寸OLED显示反馈按键值(两个单位),如key1-01、key5--05、key11-11...;按键响应相应的键值和二进制显示LED。矩阵按钮实现方法: 1.响应相应的中断方法。 2、行列扫描法。本实验主要采用第二种方法,比较容易理解。

    (2) 矩阵键盘原理

    示意图

    走线和行扫描方式:
    矩阵按键扫描方式理解图如下:

    说明:左边理解为水平,右边的padding理解为水平。纵向理解。
    首先可以看到0x00ff,表示行与行中的按键没有接触。 0x00fe 垂直1110表示第一行接触,然后等待第一行的哪一列进行下一次接触。当第一行第一列同时响应触点时,表示第一行第一列对应的LED显示二进制0001,即第四个灯亮。
    0x00fd 垂直1101表示第二行接触,然后等待第二行哪一列进行下一次接触。当第二行第三列同时响应触点时,则表示第二行第三列对应的LED以二进制1101显示,即第一、二、四灯点亮。 ?三行第一、三列对应的LED以二进制0101显示,即第二、第四灯点亮。
    第四行同样可以得到。

    (3) 代码部分

    keys.c

    
    #include“stm32f10x.h”
    #include“keys.h”
    #include“延迟.h”
    //
    
    //**************************************************** **********************************
    u8 标志=0;
    
    void KEY_4x4_Init(void) //IO初始化
    {
     GPIO_InitTypeDef GPIO_InitStructure;
    
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,启用);GPIO_InitStructure.GPIO_Pin = KEY_HANG; //行0123
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
      GPIO_Init(KEY_PROT, &GPIO_InitStructure);
    GPIO_SetBits(KEY_PROT,KEY_HANG);
    
    //init GPIOA上拉输入
    GPIO_InitStructure.GPIO_Pin = KEY1|KEY2|KEY3|KEY4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(KEY_PROT, &GPIO_InitStructure);
    GPIO_SetBits(KEY_PROT,KEY1|KEY2|KEY3|KEY4);
    
    
    }
    
    
    无效 KEY_Scan(u8 *key)
    {
    
    GPIO_Write(KEY_PROT,0x00fe);//第一行
    if((KEY1_Input==RESET)||(KEY2_Input==RESET)||(KEY3_Input==RESET)||(KEY4_Input==RESET))
    {
    delay_ms(10);//去睡觉
    
    如果(KEY1_输入==重置)
    {
    标志=1;
    *键= 1;
    while(!GPIO_ReadInputDataBit(KEY_PROT,KEY1));
    }
    否则如果(KEY2_Input==RESET)
    {
    
    标志=1;
    *键= 2;
    while(!GPIO_ReadInputDataBit(KEY_PROT,KEY2));
    }
    否则如果(KEY3_Input==RESET)
    {
    
    标志=1;
    *键= 3;while(!GPIO_ReadInputDataBit(KEY_PROT,KEY3));
    }
    否则如果(KEY4_Input==RESET)
    {
    
    标志=1;
    *键= 4;
    while(!GPIO_ReadInputDataBit(KEY_PROT,KEY4));
    }别的
    {
    标志=0;
    GPIO_Write(KEY_PROT,0x00ff);
    }
    }
    GPIO_Write(KEY_PROT,0x00fd);//第二行
    if((KEY1_Input==RESET)||(KEY2_Input==RESET)||(KEY3_Input==RESET)||(KEY4_Input==RESET))
    {
    delay_ms(10);//去睡觉
    
    如果(KEY1_输入==重置)
    {
    标志=1;
    *键= 5;
    while(!GPIO_ReadInputDataBit(KEY_PROT,KEY1));
    }
    否则如果(KEY2_Input==RESET)
    {
    
    标志=1;
    *键= 6;
    while(!GPIO_ReadInputDataBit(KEY_PROT,KEY2));
    }
    否则如果(KEY3_Input==RESET)
    {
    
    标志=1;
    *键= 7;
    while(!GPIO_ReadInputDataBit(KEY_PROT,KEY3));
    }
    否则如果(KEY4_Input==RESET)
    {
    
    标志=1;
    *键= 8;
    while(!GPIO_ReadInputDataBit(KEY_PROT,KEY4));
    }别的
    {
    标志=0;GPIO_Write(KEY_PROT,0x00ff);
    }
    }
    GPIO_Write(KEY_PROT,0x00fb);//第三行
    if((KEY1_Input==RESET)||(KEY2_Input==RESET)||(KEY3_Input==RESET)||(KEY4_Input==RESET))
    {
    delay_ms(10);//去睡觉
    
    如果(KEY1_输入==重置)
    {
    标志=1;
    *键= 9;
    while(!GPIO_ReadInputDataBit(KEY_PROT,KEY1));
    }
    否则如果(KEY2_Input==RESET)
    {
    
    标志=1;
    *键= 10;
    while(!GPIO_ReadInputDataBit(KEY_PROT,KEY2));
    }
    否则如果(KEY3_Input==RESET)
    {
    
    标志=1;
    *键= 11;
    while(!GPIO_ReadInputDataBit(KEY_PROT,KEY3));
    }
    否则如果(KEY4_Input==RESET)
    {
    
    标志=1;
    *键= 12;
    while(!GPIO_ReadInputDataBit(KEY_PROT,KEY4));
    }别的
    {
    标志=0;
    GPIO_Write(KEY_PROT,0x00ff);
    }
    }
    GPIO_Write(KEY_PROT,0x00f7);//第四行
    if((KEY1_Input==RESET)||(KEY2_Input==RESET)||(KEY3_Input==RESET)||(KEY4_Input==RESET))
    {
    delay_ms(10);//去睡觉
    
    如果(KEY1_输入==重置)
    {标志=1;
    *键= 13;
    while(!GPIO_ReadInputDataBit(KEY_PROT,KEY1));
    }
    否则如果(KEY2_Input==RESET)
    {
    
    标志=1;
    *键= 14;
    while(!GPIO_ReadInputDataBit(KEY_PROT,KEY2));
    }
    否则如果(KEY3_Input==RESET)
    {
    
    标志=1;
    *键= 15;
    while(!GPIO_ReadInputDataBit(KEY_PROT,KEY3));
    }
    否则如果(KEY4_Input==RESET)
    {
    
    标志=1;
    *键= 16;
    while(!GPIO_ReadInputDataBit(KEY_PROT,KEY4));
    }别的
    {
    标志=0;
    GPIO_Write(KEY_PROT,0x00ff);
    }
    }
    
    }
    
    
    
    
    

    keys.h

    #ifndef __KEYS_H
    #定义__KEYS_H
    //
    
    //**************************************************** **********************************
    //V1.1修改说明
    //修改按键扫描函数,使整个代码可以支持SWD下载。
    //
    #include“stm32f10x.h”
    
    #定义KEY_HANG 0x000f //0123
    #定义KEY1 GPIO_Pin_4
    #定义KEY2 GPIO_Pin_5
    #定义KEY3 GPIO_Pin_6
    #定义KEY4 GPIO_Pin_7
    
    #define KEY1_Input GPIO_ReadInputDataBit(KEY_PROT,KEY1)#define KEY2_Input GPIO_ReadInputDataBit(KEY_PROT,KEY2)
    #define KEY3_Input GPIO_ReadInputDataBit(KEY_PROT,KEY3)
    #define KEY4_Input GPIO_ReadInputDataBit(KEY_PROT,KEY4)
    
    #定义KEY_PROT GPIOA
    
    外部 u8 标志;
    
    void KEY_4x4_Init(void);//IO初始化
    //u8 KEY_Scan(void);
    无效 KEY_Scan(u8 *key); //按键扫描函数
    
    #万一
    
    

    main.c

    #include“stm32f10x.h”
    #include“led.h”
    #include“延迟.h”
    #包括“sys.h”
    #include“keys.h”
    //#include“usart.h”
    #include“OLED.h”
    
    
    
    
    /*接线说明
    PA0~PA3----R4~R1 //OK
    PA4~PA7-----C4~C1 //柱
    */
    
     u8键=0;
     u8i;
     int 主函数(无效)
     {
    
    LED_Init();
    延迟初始化();
    KEY_4x4_Init();
    //uart_init(115200);
    OLED_Init();
    /*OLED初始化接口*/
    OLED_ShowChar(1, 1, 'A');
    OLED_ShowString(1, 3, "HelloWorld!");
    OLED_ShowNum(2, 1, 12345, 5);
    OLED_ShowSignedNum(2, 7, -66, 2);
    OLED_ShowHexNum(3, 1, 0xAA55, 4);
    OLED_ShowBinNum(4, 1, 0xAA55, 16);
    
    同时(1)
    {
    
    KEY_Scan(&key); //获取键值keyif(FLAG == 1) // 按键
    {
    标志=0;
    OLED_Clear();
    OLED_ShowNum(2, 1, 键, 2); //显示键值key
    //Printf("KEY = %d\r\n",key);
    if(key==1) //0001
    {
    GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14);
    GPIO_ResetBits(GPIOB,GPIO_Pin_15);
    }
    if(key==2) //0010
    {
    GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_15);
    GPIO_ResetBits(GPIOB,GPIO_Pin_14);
    }
    if(key==3) //0011
    {
    GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13);
    GPIO_ResetBits(GPIOB,GPIO_Pin_14|GPIO_Pin_15);
    }
    if(key==4) //0100
    {
    GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_14|GPIO_Pin_15);
    GPIO_ResetBits(GPIOB,GPIO_Pin_13);
    }
    if(key==5) //0101
    {
    GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_14);
    GPIO_ResetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_15);
    }
    if(key==6) //0110
    {
    GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_15);GPIO_ResetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14);
    }
    if(key==7) //0111
    {
    GPIO_SetBits(GPIOB,GPIO_Pin_12);
    GPIO_ResetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
    }
    if(key==8) //1000
    {
    GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
    GPIO_ResetBits(GPIOB,GPIO_Pin_12);
    }
    if(key==9) //1001
    {
    GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14);
    GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_15);
    }
    if(key==10) //1010
    {
    GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_15);
    GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_14);
    }
    if(key==11) //1011
    {
    GPIO_SetBits(GPIOB,GPIO_Pin_13);
    GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_14|GPIO_Pin_15);
    }
    if(key==12) //1100
    {
    GPIO_SetBits(GPIOB,GPIO_Pin_14|GPIO_Pin_15);
    GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13);
    }
    if(key==13) //1101{
    GPIO_SetBits(GPIOB,GPIO_Pin_14);
    GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_15);
    }
    if(key==14) //1110
    {
    GPIO_SetBits(GPIOB,GPIO_Pin_15);
    GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14);
    }
    if(key==15) //1111
    {
    GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
    }
    
    if(key==16) //来回触发4次
    {
    for(i=0;i<4;i++)
    {
    GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13);
    GPIO_SetBits(GPIOB,GPIO_Pin_14|GPIO_Pin_15);
    延迟毫秒(1000);
    GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13);
    GPIO_ResetBits(GPIOB,GPIO_Pin_14|GPIO_Pin_15);
    延迟毫秒(1000);
    }
    }
    //LCD12864_Write_Number(0x8d,键);
    
    }
    
    }
     }
    
    
    

    (4)效果展示

    矩阵键盘实验效果:

    矩阵键盘

    三、总结与扩展

    总结:
    根据以上内容,学习矩阵按钮与触摸按钮类似,很容易理解。输入信号给stm32,驱动LED相应点亮或熄灭。矩阵按键主要用于需要多个按键来解决管脚少的问题的应用。
    总结一下调试代码或硬件可能出现的问题:
    (1)出现按键响应慢:因为矩阵按键模块的触发采用行列扫描,比中断触发快响应速度慢;代码部分按键扫描延迟太高,或者可能出现去抖(10ms~20ms)。
    (2)按键硬件无反应:可能是键盘模块引脚与stm32引脚接线错误或接反;也可能是对应管脚冲突和占用造成的,需要调用AFIO口复用转换为正常I/O,或许可以解决;也可能是硬件损坏的问题,或者是裸露的铜造成的短路。
    扩展: 您可以使用矩阵键盘模块进行简单计算器、密码锁、功能键等实验。那么就分享在这里,大胆尝试实践探索,欢迎讨论。

    今天就这样。你要有信心一步步积累理论和实践经验。一起来学习吧!

    附上参考链接和视频链接

    链接:参考
    链接:参考视频
    链接:矩阵按钮视频分享
    链接:源代码例程
    提取码:3232