51.矩阵键盘实验

本次实验使用的是淘宝上常见的矩阵键盘,如下图,最左边和最右边的引脚为空,所以这里说的1引脚对应单片机从左往右数的第二个,第八个引脚对应倒数第二个引脚。

原理图如下(从淘宝找的,有点模糊):

     

从原理图看:

   引脚1关联的键位有:1 ,4,7,*。 引脚2关联的键位有:2,5,8,0。引脚3关联的引脚:3,6,9,#。引脚4关联的引脚:A,B,C,D。引脚5关联引脚:1,2,3,A。 引脚6关联引脚:4,5,6,B。

引脚7关联引脚:7,8,9,C。 引脚8关联引脚:*,0,#,D。

通过使用万用表测量电流,按下对应按键,万用表显示对应电流。

下面进行代码的编写:

1.1按键初始化(void keyboard_init(void))

1.初始化GPIO,GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_10 配置为下降沿中断触发,上拉。  

2.GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 ,输入模式,下拉。

3.还有设置中断优先级分组以及使能中断

void keyboard_init(void)
{
    GPIO_InitTypeDef gpio_initstruct;

    __HAL_RCC_GPIOB_CLK_ENABLE();                           
    
    //调用GPIO初始化函数
    gpio_initstruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_10;          
    gpio_initstruct.Mode = GPIO_MODE_IT_FALLING;             
    gpio_initstruct.Pull = GPIO_PULLUP;                     
    gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;           
    HAL_GPIO_Init(GPIOB, &gpio_initstruct);
    
    gpio_initstruct.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;          
    gpio_initstruct.Mode = GPIO_MODE_INPUT;             
    gpio_initstruct.Pull = GPIO_PULLDOWN;                     
    HAL_GPIO_Init(GPIOB, &gpio_initstruct);
    
    HAL_NVIC_SetPriority(EXTI0_IRQn, 3, 0);
    HAL_NVIC_EnableIRQ(EXTI0_IRQn);
    
    HAL_NVIC_SetPriority(EXTI1_IRQn, 3, 0);
    HAL_NVIC_EnableIRQ(EXTI1_IRQn);
    
    HAL_NVIC_SetPriority(EXTI2_IRQn, 3, 0);
    HAL_NVIC_EnableIRQ(EXTI2_IRQn);
    
    HAL_NVIC_SetPriority(EXTI15_10_IRQn, 3, 0);
    HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
}
1.2中断函数
void EXTI0_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}

void EXTI1_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
}

void EXTI2_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);
}

void EXTI15_10_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10);
}
1.3在回调函数中,确定按下按键的行和列
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    uint8_t row = 0, column = 0;
    
    if(key_value != 0) return;  //判断键值是否为空,不为空直接返回
    //确认行
    if(GPIO_Pin == GPIO_PIN_0)
        row = 0x10;
    else if(GPIO_Pin == GPIO_PIN_1)
        row = 0x20;
    else if(GPIO_Pin == GPIO_PIN_2)
        row = 0x30;
    else if(GPIO_Pin == GPIO_PIN_10)
        row = 0x40;
    
    //确定列
    if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_11) == GPIO_PIN_SET)
    {
        delay_ms(10);     //消抖
        while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_11))
            column = 0x01;
    }
    else if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12) == GPIO_PIN_SET)
    {
        delay_ms(10);
        while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12))
            column = 0x02;
    }
    else if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_13) == GPIO_PIN_SET)
    {
        delay_ms(10);
        while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_13))
            column = 0x03;
    }
    
    if(row != 0 && column != 0)
        key_value = row | column;   //取得键值
}
1.4将键值转换成对应的字符
uint8_t keyboard_get_value(void)
{
    uint8_t ch = 0;
    if(key_value != 0)
    {
        if(key_value == 0x11) ch = '1';
        else if(key_value == 0x12) ch = '2';
        else if(key_value == 0x13) ch = '3';
        else if(key_value == 0x21) ch = '4';
        else if(key_value == 0x22) ch = '5';
        else if(key_value == 0x23) ch = '6';
        else if(key_value == 0x31) ch = '7';
        else if(key_value == 0x32) ch = '8';
        else if(key_value == 0x33) ch = '9';
        else if(key_value == 0x41) ch = '*';
        else if(key_value == 0x42) ch = '0';
        else if(key_value == 0x43) ch = '#';
        delay_ms(400);
        key_value = 0x00;
    }
    return ch;
}

main 函数

#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "keyboard.h"

int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
    stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */
    led_init();                         /* 初始化LED灯 */
    uart1_init(115200);
    keyboard_init();
    printf("hello world!\r\n");

    uint8_t key_value = 0;
    while(1)
    { 
        key_value = keyboard_get_value();
        if(key_value != 0)
        {
            printf("按下了:%c\r\n", key_value);
            key_value = 0;
        }
    }
}

更新:查找stm32f103 c8t6产品手册发现 pb3 pb4用作jtag引脚,故而将jtag引脚重定义为普通IO口输入输出

//keyboard.h 头文件
#ifndef __KEYBOARD_H__
#define __KEYBOARD_H__

#include "sys.h"

#define   P1              GPIO_PIN_1   //从左往右,第二个引脚,下面依次往右数
#define   P2              GPIO_PIN_2
#define   P3              GPIO_PIN_3
#define   P4              GPIO_PIN_4
                                   
#define   P5              GPIO_PIN_6
#define   P6              GPIO_PIN_7
#define   P7              GPIO_PIN_12
#define   P8              GPIO_PIN_13

#define   PIN_SOURCE      GPIOB
void  keyboard_init(void);
uint8_t  get_keyboard_ch(void);

#endif

//keyboard.c 文件
#include "keyboard.h"

uint8_t key_val=0;

void  keyboard_init(void)
{
   GPIO_InitTypeDef GPIO_InitStructure;
   __HAL_RCC_GPIOA_CLK_ENABLE();
    
   GPIO_InitStructure.Pin= P1 | P2 | P3 | P4;  
   GPIO_InitStructure.Mode=GPIO_MODE_IT_FALLING;  //下降沿触发中断
   GPIO_InitStructure.Pull=GPIO_PULLUP;  //上拉
   GPIO_InitStructure.Speed=GPIO_SPEED_FREQ_HIGH;
   
   HAL_GPIO_Init(PIN_SOURCE,&GPIO_InitStructure);
    
   GPIO_InitStructure.Pin= P5 | P6 | P7 | P8;  
   GPIO_InitStructure.Mode=GPIO_MODE_INPUT;  //输入模式
   GPIO_InitStructure.Pull=GPIO_PULLDOWN;  //下拉
   GPIO_InitStructure.Speed=GPIO_SPEED_FREQ_HIGH;
   
   HAL_GPIO_Init(PIN_SOURCE,&GPIO_InitStructure);
   __HAL_AFIO_REMAP_SWJ_NOJTAG();  // 禁用 JTAG,但保留 SWD 

    
   HAL_NVIC_SetPriority(EXTI1_IRQn,3,0);
   HAL_NVIC_EnableIRQ(EXTI1_IRQn);
   
   HAL_NVIC_SetPriority(EXTI2_IRQn,3,0);
   HAL_NVIC_EnableIRQ(EXTI2_IRQn);
   
   HAL_NVIC_SetPriority(EXTI3_IRQn,3,0);
   HAL_NVIC_EnableIRQ(EXTI3_IRQn);
   
   HAL_NVIC_SetPriority(EXTI4_IRQn,3,0);
   HAL_NVIC_EnableIRQ(EXTI4_IRQn);
}

void EXTI1_IRQHandler(void)
{
   HAL_GPIO_EXTI_IRQHandler(P1);
}

void EXTI2_IRQHandler(void)
{
   HAL_GPIO_EXTI_IRQHandler(P2);
}

void EXTI3_IRQHandler(void)
{
   HAL_GPIO_EXTI_IRQHandler(P3);
    
}

void EXTI4_IRQHandler(void)
{
   HAL_GPIO_EXTI_IRQHandler(P4);
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    uint8_t row=0,col=0;
    if(key_val !=0) return;
    
    //读取中断的Pin引脚
    if(GPIO_Pin==P1){
       row=0x10;
    } 
    
    else if(GPIO_Pin==P2){
       row=0x20;
    } 

    else if(GPIO_Pin==P3){
       row=0x30;
    }    
    
    else if(GPIO_Pin==P4){
        row=0x40;
    }

    if(HAL_GPIO_ReadPin(PIN_SOURCE,P5)==GPIO_PIN_SET){
        delay_ms(10);
        while(HAL_GPIO_ReadPin(PIN_SOURCE,P5));
        col=0x01;
    
    }
    else if(HAL_GPIO_ReadPin(PIN_SOURCE,P6)==GPIO_PIN_SET){
        delay_ms(10);
        while(HAL_GPIO_ReadPin(PIN_SOURCE,P6));
        col=0x02;
    }
    else if(HAL_GPIO_ReadPin(PIN_SOURCE,P7)==GPIO_PIN_SET){
        delay_ms(10);
        while( HAL_GPIO_ReadPin(PIN_SOURCE,P7));
        col=0x03; 
    }
    else if(HAL_GPIO_ReadPin(PIN_SOURCE,P8)==GPIO_PIN_SET){
        delay_ms(10);
        while(HAL_GPIO_ReadPin(PIN_SOURCE,P8) );
        col=0x04;
    }
    if( (row!=0) &&(col!=0)){
       key_val= row | col;
    }

  
}
uint8_t  get_keyboard_ch(void)
{
    uint8_t ch=0;
    if(key_val!=0){
        if(key_val==0x11) ch='1';
        else if(key_val==0x12) ch='4';
        else if(key_val==0x13) ch='7';
        else if(key_val==0x14) ch='*';
        else if(key_val==0x21) ch='2';
        else if(key_val==0x22) ch='5';
        else if(key_val==0x23) ch='8';
        else if(key_val==0x24) ch='0';
        else if(key_val==0x31) ch='3';
        else if(key_val==0x32) ch='6';
        else if(key_val==0x33) ch='9';
        else if(key_val==0x34) ch='#';
        else if(key_val==0x41) ch='A';
        else if(key_val==0x42) ch='B';
        else if(key_val==0x43) ch='C';
        else if(key_val==0x44) ch='D';
        delay_ms(400);
        key_val=0;
    }
    return ch;
}

就是加了一行   __HAL_AFIO_REMAP_SWJ_NOJTAG();  // 禁用 JTAG,但保留 SWD 

其他没啥多大变化

按键测试能正常输出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值