[STM32] 4 * 4 matrix keyboard (external interrupt trigger mode)

Posted by mattchewone on Thu, 21 Oct 2021 20:28:26 +0200

one   EXTI (external interrupt)   brief introduction

        The STM32F10x external interrupt / event controller (EXTI) contains up to 20 edge detectors for generating event / interrupt requests. Each input line of EXTI can be configured separately to select the type (interrupt or event) and the corresponding trigger event (rising edge trigger, falling edge trigger or edge trigger).
        EXTI is divided into two functions: one generates interrupts and the other generates events. This is what we mainly do in STM32: configure external interrupts and write interrupt service functions.

2. Introduction to 4 * 4 matrix keyboard

.

  The line reversal method detects which key is pressed:

          For example, first, we output the low level to the row and set the pull-up input to the column. When a key is pressed, the potential of the column is pulled down. At this time, we can know that the potential of the column is pulled down by reading the level state of the input pin of the column. When we detect that the potential of the column is pulled down, we let the column output the high level and set the pull-down input mode to the row, Similarly, it can detect which line of potential is pulled up. Of course, there are other key detection methods. Only one of them is introduced here.

3.EXTI configuration steps (based on firmware library development)

    (1) Configure IO port initialization function
        
        The author scans the keys by initializing the IO port twice. The first initialization of the IO port is used to detect which column of the corresponding pin triggers the external interrupt. The second initialization is used to scan the row after entering the corresponding interrupt service function to judge which key is pressed in the interrupt function.
    (2) Set interrupt source, interrupt priority and enable peripheral interrupts
          The author uses GPIOB    :   GPIO_ Pin_ 2 |GPIO_ Pin_ 0 |GPIO_ Pin_ 5 |GPIO_ Pin_ six     4 pins as external interrupt source
void NVIC_Config(void)
{
	NVIC_InitTypeDef   NVIC_InitStruct;                        //NVIC configuration structure	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);             //Configure as group 2
	
	NVIC_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn;            //Select break line
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;      //Preemption priority is 0
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;             //The sub priority is 1
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;               //Enable NVIC
    NVIC_Init(&NVIC_InitStruct); 	
	
	NVIC_InitStruct.NVIC_IRQChannel = EXTI2_IRQn;              //Select break line
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;             //The child priority is 0
	NVIC_Init(&NVIC_InitStruct);  
	
	NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;              //Select break line
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;             //The sub priority is 2
	NVIC_Init(&NVIC_InitStruct);  
	
}

void EXTI_KEY_Init(void)
{		
		EXTI_InitTypeDef  EXTI_InitStruct;		
		NVIC_Config();	
        KEY1_Init();  			
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);       
//Enable APB2 clock. Note: external interrupt needs to turn on AFIO clock
	
        //Initialize column 3 interrupt 	
	    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource2);   //Select external interrupt source
	    EXTI_InitStruct.EXTI_Line    = EXTI_Line2;                
        EXTI_InitStruct.EXTI_Mode    = EXTI_Mode_Interrupt;       //Configure as interrupt
        EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;       //Configured as falling edge trigger
        EXTI_InitStruct.EXTI_LineCmd = ENABLE;
	    EXTI_Init(&EXTI_InitStruct);                              
			
		
		//Initialize column 4 interrupt	
	    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);   //Select external interrupt source
	    EXTI_InitStruct.EXTI_Line    = EXTI_Line0; 
		EXTI_Init(&EXTI_InitStruct);                                  //Initialization function
				
		
		//Initialize column 2 interrupt 	
	    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource5);   //Select external interrupt source
	    EXTI_InitStruct.EXTI_Line    = EXTI_Line5; 
		EXTI_Init(&EXTI_InitStruct);                              //Initialization function
 
     
		//Initialize column 1 interrupt 	
	    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource6);   //Select external interrupt source
	    EXTI_InitStruct.EXTI_Line    = EXTI_Line6; 
		EXTI_Init(&EXTI_InitStruct);                              //Initialization function
         
	
    
}

(3) Write EXTI interrupt service function  

All interrupt functions are in the STM32F1 startup file. If you don't know the name of the interrupt function, you can open the startup file to find it. Here we use the external interrupt, whose function name is as follows:
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
EXTI9_5_IRQHandler
EXTI15_10_IRQHandler
As can be seen from the function name, the first 0-4 interrupt lines are independent functions, and interrupt lines 5-9 share an EXTI9_5_IRQHandler and interrupt lines 10-15 also share a function EXTI15_10_IRQHandler, so pay attention when writing the corresponding interrupt service function.
Because the code is too long, the author only shows one of the interrupt functions here
void EXTI2_IRQHandler(void) 
{
        if(EXTI_GetITStatus(EXTI_Line2) != RESET)           //Detection interrupt flag bit
		{					 
			    KEY2_Init();
			    //Read the status of line 4
			       if(Column1==1)
					{
						while(Column1)
						   KeyValue=3;
												
					}
					if(Column2)
					{
						
						while(Column2)						
						   KeyValue=7;
												
					}
					if(Column3)
					{
						
						while(Column3)						
					    	KeyValue=11;
												
					}
					if(Column4)
					{
						
						while(Column4==1)						
						  KeyValue=15;
												
					}
			
			EXTI_ClearITPendingBit(EXTI_Line2);                         //Clear flag bit
			KEY1_Init(); //Reset GPIO and wait for the next interrupt
		}
		
}

(4)exti_key16.h file

#ifndef __STM32F10X_EXTI_KEY16_H__
#define __STM32F10X_EXTI_KEY16_H__


#include "stm32f10x.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"

#define GPIO_CLK 	            RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC

#define Column_GPIO_PORT    	GPIOC			            	
#define Column_GPIO_PIN		    GPIO_Pin_0| GPIO_Pin_1 |GPIO_Pin_2 |GPIO_Pin_3   

#define LINE_GPIO_PORT    	    GPIOB			               
#define LINE_GPIO_PIN		    GPIO_Pin_2 |GPIO_Pin_0 |GPIO_Pin_5 |GPIO_Pin_6		

#define Column1       PCin(3) //R4
#define Column2       PCin(2) //R3
#define Column3       PCin(0) //R2			
#define Column4       PCin(1) //R1
#define Line1         PBin(6) //C4
#define Line2         PBin(5) //C3
#define Line3         PBin(2) //C2				
#define Line4         PBin(0) //C1

void EXTI_KEY_Init(void);



#endif

  

          Finally, this is my first time to write CSDN. There are many deficiencies. Welcome to point out, communicate and learn from each other. Thank you!

Topics: stm32 ARM