目录
一、简介
二、原理图
三、程序实现
一、简介
矩阵键盘,也称矩阵按键,是为了节约单片机IO口占用所引入的一种外设。
二、矩阵按键的原理图
三、程序实现
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); //PA0gpio_init(GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_1); //PA1gpio_init(GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_2); //PA2gpio_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); //PB0gpio_init(GPIOB,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_1); //PB1gpio_init(GPIOB,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_2); //PB2gpio_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);//PC13gpio_init(GPIOC,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_14);//PC14gpio_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); //PB0gpio_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初始化为下拉输入,等待下一次按键的按下。