STM32 controls the color and brightness of LED lights through Key

As the title says, use Keil uVision5 as the platform to control the brightness and color changes of the LED (red, green, blue, white cycle) through the GPIO register to STM32F103VE.

Title and analysis

Press KEY1 to control the LED light to switch between four modes: “red light – green light – blue light – white light”

Press KEY2 to control the LED light to turn off

Prerequisite knowledge

First, according to the introduction of the circuit board, we know that the Key1 and Key2 interfaces are GPIO PA0 and PC13. At the same time, according to the structural schematic diagram

It can be seen that when these buttons are not pressed, the input status of the GPIO pin is low level (the circuit where the button is located is blocked and the pin is grounded). When the button is pressed, the input status of the GPIO pin is high level ( The circuit where the button is located is turned on and the pin is connected to the power supply). As long as we detect the input level of the pin, we can determine whether the button is pressed. That is, the function KEY_Scan() needs to be used.

At the same time, remember the pins of R, G, and B lights of different colors, and correspond them in subsequent define or header files. Here, the author defines R, G, and B as LED1, LED2, and LED3 respectively (of course, it is recommended to define them as LEDR, G, and B for readability). The corresponding pins are Pin5, Pin0, and Pin1.

Read GPIO input

The input level of the GPIO pin can be sensed by reading the data bit corresponding to the IDR register; and the STM32 standard library provides the library function GPIO_ReadInputDataBit to obtain the bit status; so how do we determine what happened after this button was pressed? The author here provides an algorithm that is not perfect or satisfactory:

If a button press is detected, use a while loop to continuously detect the button status until the button is released. After the button is released, the Key_Scan function returns a “KEY_ON” value; if no button is detected

Press, the function directly returns “KEY_OFF”.

Readers can optimize by themselves, including the determination of whether the button is released (after the author’s experiment, I found that there is not much difference between the two on the development board, but the algorithm is ugly)

Algorithm

The overall algorithm is divided into two parts. The first part uses library functions and header files to bind key1key2 to LED123, and the second part solves the loop problem. The circuit board here actually has a counting function, which can be output using the judgment of cycle setting modulo four. The author chose the simpler switch function here. Interested students can try for and while.

Writing header files

Here we need to include three header files, of which stm32f10x.h and stm32f10x_gpio.h are included in the library, and the other one needs to be created by yourself (of course it is no problem to write it directly in main.c, mainly once it is written) Projects that require LED can be called directly). Here the author names it bsp_led.h.

#ifndef __LED_H
#define __LED_H


#include "stm32f10x.h"


//red
#define LED1_GPIO_PORT GPIOB /*GPIO port*/
#define LED1_GPIO_CLK RCC_APB2Periph_GPIOB/*GPIO port clock*/
#define LED1_GPIO_PIN GPIO_Pin_5 /*GPIO connected to SCL clock line*/

//green
#define LED2_GPIO_PORT GPIOB
#define LED2_GPIO_CLK RCC_APB2Periph_GPIOB
#define LED2_GPIO_PIN GPIO_Pin_0

//bule
#define LED3_GPIO_PORT GPIOB
#define LED3_GPIO_CLK RCC_APB2Periph_GPIOB
#define LED3_GPIO_PIN GPIO_Pin_1



#define ON 0 /*This is related to high and low level input and output. If you are interested, you can search for the structural schematic diagram*/
#define OFF 1

/*Use standard firmware library to control IO*/
#define LED1(a) if (a)
GPIO_SetBits(LED1_GPIO_PORT,LED1_GPIO_PIN);
else
GPIO_ResetBits(LED1_GPIO_PORT,LED1_GPIO_PIN)

#define LED2(a) if (a)
GPIO_SetBits(LED2_GPIO_PORT,LED2_GPIO_PIN);
else
GPIO_ResetBits(LED2_GPIO_PORT,LED2_GPIO_PIN)

#define LED3(a) if (a)
GPIO_SetBits(LED3_GPIO_PORT,LED3_GPIO_PIN);
else
GPIO_ResetBits(LED3_GPIO_PORT,LED3_GPIO_PIN)

/*Here defines macros for controlling IO*/
#define LED1_TOGGLE digitalToggle(LED1_GPIO_PORT,LED1_GPIO_PIN)
#define LED1_OFF digitalHi(LED1_GPIO_PORT,LED1_GPIO_PIN)
#define LED1_ON digitalLo(LED1_GPIO_PORT,LED1_GPIO_PIN)

#define LED2_TOGGLE digitalToggle(LED2_GPIO_PORT,LED2_GPIO_PIN)
#define LED2_OFF digitalHi(LED2_GPIO_PORT,LED2_GPIO_PIN)
#define LED2_ON digitalLo(LED2_GPIO_PORT,LED2_GPIO_PIN)

#define LED3_TOGGLE digitalToggle(LED3_GPIO_PORT,LED3_GPIO_PIN)
#define LED3_OFF digitalHi(LED3_GPIO_PORT,LED3_GPIO_PIN)
#define LED3_ON digitalLo(LED3_GPIO_PORT,LED3_GPIO_PIN)
/*Note that the above pin LED1_GPIO_PIN is actually the same as GPIO_PIN_5 and can be replaced with each other*/

void LED_GPIO_Config(void);

#endif 

Initialization and Miscellaneous

How to use GPIO to control KEY to control the LED on and off? Here you need to use two functions: GPIO_ResetBits() and GPIO_WriteBit() to control the on and off, which is to enter Bit_Reset or Bit_Set in the following function.

Then before we write the main function, we need to initialize the LED port and GPIO peripherals. The code is as follows

 GPIO_InitTypeDef GPIO_InitStructure;/*To avoid errors, it is recommended to write this code at the top of all initializations*/
  RCC_APB2PeriphClockCmd(KEY1_GPIO_CLK|KEY2_GPIO_CLK|LED_GPIO_CLK,ENABLE);
  GPIO_InitStructure.GPIO_Pin=LED1_GPIO_PIN|LED2_GPIO_PIN|LED3_GPIO_PIN;
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
  GPIO_Init(LED_GPIO_PORT, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin=KEY1_GPIO_PIN;
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
  GPIO_Init(KEY1_GPIO_PORT, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin=KEY2_GPIO_PIN;
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
  GPIO_Init(KEY2_GPIO_PORT, &GPIO_InitStructure);
  GPIO_WriteBit(LED_GPIO_PORT,LED1_GPIO_PIN|LED2_GPIO_PIN|LED3_GPIO_PIN,Bit_SET);
  //The above are all initialization of GPIO peripherals
  LED_GPIO_Config(); /*LED initialization and if an error is reported, it is recommended to put it on the second line*/

Miscellaneous define (I re-bind the PIN for RGB and use it later, but you don’t need to, just look for the correct PIN from the header file)

#define SOFT_DELAY Delay(0x0FFFFF);

#define KEY1_GPIO_CLK RCC_APB2Periph_GPIOA
#define KEY1_GPIO_PORT GPIOA
#define KEY1_GPIO_PIN GPIO_Pin_0

#define KEY2_GPIO_CLK RCC_APB2Periph_GPIOC
#define KEY2_GPIO_PORT GPIOC
#define KEY2_GPIO_PIN GPIO_Pin_13

#define LED_GPIO_CLK RCC_APB2Periph_GPIOB
#define LED_GPIO_PORT GPIOB
#define LEDG_GPIO_PIN GPIO_PIN_0
#define LEDB_GPIO_PIN GPIO_PIN_1
#define LEDR_GPIO_PIN GPIO_PIN_5

#define KEY_ON 1/*Be careful not to confuse it with LED*/
#define KEY_OFF 0

void Delay(__IO u32 nCount); /*Set a delay function*/

Overall code implementation

Students copying homework can read this directly (remember to add qwq to the previous header file first)

#include "stm32f10x.h"
#include "bsp_led.h"
#include "stm32f10x_gpio.h"

#define SOFT_DELAY Delay(0x0FFFFF);

#define KEY1_GPIO_CLK RCC_APB2Periph_GPIOA
#define KEY1_GPIO_PORT GPIOA
#define KEY1_GPIO_PIN GPIO_Pin_0

#define KEY2_GPIO_CLK RCC_APB2Periph_GPIOC
#define KEY2_GPIO_PORT GPIOC
#define KEY2_GPIO_PIN GPIO_Pin_13

#define LED_GPIO_CLK RCC_APB2Periph_GPIOB
#define LED_GPIO_PORT GPIOB
#define LEDG_GPIO_PIN GPIO_PIN_0
#define LEDB_GPIO_PIN GPIO_PIN_1
#define LEDR_GPIO_PIN GPIO_PIN_5

#define KEY_ON 1
#define KEY_OFF 0

uint8_t Key_Scan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin)
{
if (GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON)
{while (GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON);
return KEY_ON;
}else
return KEY_OFF;
}/*The ugly loop verification algorithm mentioned above*/

void Delay(__IO u32 nCount);

int main(void)
{
int flag=0;
GPIO_InitTypeDef GPIO_InitStructure;

LED_GPIO_Config();
RCC_APB2PeriphClockCmd(KEY1_GPIO_CLK|KEY2_GPIO_CLK|LED_GPIO_CLK,ENABLE);

  GPIO_InitStructure.GPIO_Pin=LED1_GPIO_PIN|LED2_GPIO_PIN|LED3_GPIO_PIN;
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
  GPIO_Init(LED_GPIO_PORT, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin=KEY1_GPIO_PIN;
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
  GPIO_Init(KEY1_GPIO_PORT, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin=KEY2_GPIO_PIN;
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
  GPIO_Init(KEY2_GPIO_PORT, &GPIO_InitStructure);
  GPIO_WriteBit(LED_GPIO_PORT,LED1_GPIO_PIN|LED2_GPIO_PIN|LED3_GPIO_PIN,Bit_SET);


while (1)
{
if(Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==KEY_ON)
{
\t\t\t
switch(flag)
{ /*Here you must make sure that when one light is on, make sure the other two are off, otherwise other colors of light will be synthesized*/
case 0:
flag + + ;
GPIO_ResetBits(LED_GPIO_PORT,LED1_GPIO_PIN);
                GPIO_WriteBit(LED_GPIO_PORT,LED1_GPIO_PIN,Bit_RESET);
GPIO_ResetBits(LED_GPIO_PORT,LED2_GPIO_PIN);
GPIO_WriteBit(LED_GPIO_PORT,LED2_GPIO_PIN,Bit_SET);
GPIO_ResetBits(LED_GPIO_PORT,LED3_GPIO_PIN);
GPIO_WriteBit(LED_GPIO_PORT,LED3_GPIO_PIN,Bit_SET);
break;
\t\t\t\t
case 1:
flag + + ;
GPIO_ResetBits(LED_GPIO_PORT,LED1_GPIO_PIN);
GPIO_WriteBit(LED_GPIO_PORT,LED1_GPIO_PIN,Bit_SET);
GPIO_ResetBits(LED_GPIO_PORT,LED2_GPIO_PIN);
GPIO_WriteBit(LED_GPIO_PORT,LED2_GPIO_PIN,Bit_RESET);
GPIO_ResetBits(LED_GPIO_PORT,LED3_GPIO_PIN);
GPIO_WriteBit(LED_GPIO_PORT,LED3_GPIO_PIN,Bit_SET);
break;
\t\t\t\t
case 2:
flag + + ;
GPIO_ResetBits(LED_GPIO_PORT,LED1_GPIO_PIN);
GPIO_WriteBit(LED_GPIO_PORT,LED1_GPIO_PIN,Bit_SET);
GPIO_ResetBits(LED_GPIO_PORT,LED2_GPIO_PIN);
GPIO_WriteBit(LED_GPIO_PORT,LED2_GPIO_PIN,Bit_SET);
GPIO_ResetBits(LED_GPIO_PORT,LED3_GPIO_PIN);
GPIO_WriteBit(LED_GPIO_PORT,LED3_GPIO_PIN,Bit_RESET);
break;
\t\t\t\t
case 3:
flag=0;
GPIO_ResetBits(LED_GPIO_PORT,LED1_GPIO_PIN);
                GPIO_WriteBit(LED_GPIO_PORT,LED1_GPIO_PIN,Bit_RESET);
GPIO_ResetBits(LED_GPIO_PORT,LED2_GPIO_PIN);
GPIO_WriteBit(LED_GPIO_PORT,LED2_GPIO_PIN,Bit_RESET);
GPIO_ResetBits(LED_GPIO_PORT,LED3_GPIO_PIN);
GPIO_WriteBit(LED_GPIO_PORT,LED3_GPIO_PIN,Bit_RESET);
break;
}
\t\t\t
}
else if(Key_Scan(KEY2_GPIO_PORT,KEY2_GPIO_PIN)==KEY_ON)
{
GPIO_ResetBits(LED_GPIO_PORT,LED1_GPIO_PIN);
      GPIO_WriteBit(LED_GPIO_PORT,LED1_GPIO_PIN,Bit_SET);
GPIO_ResetBits(LED_GPIO_PORT,LED2_GPIO_PIN);
      GPIO_WriteBit(LED_GPIO_PORT,LED2_GPIO_PIN,Bit_SET);
GPIO_ResetBits(LED_GPIO_PORT,LED3_GPIO_PIN);
      GPIO_WriteBit(LED_GPIO_PORT,LED3_GPIO_PIN,Bit_SET);
}
\t\t
}

}

Shortcomings

The first is the loop verification problem mentioned above. It will continue to loop after pressing the key. There is a more concise algorithm implementation on the site. Students can learn it. The second is whether the switch algorithm is too troublesome. It can count the number of key1 button presses. The number of times can be cyclically judged, which should be more concise. Have a nice day everyone.