STM32 microcontroller beginner 3-GPIO detailed explanation

GPIO (General-purpose input/output) is general-purpose input and output. GPIO is the most basic peripheral of the microcontroller, and any other peripheral is inseparable from GPIO. This article will explain in detail the internal structure and working principle of GPIO, and attach a simple program for beginners to learn.

Different from 51 single-chip microcomputer (51 single-chip microcomputer can directly control the high and low level of IO port by writing P0=0xff or P0^1=1), the IO of STM32 must be initialized and the corresponding clock must be initialized before use, otherwise The IO port will not output.

First look at the GPIO internal structure diagram (below)

 The IO port has two paths, one is output (I:in) and the other is input (O:out).

We call the part that controls the IO input the input driver (as shown in the upper dashed box in the figure above), which consists of a Schottky trigger and a set of pull-up and pull-down resistors and their control switches. When the Schottky trigger is used for digital input (that is, 1 and 0), it maintains the stability of the level (the principle will not be elaborated), if it is used as an analog input, the Schottky trigger will be skipped. The state of the switch and pull-up resistor on the right depends on the mode of the IO port, which will be explained in detail below.

Similarly, we call the part that controls the IO output the output driver (as shown in the lower dashed box in the figure above), which consists of an output controller and two MOS tubes (the upper tube is PMOS, connected to VCC; the lower tube is NMOS, connected to GND connected) composition. The output controller is used to control the switch state of the two mos tubes to output high level or low level, and its state also depends on the mode of IO, which will be explained in detail below.

The protection diode is used to limit the level of the IO port between Vss and Vdd.

Next, we will introduce the working status of GPIO in each mode in detail.

 The GPIO of STM32 has 8 modes (4 types of input, 4 types of output), as shown in the following table:

 1. Analog input AIN

First of all, in the input mode (no matter which input mode), the two MOS transistors of the output driver are all in the disconnected state.

The analog input mode is used to convert the voltage analog of 0-3.3V (3.3V is based on the power supply voltage of the microcontroller, if the voltage is 3.2V, it is 0-3.2V) into 0-2^12 (take STM32F103C8T6 as an example , its ADC is 12 bits, so it is 0 to 2 to the 12th power) digital quantity for CPU use. This mode is required for analog signal acquisition, such as temperature and humidity acquisition, voltage and current acquisition, etc.

 In this mode, the upper and lower switches of the input driver are all off, and the analog path is shown by the arrow in the figure above.

The voltage of the IO is directly input to the on-chip ADC.

2. Floating input IN_FLOATING

This mode is used for digital input, and the CPU will collect the level of the IO port.

In this mode, the upper and lower switches of the input driver are all disconnected (at this time, the IO port is in a high configuration, which can be considered as an internal disconnection between the IO and the microcontroller), and the signal path is shown by the arrow in the figure above. For the convenience of research, the input driver is simplified as follows.

In this mode, if the IO port is in a floating state (that is, the IO port is neither high nor low), the value collected by the CPU will also be in an uncertain state, so this input mode requires an external A pull-up or pull-down resistor is required for stable input (see below).

 For the external pull-up resistor method: when the switch is turned off, the IO level will be pulled to VCC, which is a high level, and when the switch is closed, the IO is directly connected to GND and forced to become a low level. (off 1 off 0)

 For the external pull-down resistor method: when the switch is turned off, the level of IO will be pulled to GND, that is, low level, and when the switch is closed, IO is directly connected to VCC, forcing it to become high level. (off 0 off 1)

The switching logic of the two connection methods is just opposite. The resistance value of the pull-up (pull-down) resistor can be 1K-10K (not less than the maximum sink current of VCC/pin).

The function of the pull-up (pull-down) resistor in both connections is to limit the current when the switch is closed. Without these two resistors, VCC is shorted directly to GND when the switch is closed.

3. Pull down and input IPD

This mode is the same as the pull-down resistor method of floating input, except that the external pull-down resistor is omitted, and the on-chip pull-down resistor is used.

In this mode, the on-chip pull-down switch remains closed and the pull-up switch remains open.

 When the external switch is turned off, the level of IO will be pulled to VSS, that is, low level, and when the switch is closed, IO is directly connected to VCC, forcing it to become high level. (off 0 off 1)

4. Pull up input IPU

This mode is opposite to the pull-down input, and the principle of the pull-up resistor connection of the floating input is the same. That is, the on-chip pull-up switch remains closed and the pull-down switch remains open.

  When the external switch is turned off, the level of IO will be pulled to VDD, that is, high level, and when the switch is closed, IO is directly connected to GND, forcing it to become low level. (off 1 off 0)

Its switching logic is the opposite of the pull-up input.

5. Open drain output OUT_OD

Again, in output mode (regardless of input mode), both switches of the input driver are open.

For the convenience of research, the output driver circuit is simplified as follows (two MOS tubes are simplified into switches):

 In open-drain mode, the high side remains disconnected.

When the IO port outputs 1, the lower tube is disconnected, and the IO is disconnected from the MCU;

When the IO outputs 0, the lower switch is closed, the IO is directly connected to VSS, and the clamp is set to a low level.

 Observation will find that when the IO port outputs 1, its state is not to output high level (IO is disconnected from the inside of the microcontroller, which can be considered as a high-impedance state), and when it outputs 0, the state is to output low level. This is the characteristic of open-drain output: the open-drain output mode cannot directly output high level, but can only output low level (from the perspective of current, the current can only flow into the IO port of the microcontroller). That's why the open-drain output gets its name: the only two states are open circuit or current flow.

So if you want to use this mode to drive an LED light, there are two connection methods: external pull-up resistor and sink connection.

 When the IO port outputs 1, the IO itself does not output a high level, but the IO port can output a high level through a pull-up resistor, so the LED is lit. The pull-up resistor is also the current-limiting resistor of the LED. In this state, without the pull-up resistor, VCC will be directly added to both ends of the LED, which will burn the LED.

When the IO output is 0, the lower tube is turned on, the IO port is connected to VSS, the anode of the LED is at low level, there is no voltage at both ends of the LED, and it goes out. The current flows from VCC through the pull-up resistor to the IO port and then to VSS.

It can be found that in this mode, no matter whether the output IO output is 1 or 0, and no matter whether the LED is on or off, there will be current flowing through the pull-up resistor, that is, it will consume current, and the current will be larger when the LED is off.

 This mode looks simpler than the pull-up resistor connection. The anode of the LED is connected to VCC, and the cathode is connected to the IO port.

When the IO port outputs 1, the lower tube is disconnected, the LED loop is open, the current cannot flow through the LED, and the LED is off.

When the IO port outputs 0, the lower tube is closed, the LED loop is closed, the current flows from VCC through the LED, and then flows into the IO port of the microcontroller through the LED, and then flows to VSS, and the LED lights up .

In this connection, the state of the LED is opposite to the logic of the IO port in the program (1 off, 0 on). When the LED is off, it consumes no energy at all, and only consumes current when it is on.

The function of the current-limiting resistor is to limit the current flowing through the LED when the LED is on, so as not to burn out, and its size can be calculated according to Vcc/LED working current.

6. Push-pull output OUT_PP

Push-pull output is one of the most commonly used modes. It can output both high level and low level, and has a strong driving ability.

In this mode, the state of the top tube and the down tube are always reversed.

When the IO port outputs 1, the upper tube is closed, the lower tube is disconnected, and the IO port is directly connected to VDD, which is a high level;

When the IO port outputs 0, the upper tube is disconnected, the lower tube is closed, and the IO port is directly connected to VSS, which is a low level.

In this mode, there are two connection methods of active type and sink type.

Source connection method, when the IO port outputs a high level, the LED lights up. The current flows out from the IO port, flows through the current limiting resistor and the LED to GNG

 

 Sink connection, when the IO port outputs a low level, the LED lights up. The current flows through the current limiting resistor, the LED flows in from the IO port, and then flows to VSS.

In this mode, do not directly connect the IO port pins together, because when the output status of the IO port is different, the IO port will be short-circuited (as shown below), which is easy to burn out the IO port.

 

7. Multiplexing open-drain output AF_OD

The multiplexing open-drain output refers to the open-drain output of the multiplexing function, and the working principle is the same as that of the open-drain output. The peripheral interfaces of STM32 (such as IIC, SPI communication interface, etc.) are all multiplexed IO ports. Assuming that PB10 and PB11 are used as the IIC communication interface, after using the multiplexed open-drain output mode, the status of these two IOs will be completely controlled by The internal peripheral output decision is no longer controlled by the GPIO output data register. It can effectively avoid the misoperation of GPIO from affecting the normal communication of IIC.

 8. Multiplexing push-pull output AF_PP

The multiplexing open-drain output refers to the push-pull output of the multiplexing function, and the working principle is the same as that of the push-pull output. It is also an output for multiplexing functions. The specific use of multiplexing push-pull or multiplexing open-drain depends on the situation. Similarly, the multiplexed open drain cannot directly output high level, and an external pull-up resistor is required. Therefore, in actual use, multiplexing push-pull is still used more.

The 8 modes of GPIO have been introduced, and the following is a simple program to demonstrate how to use the GPIO of STM32.

Check the STM32 peripheral manual, GPIO has many functions.

 But this article only talks about the basic use of GPIO: GPIO initialization, GPIO setting and reset.

As mentioned earlier, GPIO needs to be initialized before use.

The following is a simple GPIO initialization function, and the function of each line of program is analyzed below.

void GPIO_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;        //定义一个GPIO初始化参数的结构体
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   //启用GPIOB的时钟
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;     //选择要初始化的引脚
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;      //设置IO速度
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_PP;       //设置IO模式
	GPIO_Init(GPIOA,&GPIO_InitStructure);	        //初始化
}

Here I define a function void GPIO_Init(void) for GPIO initialization. As long as the function is called in the main function, the corresponding IO port can be initialized.

GPIO_InitTypeDef GPIO_InitStructure:

This line of program defines a structure named GPIO_InitStructure (this name can be chosen freely), and the prototype of this structure is GPIO_InitTypeDef (spelling must be exactly the same and cannot be changed). GPIO_InitTypeDef is defined in stm32f10x_gpio.h in the STM32 peripheral library . It consists of three members: GPIO_Pin, GPIO_Speed, and GPIO_Mode, which correspond to the three parameters of Pin value, speed, and mode.

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE):

Different from 51 single-chip microcomputer, each peripheral of STM32 has a dedicated clock controller. If you want to use the corresponding peripheral, you need to turn on the corresponding clock controller (the default is not turned on, the purpose is to reduce power consumption), otherwise the Any operation on GPIO is invalid. Looking at the internal structure diagram of STM32, the clock controller of the GPIO port is APB2, so this line of program is used to open the clock controller APB2 of GPIO.

If you want to open multiple groups at the same time, you can write it as RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE), and separate multiple groups of GPIO with |.

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; 

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;     

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_PP;    

A GPIO_InitStructure structure has been defined before, and these 3 lines are used to assign values ​​​​to the 3 members in it in turn.

The first is the Pin. Which pin you want to initialize, select which pin. Note that the pin identification here is not the pin identification of the microcontroller chip, but the serial number of the pin in its group. For example, pin 10 of STM32F103C8T6 is PA0. If you want to initialize this pin, the Pin value should be assigned as GPIO_Pin_0. Similarly, if you want to initialize the same parameters for multiple IO ports, you can write GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;  every two Pins are separated by |.

If you want to initialize the same parameters for all the IO ports in the group, you can write GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;

Then there is Speed, which is a frequency value representing the level flip speed of the IO port. There are 2MHz, 10MHz, and 50MHz to choose from. If the IO port is used for data transmission (IIC, SPI communication, etc.) or PWM wave transmission and other scenarios that require high-frequency signals, generally select the maximum speed, that is, 50MHz. Of course, common application scenarios can also use 50MHz.

The last is the IO port mode. There are 8 modes to choose from, which have been introduced in detail above.

GPIO_Init(GPIOA,&GPIO_InitStructure);

After the three members are assigned, the initialization can begin. GPIO_Init is a packaged program in the GPIO peripheral library. It has two input variables, one is GPIO, and the other is the parameter in GPIO_InitStructure. The function is to initialize GPIOA according to the parameters in GPIO_InitStructure.

If you need to initialize other IO ports, you can also write according to the above procedure.

After the initialization is completed, the IO port can be set and reset.

Several methods of setting and resetting are listed below, which can be used according to your own habits.

GPIO_SetBits(GPIOA, GPIO_Pin_0);         //PA0输出1
GPIO_ResetBits(GPIOA, GPIO_Pin_0);       //PA0输出0


GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);     //PA0输出1
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);   //PA0输出0


GPIO_Write(GPIOA, 0x1);             //PA0输出1
GPIO_Write(GPIOA, 0x0);             //PA0输出1

Among them, the GPIO_Write function operates on the entire group of GPIOs.

The following is a simple cycle flashing program of LED lights, which can be used as a reference for beginners.

#include<stm32f10x.h>                //STM32头文件
#include<stm32f10x_gpio.h>           //GPIO头文件
#include<stm32f10x_rcc.h>            //RCC时钟头文件

void GPIO_Init(void)            //GPIO初始化子函数
{
	GPIO_InitTypeDef GPIO_InitStructure;                    //定义一个GPIO初始化参数的结构体
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   //启用GPIOB的时钟
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;               //选择要初始化的引脚
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;       //设置IO速度
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_PP;            //设置IO模式
	GPIO_Init(GPIOA,&GPIO_InitStructure);	                //按以上参数初始化GPIO
}

void Delay_ms(int Time)        //延时函数
{
	int i=0;
	while(Time--)
	{
		i=8000;
		while(i--);
	}
	return;
}

void main(void)            //主函数
{
    GPIO_Init;                                    //初始化GPIO
    while(1)
    {
         GPIO_SetBits(GPIOA, GPIO_Pin_0);         //PA0输出1
         Delay_ms(500);                            //延时500ms
         GPIO_ResetBits(GPIOA, GPIO_Pin_0);       //PA0输出0
         Delay_ms(500);                            //延时500ms
    }    
}

After learning the basic GPIO settings and resets, other water light marquees are very simple, so I won’t demonstrate them here.

The above content is personal understanding, if there is any mistake, please correct me

Guess you like

Origin blog.csdn.net/qq_55203246/article/details/123723102