STM32 study notes_4 GPIO: LED, buzzer, button, sensor use

GPIO General IO

General Purpose Input Output.

Can be configured as 8 input and output modes. Usually 0~3.3V, some pins allow 5V.

image-20230419020637994

The upper dotted box is the input module, and the lower one is the output module.

The push-pull output is 1 output high level, 0 output low level. The open-drain output is just the opposite, so there is no high-level drive capability. Open-drain output is usually used in some communication protocols, such as I2C pins, so that each pin will not interfere with each other.

schema name nature feature
floating input digital input The pin level can be read, if the pin is floating, the level is uncertain
pull-up input digital input The pin level can be read, the pull-up resistor is connected internally, and the default high level is when it is suspended
pull down input digital input The pin level can be read, the pull-down resistor is connected internally, the default low level when floating
analog input analog input GPIO is invalid, the pin is directly connected to the internal ADC
open drain output digital output Can output pin level, high level is high impedance state, low level is connected to VSS
push-pull output digital output Can output pin level, high level connected to VDD, low level connected to VSS
Multiplexed open-drain output digital output Controlled by the on-chip peripherals, the high level is a high-impedance state, and the low level is connected to VSS
Multiplexed push-pull output digital output Controlled by on-chip peripherals, high level connected to VDD, low level connected to VSS

The difference between the three types of input is that when the floating input pin is floating, the level is uncertain (so try to connect a continuous driving source), and the pull-up and pull-down input will be set to the default high and low levels.

image-20230419144107702

As shown in the figure, the output part is disconnected. The input part is connected to the VDD switch for pull-down, and connected to VSS for pull-up.

The analog input does not use any devices in the figure, and the input signal is directly connected to the ADC module.

The open-drain output and push-pull output depend on whether the high level is a high-impedance state or VDD.

The multiplexed output can be read and connected to peripherals.

image-20230419145406005

It can be seen in the upper part that the input signal is output to the two outlets after being processed by the trigger.

Code: Driving LED lights

Manipulate the GPIO port to drive and light up the LED light.

First build the project template:

image-20230420024857375

Controlling gpio requires three steps: turn on the rcc clock, initialize, and control input and output functions. According to the architecture diagram, we know that GPIO is on the APB2 bus. Let's see what functions are in RCC:

image-20230420025053559

This is to control the APB2 clock, let's take a look at its content:

image-20230420025148413

Parameter 1 is the APB2 port to be operated, and parameter 2 is enabled or disabled. Quite simple.

Then look at the GPIO initialization function:

image-20230420025345860

The first parameter is an option, and the second parameter is a GPIO_InitTypeDef structure. We know that we need to set three variables: input and output mode, pin, speed.

image-20230420040211907

The last one is the input and output function control. This mainly introduces the four functions of GPIO: SetBits ResetBits WriteBit Write

We let GPIOA Pin0 output high or low level, and the other pin of LED is connected to GND or 3.3.

image-20230420143426678
#include "stm32f10x.h"
int main(void){
    
    
    /* 控制gpio需要三个步骤:开启rcc时钟,初始化,输入输出函数控制 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    GPIO_SetBits(GPIOA,GPIO_Pin_0);
    while(1){
    
    }
}

Reset is set to 0, our circuit design is 0 on, so reset is on and set is off.

It can also be written through the write function.GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);

Then you can use the delay function provided by the teacher of Jiangxie Technology to make the LED light flashing effect:

while(1){
    
    
        GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);
        Delay_ms(500);
        GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);
        Delay_ms(500);
    }

In fact, Bit_SET is 1, and RESET is 0, but we cannot directly assign a value of 0 or 1 to the function, and a type conversion is required.

while(1){
    
    
        GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)1);
        Delay_ms(500);
        GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)0);
        Delay_ms(500);
    }

Here because we are using a push-pull output, both high and low levels have driving capabilities. If it is changed to an open-drain output, the high level will have no drive capability. The open-drain output cannot allow one end of the LED to be grounded and the other end to be connected to the output, because the high level cannot be driven. It can only be connected to 3.3 at one end and output at the other end.

Therefore, push-pull output is more convenient most of the time, and there are not many application scenarios for open-drain output.

Then we try the water lamp. This is to connect multiple LED lights to pin01234567, and turn on them in while. There is nothing to say, just a place: when initializing, you can write like this:

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;

Initialize multiple at the same time. The principle of doing this is that the corresponding values ​​of these pins are 0000 0001, 0000 0010, 0000 0100, 0000 1000...can be ORed.

Similarly, we can also replace the writebit function with the write function:

GPIO_WriteBit(GPIOA,~00000010);Only the second bit, pin1, is lit.

Code: Buzzer

The buzzer used here is simpler than that of 51, and it will ring when the power is supplied without constantly reversing. But the frequency cannot be adjusted.

The buzzer prompts 3 pins, GND, VCC, IO. IO We randomly pick a pin input (don't pick the three pins used by JTAG! A15 B3 B4)

GPIO_ResetBits(GPIOB, GPIO_Pin_12);

code: button

The button is a mechanical spring structure, and it will vibrate for 5-10ms when it is pressed and released.

Buttons can be processed in four ways: connect to low level (pull-up input), connect to high level (pull-down input, not common), and add pull-up and pull-down resistors.
image-20230421025011700

For this project, we create a new HardWare folder and add some modular functions in it. For example, the button use case we want to write this time is that two buttons independently control two LED lights, then the LED.c code:

#include "stm32f10x.h"                  // Device header

void LED_Init(void){
    
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin= GPIO_Pin_0 | GPIO_Pin_1;//两个灯泡接在 A0 A1上
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
}

void LED1_On(void){
    
    
    GPIO_ResetBits(GPIOA, GPIO_Pin_0);
}

void LED1_Off(void){
    
    
    GPIO_SetBits(GPIOA, GPIO_Pin_0);
}

void LED2_On(void){
    
    
    GPIO_ResetBits(GPIOA, GPIO_Pin_1);
}

void LED2_Off(void){
    
    
    GPIO_SetBits(GPIOA, GPIO_Pin_1);
}

And supplement the response.h file.

Of course, you can define a LED_Set function and pass in two parameters to determine which lights to turn on.

Or in fact, just one, pass in 11 10 01 00 to represent the state of the light.

Processing of key input: first initialize GPIOB to read key input, and set the mode to pull-up input

void Key_Init(void){
    
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//上拉输入
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0 | GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//其实输入模式下这个参数没用
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

How to deal with the input data? Refer to the file in GPIO.h:

uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);

The last two are to read the input port and see what it outputs.

When we read the key input, we read a certain bit in the input mode.

A simple button to light up the LED only needs to read the first function, remember to debounce.

uint8_t Key_GetNum(void){
    
    
    uint8_t KeyNum=0;//按下按键时=1
    if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0)==0){
    
    
        Delay_ms(20);
        while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0)==0);
        Delay_ms(20);
        KeyNum+=1;
    }
    if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_10)==0){
    
    
        Delay_ms(20);
        while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_10)==0);
        Delay_ms(20);
        KeyNum+=2;
    }
    return KeyNum;
}

Here I use binary to judge how the two buttons are pressed.

int main(void){
    
    
    LED_Init();
    Key_Init();
    LED1_Off();
    LED2_Off();
    uint8_t KeyNum;
    while(1){
    
    
        KeyNum=Key_GetNum();
        if(KeyNum>0){
    
    
            if(KeyNum%2==1)LED1_On();
            if(KeyNum>=2)LED2_On();
        }
    }
}

This is just a test code, the effect of running is that the LED is permanently lit after pressing the button.

How to make the LED reverse state after pressing the button? At this time, we can use the reading of the current output described in the input. Instead of using LED_On and Off, we use Turn.

void LED1_Turn(void){
    
    
	if(GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_0)==1)GPIO_ResetBits(GPIOA, GPIO_Pin_0);
    else GPIO_SetBits(GPIOA, GPIO_Pin_0);
}

void LED2_Turn(void){
    
    
    if(GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1)==1)GPIO_ResetBits(GPIOA, GPIO_Pin_1);
    else GPIO_SetBits(GPIOA, GPIO_Pin_1);
}

Code: Sensor

Principle: There is a resistor inside that is changed by the value of the sensing factor, a fixed-value resistor, and we can judge the current resistance value according to the divided voltage. Photoresistors, thermistors, and infrared receivers are similar.

Analog output AO: the analog voltage value output according to the value of the sensor resistance. N1 in the figure is the sensor resistance.

There may also be a filter capacitor, both ends of which are connected to VDD GND to stabilize the control voltage (left side).

image-20230420205300753

The smaller the resistance value of the pull-up and pull-down resistors, the stronger the pulling force.

Digital output DO: Adjustment of AO output, a voltage comparator, same direction > reverse output VCC, otherwise output GND.

image-20230421024424317

where IN+ is the analog input, our sensor. IN- is an adjustable potentiometer.

image-20230421024607421

The overall circuit simplification is as follows:

image-20230421024728192

On the left is a power light.

The second is the DO light.

The third is a pull-up resistor that ensures a default high level.

Next we write a use case where the photosensitive sensor controls the buzzer. Just DO.

The code is actually very similar to the button, DO reads the input and outputs to the buzzer.

int main(void){
    
    
    Buzzer_Init();
    
    while(1){
    
    
        if(LightSensor_Get()==1)Buzzer_On();
        else Buzzer_Off();
    }
}
void LightSensor_Init(void){
    
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

uint8_t LightSensor_Get(void){
    
    
    return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13);
}
void Buzzer_Init(void){
    
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

void Buzzer_On(void){
    
    
    GPIO_ResetBits(GPIOB, GPIO_Pin_12);
}

void Buzzer_Off(void){
    
    
    GPIO_SetBits(GPIOB, GPIO_Pin_12);
}

The photosensitive sensor has a large resistance value when there is little light, and the read value is assigned to 1. You can adjust the level by twisting the potentiometer.

Both the buzzer and the LED are low-level sounding/lighting, so I unplug the buzzer and replace it with a high-level LED connected to 3.3 to realize the night light.

Guess you like

Origin blog.csdn.net/jtwqwq/article/details/130299783