STM32 Embedded Learning Introduction (3) - STM32F103 key input control LED light

Publisher:代码漫游者Latest update time:2019-04-10 Source: eefocusKeywords:STM32 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

The button is a very important input device on the microcontroller and is also easy to master. As long as you understand the most basic use of the IO port, you can operate the button.


Our goal is to control the three buttons on the development board to turn the two LED lights on the development board on or off (the light turns on when the button is pressed for the first time, the light turns off when pressed again, and so on).


The development boards used by the blogger are the mini board (STM32F103RCT6) and the battleship board (STM32F103ZET6) of Zhengdian Atom, so the examples in the following content take these two development boards as examples, but the basic principles are the same for any development board. As long as your development board has onboard buttons and LED lights (these two resources should be resources available on all development boards), then check the data manual, hardware circuit diagram, and schematic diagram of your own development board, find the IO ports corresponding to the buttons and LED lights, and then you can use the buttons to control the LED lights according to the process described in this article.


On the development board, the onboard hardware resources (such as the buttons and LED lights we use here) are all connected to certain GPIOs. To use these hardware resources, you can actually understand it as operating on these IO ports.


Let’s first briefly describe the entire process.


1. To use these hardware resources, you need to initialize them. Initialization includes enabling the IO port clock and initializing the IO port parameters. These two points were mentioned in the previous blog post.


2. After the initialization is completed, you can operate the IO port, that is, write the relevant logic code. Here, the button controls the LED light, so we must first scan the level of the IO port connected to the button. If the IO level changes, it means that the button has been pressed, and we have to reverse the state of the light. If the IO level does not change, it means that the button has not been pressed. We can scan the IO port connected to the button again after a small time interval to see if there is any change, thus forming an infinite loop.


The following code is the main function of the key experiment of the Atom Mini STM32F103RCT6 development board (mini board):


#define LED0 PAout(8) // PA8 

#define LED1 PDout(2) // PD2 

#define KEY0_PRES 1 //KEY0 

#define KEY1_PRES 2 //KEY1 

#define WKUP_PRES 3 //WK_UP 

int main(void) 

    u8 t=0; 

    delay_init(); //delay function initialization 

    LED_Init(); //Initialize the hardware interface connected to the LED 

    KEY_Init(); //Initialize the hardware interface connected to the key 

    LED0=0; //Light up LED0 

    while(1){ 

        t=KEY_Scan(0); //Get the key value 

        KEY_Scan(0); means continuous key press is not supported. If continuous key press is required, set the parameter to 1. 

        switch(t){ 

            case KEY0_PRES: LED0=!LED0; break; 

            case KEY1_PRES: LED1=!LED1; break; 

            case WKUP_PRES: LED0=!LED0; LED1=!LED1; break; 

            default: delay_ms(10); 

        } 

    }//while(1) 

}

The code is long, but the overall logic is easy to understand. First, let me explain the macro definitions of the first two lines. Here, the level output of PA8/PD2 is realized through bit operation. This line of code is actually quite complicated. To be precise, the blogger cannot explain the principle (if you check the official library function of stm32, you will find that PAout(n) here is obtained through many layers of macro definitions), but I will call it. In short, after defining it like this, the following code sets 1 to LED0, which corresponds to setting the IO port to a high level, and sets 0 to set the IO port to a low level. The following three macro definitions serve the following switch-case, which enhances the readability of the code.


Next is the main function. First, three initialization functions are called. This will be described in detail later. After the initialization is completed, LED0=0; is used to light up LED0. Next is the while(1) loop. The KEY_Scan(0); function is called in the infinite loop to detect the key. The return value of this function has four cases, namely KEY0_PRES, KEY1_PRES, WKUP_PRES, and 0. The first three return values ​​indicate that the corresponding key is pressed, and returning 0 indicates that no key is currently pressed. Then there is the switch-case structure. If a key is pressed, the corresponding branch is executed to invert the level on the LED, so that the LED is lit when pressed once and turned off when pressed again, and so on. If no key is pressed, a delay of 10ms is performed, and then the key is detected again. This is the execution process of the entire program.


The next question is how the three initialization functions and KEY_Scan(0); function are implemented.


1. Delay function


Here, two functions, delay_init(); and delay_ms(10); are used. To fully understand the principle of the delay function, you need to understand the knowledge of the timer in the STM32 kernel. It is not easy to explain it in a few words. I will write a detailed introduction to the delay function in the future. I will post it here after I finish writing it. For students who have just come into contact with STM32, I suggest that you just call this function at the beginning, and don’t delve into its implementation principle, because it involves a lot of other content. If you just start to contact STM32 with zero foundation, it will be very discouraging to read those. The calling method of these two functions: delay_ms(10); passes an integer parameter n when calling, indicating that it will delay for n milliseconds. If the delay_ms(n); function is used in the program, then the delay initialization function delay_init(); must be called before calling the delay function. In this way, it is called without parameters. In addition, the value of n cannot be too large when calling the delay_ms(n); function. The value of n has an upper limit, just like the maximum value that int can represent also has an upper limit. The specific value is related to the clock frequency. When the clock frequency is 72M (this is the default condition), n<=1864. 


The two delay functions mentioned above are not written by myself. The delay.c file in the SYSTEM folder of each experimental code of the Zhengdian Atom has this code, so the blogger just uses it, which is very convenient. If it is another development board, you can check the manual to see how to implement the delay function. If it doesn't work, the following code can also achieve the delay...


void Delay(u32 count)

{

  u32 i=0;

  for(;i


}

 


2.LED_Init(); and KEY_Init(); functions


These two functions are written by myself, which configure the relevant parameters of the IO port. Here is the code first:


void LED_Init(void)

{

 

GPIO_InitTypeDef GPIO_InitStructure;


RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD, ENABLE); //Enable PA, PD port clock


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //LED0-->PA.8 port configuration

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //Push-pull output

GPIO_InitStructure.GPIO_Speed ​​= GPIO_Speed_50MHz; //IO port speed is 50MHz

GPIO_Init(GPIOA, &GPIO_InitStructure); //Initialize GPIOA according to the set parameters.8


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //LED1-->PD.2 port configuration, push-pull output

GPIO_Init(GPIOD, &GPIO_InitStructure); //Push-pull output, IO port speed is 50MHz

}

void KEY_Init(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

 

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,ENABLE); //Enable PORTA, PORTC clock


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; //PA15

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //Set to pull-up input

  GPIO_Init(GPIOA, &GPIO_InitStructure); //Initialize GPIOA15


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //PC5

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //Set to pull-up input

  GPIO_Init(GPIOC, &GPIO_InitStructure); //Initialize GPIOC5

 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//PA0

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 is set to input, pull-down by default   

GPIO_Init(GPIOA, &GPIO_InitStructure); //Initialize GPIOA.0

}

 


For the initialization of GPIO ports, please refer to the blogger’s previous article, STM32 Embedded Learning Primer (2) - Introduction to STM32 GPIO


As for why these parameters are configured here, they are determined according to the hardware connection of the development board. The above code is the code of the Zhengdian Atom MiniSTM32F103RCT6 development board. The schematic diagram of this development board is as follows:



From here you can see the IO ports corresponding to the buttons and whether they are connected to high or low levels. For example, two LEDs are connected to high levels in hardware, so when you set the other end to low level, they will light up, and if the other end is set to high level, they will go out. In addition, the mode of the IO port is also determined by the hardware connection.


3. KEY_Scan(0); function implementation


The implementation of this function is not difficult. It has little to do with the knowledge of STM32. It is just a logic problem of C language. The code is as follows:


//Key processing function

//Return the key value

//mode: 0, does not support continuous pressing; 1, supports continuous pressing;

//return value:

//0, no button is pressed

//KEY0_PRES, KEY0 is pressed

//KEY1_PRES, KEY1 is pressed

//WKUP_PRES, WK_UP pressed 

//Note that this function has a response priority, KEY0>KEY1>WK_UP!!

u8 KEY_Scan(u8 mode)

{  

static u8 key_up=1;//button press and release flag

if(mode)key_up=1; //Support continuous pressing   

if(key_up&&(KEY0==0||KEY1==0||WK_UP==1))

{

delay_ms(10); //debounce 

key_up=0;

if(KEY0==0)

return KEY0_PRES;

else 

if(KEY1==0)

return KEY1_PRES;

else

if(WK_UP==1)

return WKUP_PRES;

}else 

if(KEY0==1&&KEY1==1&&WK_UP==0)

key_up=1;

return 0; // No button pressed

}


Keywords:STM32 Reference address:STM32 Embedded Learning Introduction (3) - STM32F103 key input control LED light

Previous article:STM32 Practice 4. Use timer and serial port to receive instructions to control LED brightness
Next article:Summary of stm32 KEY control LED

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号