基于GD32矩阵按键程序实现

目录

一、简介

二、原理图

三、程序实现


 一、简介

矩阵键盘,也称矩阵按键,是为了节约单片机IO口占用所引入的一种外设。

 二、矩阵按键的原理图

基于GD32矩阵按键程序实现_第1张图片

三、程序实现

GPIO初始化引脚代码

/*!
    \brief      Init Key Function
    \param[in]  none
    \param[out] none
    \retval     none
*/
void Key_Init(void)
{

    gpio_init(GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_0); //PA0
    gpio_init(GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_1); //PA1
    gpio_init(GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_2); //PA2
    gpio_init(GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_3); //PA3  复用
    gpio_init(GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_4); //PA4  复用
    gpio_init(GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_5); //PA5  复用
    gpio_init(GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_6); //PA6  复用
    gpio_init(GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_7); //PA7  复用

    gpio_init(GPIOB,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_0); //PB0
    gpio_init(GPIOB,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_1); //PB1
    gpio_init(GPIOB,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_2); //PB2

    gpio_init(GPIOC,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_4); //PC4  复用
    gpio_init(GPIOC,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_13);//PC13
    gpio_init(GPIOC,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_14);//PC14

    gpio_init(GPIOB,GPIO_MODE_IPD,GPIO_OSPEED_10MHZ,GPIO_PIN_10);//PB10  下拉输入
    gpio_init(GPIOB,GPIO_MODE_IPD,GPIO_OSPEED_10MHZ,GPIO_PIN_11);//PB11  下拉输入

把公共端PB10 和PB11初始化为GPIO_MODE_IPD下拉输入模式GPIO_OSPEED_10MHZ输出最大速度10MHz,其余配置成GPIO_MODE_IN_FLOATING浮空输入模式,GPIO_OSPEED_10MHZ输出最大速度10MHz。

void Exti_Inteerupt_Config(void)
{

    /*中断优先级配置*/
    nvic_irq_enable(EXTI10_15_IRQn, 1U, 0U);

    /* connect key EXTI line to key GPIO pin */
    gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOB, GPIO_PIN_SOURCE_10);  //PB0
    gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOB, GPIO_PIN_SOURCE_11);  //PB1

    /* configure key EXTI line */
    exti_init(EXTI_10, EXTI_INTERRUPT, EXTI_TRIG_RISING);
    exti_init(EXTI_11, EXTI_INTERRUPT, EXTI_TRIG_RISING);

    exti_interrupt_flag_clear(EXTI_10);
    exti_interrupt_flag_clear(EXTI_11);
    exti_interrupt_enable(EXTI_10);
    exti_interrupt_enable(EXTI_11);

}

外部中断配置函数

 nvic_irq_enable(EXTI10_15_IRQn, 1U, 0U); 配置外部中断优先级  1U抢占优先级,0U子优先级

 gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOB, GPIO_PIN_SOURCE_10); 把 GPIOB  Pin10配置外部源 

  exti_init(EXTI_10, EXTI_INTERRUPT, EXTI_TRIG_RISING);初始化EXTI_10  为EXTI_INTERRUPT外部中断,EXTI_TRIG_RISING上升沿触发

exti_interrupt_flag_clear(EXTI_10); 清除EXTI_10中段标志位

exti_interrupt_enable(EXTI_10); 使能外部中断

/*!
    \brief      Key Judge Function
    \param[in]  none
    \param[out] none
    \retval     none
*/
void Key_Judge(void)
{
    if (RESET != exti_interrupt_flag_get(EXTI_10))   						//PB10里面的按键按下
    {
        gpio_init(GPIOB,GPIO_MODE_OUT_OD,GPIO_OSPEED_10MHZ,GPIO_PIN_10);   //PB10 开漏输出
        delay_1ms(20);
        Key_PB10();													       //判断是PB10里面的那个按键按下
        gpio_init(GPIOB,GPIO_MODE_IPD,GPIO_OSPEED_10MHZ,GPIO_PIN_10);  	   //PB10 下拉输入
        exti_interrupt_flag_clear(EXTI_10);								   //清除中断
    }
    else if (RESET != exti_interrupt_flag_get(EXTI_11))					   //PB11里面的按键按下
    {
        gpio_init(GPIOB,GPIO_MODE_OUT_OD,GPIO_OSPEED_10MHZ,GPIO_PIN_11);   //PB11 开漏输出
        delay_1ms(20);
        Key_PB11();														   //判断是PB11里面的那个按键按下
        gpio_init(GPIOB,GPIO_MODE_IPD,GPIO_OSPEED_10MHZ,GPIO_PIN_11);      //PB11 下拉输入
        exti_interrupt_flag_clear(EXTI_11);
    }
}

这是按键检测函数

if判断是哪个公共端触发的中断

gpio_init(GPIOB,GPIO_MODE_OUT_OD,GPIO_OSPEED_10MHZ,GPIO_PIN_10);   //PB10 开漏输出    如果是EXTI_10 就把PB10引脚初始化为开漏输出,延迟20个毫秒是等待初始化完成,在调用检测引脚函数找出按键,最后再次初始化PB10为下拉输入,清除中断标志为。

/*!
    \brief      Key PB10 Function
    \param[in]  none
    \param[out] none
    \retval     none
*/
void Key_PB10(void)
{
    if(gpio_input_bit_get(GPIOA,GPIO_PIN_4) == RESET) {
        PB10.ACC = 1;
    } else if(gpio_input_bit_get(GPIOC,GPIO_PIN_4) == RESET) {
        PB10.P_key = 1;
    } else if(gpio_input_bit_get(GPIOA,GPIO_PIN_7) == RESET) {
        PB10.double_flash = 1;
    } else if(gpio_input_bit_get(GPIOA,GPIO_PIN_6) == RESET) {
        PB10.right_turn_light = 1;
    } else if(gpio_input_bit_get(GPIOA,GPIO_PIN_5) == RESET) {
        PB10.left_turn_light = 1;
    } else if(gpio_input_bit_get(GPIOA,GPIO_PIN_3) == RESET) {
        PB10.return_key = 1;
    } else if(gpio_input_bit_get(GPIOB,GPIO_PIN_2) == RESET) {
        PB10.locus_minus = 1;
    } else if(gpio_input_bit_get(GPIOB,GPIO_PIN_1) == RESET) {
        PB10.locus_add = 1;
    } else if(gpio_input_bit_get(GPIOB,GPIO_PIN_0) == RESET) {
        PB10.reserved2 = 1;
    }
}

按键判断函数就是挨个检测哪个引脚是低电平。

/*!
    \brief      this function handles Exti10-15
    \param[in]  none
    \param[out] none
    \retval     none
*/
void EXTI10_15_IRQHandler(void)
{
	Key_Judge(); //按键判断函数
}

总结

举例

当我按下K10的时候,初始化时我们把PA6初始化为浮空输入,看原理图3.3v电源是和PA6导通,我按下K10按键,PB11这里会导通,PB11初始化为下拉输入,并为EXTI_11的中断源,此时会跑到EXTI10_15_IRQHandler中断函数,在进入Key_Judge()函数里面,Key_Judge()函数里面会去判断是哪个中断源触发的,判断出是PB11后,马上初始化引脚为开漏输出,在进Key_PB11函数里面去读取连接PB11上的每根引脚电平,因为是开漏输出,所以当按键按下,会把连接的pin脚也拉低,这样就判断出是哪个按键按下,判断出来后在把PB11初始化为下拉输入,等待下一次按键的按下。

你可能感兴趣的:(GD32应用,矩阵,单片机)