[Blue Bridge Cup] Embedded programming_KEY module

Table of contents

Know the schematic diagram of the button

Key code configuration

Module KEY code reference

main program design

uwTick small practice

XOR Logic Exercises

Long press and short press practice


Know the schematic diagram of the button

05d7e873f2be4c108d1247adff74ce6b.png

Source of this picture: CT117E-M4 Product Manual.pdf

PB0 PB1 PB2 PA0 respectively correspond to buttons B1 B2 B3 B4 When the button is pressed, the GPIO port detects high and low levels and does not need to output

Therefore, we choose the input mode. The button is not pressed. The GPIO port is always detected as a high level. When the button is pressed, the GPIO port is detected as a low level. So we choose the floating input mode (no pull-up or pull-down)

Module set not ready to use interrupt

Thinking about how to detect that a key is pressed?

Use falling edge or rising edge?

Key code configuration

2b5b8c61291e43b593826890c5caa8b4.png

 (Note that this MX configuration is not configured on the basis of the previous led module)

b987048605744b65bbe73cff3d463843.png

Module KEY code reference

Because it is not configured on the previous led mx, the function MX_GPIO_Init added key.c will have a function with the same name. We need to change the name of the main function. Don’t worry about conflicting with the module ledGPIO configuration when calling the configuration function!

filekey.c

#include "key.h"
unsigned char key_val;
unsigned char key_old;
unsigned char key_down;
void MX_GPIO_key_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  /*Configure GPIO pin : PA0 */
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  /*Configure GPIO pins : PB0 PB1 PB2 */
  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
unsigned char key_can(void)
{
    //思路不断做if判断引脚电平 低电平代表该键按下 
     if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == 0) 
         return B1;
     else if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == 0) 
         return B2;
     else if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == 0) 
         return B3;
     else if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == 0) 
         return B4;
     else 
         return (unsigned char)0;//没有按键被按下
}
//检测下降沿函数
unsigned char key_down_fun(void)
{
        
    //新值异或旧值再与新值得到下降沿
    key_val=key_can();
    key_down=(key_val^key_old)&key_val;
    key_old=key_val;
    return key_down;
}
filekey.h
​​​​​​​#ifndef __KEY_H__
#define __KEY_H__
#include "main.h" 
#define B1 (unsigned char)1
#define B2 (unsigned char)2
#define B3 (unsigned char)3
#define B4 (unsigned char)4
void MX_GPIO_key_Init(void);
unsigned char key_can(void);
unsigned char key_down_fun(void);
#endif

main program design

//设置周期的变量
#include "key.h"
__IO uint32_t uwTick_key;
void key_proc(void);

int main(void)
{
    MX_GPIO_key_Init();
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_key_Init();
    while (1)
  {
        key_proc();
  }
 
}

void key_proc(void)
{    

    if((uwTick-uwTick_key)<100) return;
    uwTick_key = uwTick;
    
    //设置扫描周期
    unsigned char key_down = key_down_fun();
    if(key_down == B1)//按键被按下
        Led_Input_Disp(0XFF);
    if(key_down == B2)
        Led_Input_Disp(0X00);
    if(key_down == B3)
        Led_Input_Disp(0X88);
    if(key_down == B4)
        Led_Input_Disp(0Xaa);
}

Introducing the new member uwTick

After the program runs, this value will always increase by itself, which is fixed like a counter unit time, so it is called a timer

uwTick small practice

Now use uwTick to realize that B1 presses the indicator light and the LED is all on for 5 seconds and then turns off

void key_proc(void)
{    

    if((uwTick-uwTick_key)<100) return;
    uwTick_key = uwTick;
    static unsigned char B1down_Do_Time;
    static __IO uint32_t uwTick_key_delay;
    
    unsigned char key_down = key_down_fun();
    if(key_down == B1){
        Led_Input_Disp(0XFF);
        B1down_Do_Time = 1;
        uwTick_key_delay = uwTick;
    }
        
    if(((uwTick-uwTick_key_delay)>= 5000)&&(B1down_Do_Time == 1))
        Led_Input_Disp(0X00);

}

Do you understand the logic above? UwTick is cleverly used to realize the delay, but there are still some problems in the program.... B1down_Do_Time is not reset to 0, so that the same effect occurs again in the program.

XOR Logic Exercises

Now use uwTick to realize that B1 is pressed and the indicator LED flashes for 5 seconds and then turns off

void key_proc(void)
{    
    if((uwTick-uwTick_key)<100) return;//准备这段时间是led的闪烁间隔  有扫描函数的存在也不宜过大
    uwTick_key = uwTick;
    static unsigned char B1down_Do_Time;
    static __IO uint32_t uwTick_key_delay;
    static unsigned char ucLed;
    unsigned char key_down = key_down_fun();
    if(key_down == B1){
        B1down_Do_Time = 1;
        uwTick_key_delay = uwTick;
    }
    if(B1down_Do_Time == 1){
        ucLed ^= 0xff; //异或操作 不同为1 相同为零   实现进行闪烁操作
    }    
    if(((uwTick-uwTick_key_delay)>= 5000)&&(B1down_Do_Time == 1)){
    // if(((uwTick_key_delay+5000) <= uwTick)...
      //  Led_Input_Disp(0X00);
        B1down_Do_Time = 0;
        ucLed &= (~0xff);            //与操作就是清零操作
    }
    Led_Input_Disp(ucLed);
}

Long press and short press practice

Now realize short press B1 (<800ms) led1 to switch the flashing light state and long press B1 led1 to realize the flashing light effect (the interval is 500ms)

void key1_fun(void)
{
	
	static unsigned char uled;
	static __IO uint32_t uwTick_key_up_time;
	static __IO uint32_t uwTick_key1;
	static __IO uint32_t uwTick_key_delay1;
	
	key_new=key_scan();
	key_down = (key_new^key_old)&key_new;
	key_up=(key_new^key_old)&~key_new;
	key_old=key_new;


	if(key_down)
	{
		uwTick_key_up_time = uwTick;
		uwTick_key_delay1 = uwTick;
	}

	if((uwTick - uwTick_key_up_time) <= 800)//短按识别
	{
				if(key_up == B1)
				{
				uled ^= 0x01;
				
				}
				
	}else //长按
	{
		
				if(key_new == B1&& uwTick-uwTick_key_delay1>500)
				{
					uled ^= 0x01; 
					
				uwTick_key_delay1 = uwTick;
				}
	}
		inputchar_led_display(uled);
}	

Guess you like

Origin blog.csdn.net/shelter1234567/article/details/129116002