Tangwx

Tangwx

博客网站

03. STM32 GPIO General Input and Output Ports

3 GPIO General Purpose Input Output Ports#

3.1 Introduction to GPIO#

GPIO (General Purpose Input Output) general purpose input output ports

Can be configured into 8 input/output modes

Pin level: 0V~3.3V, some pins can tolerate 5V

In output mode, it can control the port to output high or low levels, used to drive LEDs, control buzzers, simulate communication protocol output timing, etc.

In input mode, it can read the high or low level or voltage of the port, used for reading key inputs, external module level signal inputs, ADC voltage collection, simulating communication protocol receiving data, etc.

3.2 Basic Structure of GPIO#

In STM32, all GPIOs are mounted on the APB2 peripheral bus, where GPIOs are named as GPIOA, GPIOB, GPIOC, etc. Each GPIO peripheral has 16 pins, numbered from 0 to 15. Each GPIO module mainly includes registers and drivers. The register is a special type of memory that the core can read and write through the APB2 bus, thus completing the functions of outputting levels and reading levels. Each bit of this register corresponds to a pin, where writing 1 to the output register will output a high level on the corresponding pin, and writing 0 will output a low level. Reading 1 from the input register indicates that the corresponding port is currently at a high level, while reading 0 indicates a low level. Since STM32 is a 32-bit microcontroller, all internal registers are 32 bits, but the ports are only 16 bits, so this register only has the lower 16 bits corresponding to the ports, and the upper 16 bits are unused. This driver is used to increase the driving capability of the signal; the register is only responsible for storing data. If operations like lighting up are to be performed, a driver is still needed to increase the driving capability. This is the overall basic structure of GPIO.

image-20220821193133744

3.3 GPIO Bit Structure#

The specific circuit structure of each bit in GPIO is shown in the following diagram from the STM32 reference manual. The left three are registers, the middle part is the driver, and the right side is a pin of a certain IO port. The overall structure can be divided into two parts: the upper part is the input part, and the lower part is the output part.

3.3.1 Input Part#

Two protection diodes are connected at the pin to limit the input voltage. The upper diode connects to VDD-3.3V, and the lower connects to VSS-0V. If the input voltage exceeds 3.3V, the upper diode will conduct, and the current generated by the input voltage will flow directly into VDD instead of into the internal circuit, thus avoiding damage to the internal circuits from excessive voltage. If the input voltage is lower than 0V, this voltage is relative to VSS, so negative voltage is possible. At this time, the lower diode will conduct, and the current will flow directly from VSS, not drawing current from the internal circuit, thus protecting the internal circuit as well. If the input voltage is between 0~3.3V, both diodes will not conduct, and the diodes will have no effect on the circuit; this is the purpose of the protection diodes. The current passes through the pull-up and pull-down resistors, with the pull-up resistor connected to VDD and the pull-down resistor connected to VSS. This switch can be configured through the program. If the upper is conducting and the lower is disconnected, it is a pull-up input mode; if the lower is conducting and the upper is disconnected, it is a pull-down input mode; if both are disconnected, it is a floating input mode. Pull-up and pull-down are used to provide a default input level. For a digital port, the input is either high or low. If nothing is connected to the input, it will be in a floating state, and the input level of the pin is easily affected by external interference. To avoid uncertain input data caused by floating pins, we need to add pull-up or pull-down resistors here. If a pull-up resistor is connected, when the pin is floating, the pull-up resistor will ensure the pin is at a high level, so pull-up input can also be called a default high-level input mode; the same applies to pull-down, which defaults to a low-level input mode. The resistance values of pull-up and pull-down resistors are relatively large, representing weak pull-up and weak pull-down, aiming to minimize the impact on normal input operations. The TTL Schmitt trigger here should be a Schmitt trigger, which shapes the input voltage. Its execution logic is that when the input voltage exceeds a certain threshold, the output will instantly rise to a high level, and when the input voltage falls below a certain threshold, the output will instantly drop to a low level. For the Schmitt trigger, only exceeding the upper limit or falling below the lower limit will cause the output to change. The waveform shaped by the Schmitt trigger can be directly written into the data register, and we can read the data corresponding to a certain bit from the input data register to know the input level of the port. The analog input is connected to the ADC because the ADC needs to receive analog signals, so this line needs to connect to the front of the Schmitt trigger. The other is a multiplexed function input, which connects to other peripherals that need to read port data, such as the input pin of a serial port, etc. This line receives digital signals, so it comes after the Schmitt trigger.

3.3.2 Output Part#

The digital part is controlled by the output data register or on-chip peripherals, connected to the output control part through a data selector. If controlled through the output data register, it is a standard IO port output; writing to a certain bit of this data register can operate on the corresponding port. There is also a bit set/clear register on the left, used to operate a certain bit of the output data register without affecting other bits. This output data register controls 16 ports simultaneously, and this register can only be read and written as a whole. If you want to control a certain port individually without affecting other ports, some special operations are required. The first method is to read this register first, then use bitwise AND &= and bitwise OR |= to change a certain bit, and finally write the modified data back. This method is relatively cumbersome and inefficient, making it unsuitable for IO port operations. The second method is to set this bit set/clear register. If we want to set a certain bit to 1, we write 1 to the corresponding bit of the bit set register and write 0 to the bits that do not need to be operated. This way, the internal circuit will automatically set the corresponding bit of the output data register to 1, while keeping the other bits unchanged. This ensures that only one bit is operated without affecting the others, and this is a one-step operation. If you want to clear a certain bit, just write 1 to the corresponding bit of the bit clear register, and the internal circuit will clear that bit. Additionally, there is a third operation method, which is to read and write the bit band area in STM32. The function of this bit band is similar to the bit addressing function of the 51 microcontroller. In STM32, a dedicated address area is allocated, which maps all bits of RAM and peripheral registers. Reading and writing data in this address is equivalent to reading and writing a certain bit of the mapped position. This is the operation method of bit banding, which we will not use in this course; we mainly use library functions to operate, and the library functions use the method of reading and writing the bit set/clear register. After output control, it connects to two MOSFETs, with the upper being P-MOS and the lower being N-MOS. This MOSFET acts as an electronic switch, and our signal controls the switch's conduction and closure, which is responsible for connecting the IO port to VDD or VSS. Here, you can choose between push-pull, open-drain, or off three output modes. In push-pull output, both P-MOS and N-MOS are effective. When the data register is 1, the upper tube conducts, and the lower tube disconnects, directly connecting the output to VDD, which means outputting a high level; when the data register is 0, the upper tube disconnects, and the lower tube conducts, directly connecting the output to VSS, which means outputting a low level. In this mode, both high and low levels have strong driving capabilities, so the push-pull output mode can also be called strong push output mode. In push-pull output mode, STM32 has absolute control over the IO port, and both high and low levels are determined by STM32. In open-drain output mode, P-MOS is ineffective, and only N-MOS is working. In this mode, only the low level has driving capability, while the high level has no driving capability. Open-drain mode can be used as a driving method for communication protocols, such as the I2C communication pins, which use open-drain mode. In multi-device communication, this mode can avoid mutual interference among devices. Additionally, open-drain mode can also be used to output 5V level signals. When an external pull-up to 5V power supply is connected to the IO port, when outputting a low level, the internal N-MOS directly connects to VSS, and when outputting a high level, it is pulled high to 5V by the external pull-up resistor. This allows for the output of 5V level signals, compatible with some 5V level devices. This is the main use of open-drain output. The remaining state is off, which occurs when the pin is configured as input mode; both MOSFETs are ineffective, meaning output is off, and the port's level is controlled by external signals. This is the complete introduction to the GPIO bit structure.

image-20220821193240193

3.4 Eight Working Modes of GPIO#

By configuring the GPIO port configuration register, the port can be configured into the following 8 modes:

The circuit structures of floating input, pull-up input, and pull-down input are basically the same, with the difference being the connection of the pull-up and pull-down resistors. They all belong to digital input ports and can read the high and low levels of the port. When the pin is floating, pull-up input defaults to high level, pull-down input defaults to low level, while the level of floating input is uncertain. Therefore, when using floating input, the port must be connected to a continuous driving source, and a floating state cannot occur.

The characteristic of analog input is that GPIO is invalid, and the pin is directly connected to the internal ADC, which is a dedicated configuration for the ADC.

Open-drain output and push-pull output have similar circuit structures, both being digital output ports used to output high and low levels. The difference is that the high level of open-drain output presents a high-impedance state with no driving capability, while both high and low levels of push-pull output have driving capability.

Multiplexed open-drain output and multiplexed push-pull output are similar to ordinary open-drain and push-pull outputs, except that the output levels are controlled by on-chip peripherals.

Among these 8 modes of GPIO, only the analog input mode disables the digital input function; in the other 7 modes, the input is valid.

Mode NameNatureFeatures
Floating InputDigital InputCan read pin level; if the pin is floating, the level is uncertain
Pull-Up InputDigital InputCan read pin level; internally connected to pull-up resistor; defaults to high level when floating
Pull-Down InputDigital InputCan read pin level; internally connected to pull-down resistor; defaults to low level when floating
Analog InputAnalog InputGPIO is invalid; pin is directly connected to internal ADC
Open-Drain OutputDigital OutputCan output pin level; high level is high-impedance state; low level connects to VSS
Push-Pull OutputDigital OutputCan output pin level; high level connects to VDD; low level connects to VSS
Multiplexed Open-Drain OutputDigital OutputControlled by on-chip peripherals; high level is high-impedance state; low level connects to VSS
Multiplexed Push-Pull OutputDigital OutputControlled by on-chip peripherals; high level connects to VDD; low level connects to VSS

3.5 GPIO Input Floating/Pull-Up/Pull-Down Configuration#

In input mode, the output driver is off, and the port can only input but not output. The above two resistors can be selected to work as pull-up, pull-down, or not work, corresponding to pull-up input, pull-down input, and floating input. The input is shaped by the Schmitt trigger and then connected to the input data register. The input protection on the right is labeled VDD or VDD_FT, which distinguishes between 3.3V ports and 5V ports. For pins that tolerate 5V, the upper protection diode needs to be processed; otherwise, if it is directly connected to VDD3.3V, connecting an external 5V voltage will cause the upper diode to turn on and generate a large current.

image-20220821193727313

3.6 High-Impedance Analog Input Configuration of GPIO#

The output of the analog input is also off, and the input Schmitt trigger is also in a closed and ineffective state. Most of the GPIOs are useless, leaving only the direct connection from the pin to the on-chip peripherals, which is the ADC. Therefore, when we use the ADC, we simply configure the pin as an analog input; otherwise, analog input is generally not used.

image-20220821193914682

3.7 Open-Drain/Push-Pull Output Configuration of GPIO#

Output is controlled by the output data register. If P-MOS is ineffective, it is open-drain output; if both P-MOS and N-MOS are effective, it is push-pull output. Additionally, in output mode, input mode is also valid. A port can only have one output but can have multiple inputs. When configured as output mode, it can also input at the same time.

image-20220821193955149

3.8 Multiplexed Open-Drain/Push-Pull Output#

The output control on the left is disconnected, and the control of the pin is transferred to the on-chip peripherals, which control it. In the input part, the on-chip peripherals can also read the pin level, while ordinary input is also valid, receiving the level signal at the same time.

image-20220829075654841

3.9 GPIO Control of LED and Active Buzzer#

image-20220829084106943

USE STD PERIPH DRIVER

3.9.1 LED Blinking#

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

int main(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); // Enable GPIO clock for port C
	GPIO_InitTypeDef GPIO_InitStructure; // Define GPIO structure variable
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // General push-pull output
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; // PC13 pin
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 50MHz speed
	GPIO_Init(GPIOC, &GPIO_InitStructure); // Initialize GPIO configuration
    // Output or output SetBits sets to high level ResetBits sets to low level
//	GPIO_SetBits(GPIOC, GPIO_Pin_13);
	GPIO_ResetBits(GPIOC, GPIO_Pin_13);
	while (1)
	{
        GPIO_SetBits(GPIOC, GPIO_Pin_13); // SetBits sets to high level
        Delay_ms(500);
		GPIO_ResetBits(GPIOC, GPIO_Pin_13); // ResetBits sets to low level
        Delay_ms(500);
        
		GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET); // Low level
		Delay_ms(500);
		GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET); // High level
		Delay_ms(500);
        
        GPIO_WriteBit(GPIOC, GPIO_Pin_13, {BitAction}0); // Low level
		Delay_ms(500);
		GPIO_WriteBit(GPIOC, GPIO_Pin_13, {BitAction}1); // High level
		Delay_ms(500);
	}
}

3.9.2 LED Running Light#

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

/************************************************************************************************************************
* GPIO (General Purpose Input Output) general purpose input output ports
* Can be configured into 8 input/output modes
* Pin level: 0V~3.3V, some pins can tolerate 5V FT
* In output mode, it can control the port to output high or low levels, used to drive LEDs, control buzzers, simulate communication protocol output timing, etc.
* In input mode, it can read the high or low level or voltage of the port, used for reading key inputs, external module level signal inputs, ADC voltage collection, simulating communication protocol receiving data, etc.
* The TTL Schmitt trigger in the GPIO port image should be a Schmitt trigger.
* The Schmitt trigger only changes when above the upper limit or below the lower limit, effectively debouncing.
* Push-pull output, open-drain output, and off are three states.
* In push-pull output, both P-MOS and N-MOS are effective. In this mode, both high and low levels have strong driving capabilities, so push-pull output is also called strong push output mode.
* In push-pull output mode, STM32 has absolute control over the IO port; both high and low levels are determined by STM32.
* In open-drain output mode, P-MOS output is ineffective, and only N-MOS is working. In this mode, only the low level has driving capability; the high level has no driving capability.
* Open-drain mode can be used as a driving method for communication protocols, such as I2C communication pins, which use open-drain mode. In multi-device communication, this mode can avoid mutual interference among devices.
* Additionally, open-drain mode can also be used to output 5V level signals.
* Off occurs when the pin is configured as input mode; both P-MOS and N-MOS are ineffective, output is off, and the port's level signal is controlled by external signals.
************************************************************************************************************************/

/************************************************************************************************************************
* | **Mode Name** | **Nature** | **Features** |
* | ------------ | -------- | -------------------------------------------------- |
* | Floating Input | Digital Input | Can read pin level; if the pin is floating, the level is uncertain |
* | Pull-Up Input | Digital Input | Can read pin level; internally connected to pull-up resistor; defaults to high level when floating |
* | Pull-Down Input | Digital Input | Can read pin level; internally connected to pull-down resistor; defaults to low level when floating |
* | Analog Input | Analog Input | GPIO is invalid; pin is directly connected to internal ADC |
* | Open-Drain Output | Digital Output | Can output pin level; high level is high-impedance state; low level connects to VSS |
* | Push-Pull Output | Digital Output | Can output pin level; high level connects to VDD; low level connects to VSS |
* | Multiplexed Open-Drain Output | Digital Output | Controlled by on-chip peripherals; high level is high-impedance state; low level connects to VSS |
* | Multiplexed Push-Pull Output | Digital Output | Controlled by on-chip peripherals; high level connects to VDD; low level connects to VSS |
* Floating input, pull-up input, and pull-down input have similar circuit structures; the difference is in the connection of pull-up and pull-down resistors.
* Open-drain output and push-pull output also have similar circuit structures; the difference is that the high level of open-drain output presents a high-impedance state with no driving capability.
* Multiplexed open-drain output and multiplexed push-pull output are similar to ordinary outputs, except that the output levels are controlled by on-chip peripherals.
* Only analog input disables the digital input function; in other modes, digital input is valid.
************************************************************************************************************************/ 

int main(void)
{
	/***********************************************************************************
		GPIO Output
	***********************************************************************************/
	uint16_t i = 0; // Define loop variable
	// Enable corresponding clock
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // Enable clock for port A
	// Define a structure
	GPIO_InitTypeDef GPIO_InitStructure;
	// Configure port mode
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // General push-pull output
	/**********************************************************
	GPIO 8 Working Modes
	GPIO_Mode_AIN Analog Input
	GPIO_Mode_IN_FLOATING Floating Input
	GPIO_Mode_IPD Pull-Down Input
	GPIO_Mode_IPU Pull-Up Input
	GPIO_Mode_Out_OD Open-Drain Output
	GPIO_Mode_Out_PP Push-Pull Output
	GPIO_Mode_AF_OD Multiplexed Open-Drain Output
	GPIO_Mode_AF_PP Multiplexed Push-Pull Output
	**********************************************************/
	// GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // Pin A4
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; // All pins of port A
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 50MHz speed
	// Port initialization
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	// Set port high and low levels
	/********************************************************************
	void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); // Set pin to high level
	void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); // Set pin to low level
	void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal); // BitAction BitVal value is Bit_RESET and Bit_SET
	void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal); // PortVal: value to write to port output data register
	*********************************************************************/
	// GPIO_SetBits(GPIOC, GPIO_Pin_13); // High level
	// GPIO_ResetBits(GPIOC, GPIO_Pin_13); // Low level
	// GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET); // Low level
	// GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET); // High level
	// GPIO_Write(GPIOC, 0x0001); // 0000 0000 0000 0001 corresponds to PC0~PC15, a total of 16 pins
	while (1)
	{
		/*
		// LED Blinking
		GPIO_WriteBit(GPIOA, GPIO_Pin_4, Bit_RESET); // Low level
		Delay_ms(500);
		GPIO_WriteBit(GPIOA, GPIO_Pin_4, Bit_SET); // High level
		Delay_ms(500);
		*/
		// Running Light
		for (i = 0; i < 16; i++)
		{
			GPIO_Write(GPIOA, ~0x0001); // 0000 0000 0000 0001, bitwise NOT, low level lights up
			Delay_ms(500);
			GPIO_Write(GPIOA, ~0x0002); // 0000 0000 0000 0010
			Delay_ms(500);
			GPIO_Write(GPIOA, ~0x0004); // 0000 0000 0000 0100
			Delay_ms(500);
			GPIO_Write(GPIOA, ~0x0008); // 0000 0000 0000 1000
			Delay_ms(500);
			GPIO_Write(GPIOA, ~0x0010); // 0000 0000 0001 0000
			Delay_ms(500);
			GPIO_Write(GPIOA, ~0x0020); // 0000 0000 0010 0000
			Delay_ms(500);
			GPIO_Write(GPIOA, ~0x0040); // 0000 0000 0100 0000
			Delay_ms(500);
			GPIO_Write(GPIOA, ~0x0080); // 0000 0000 1000 0000
			Delay_ms(500);
			// GPIO_Write(GPIOA, 0x0001); // High level lights up
			// Delay_ms(500);
		}
	}
}

3.9.3 Buzzer#

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

int main(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // General push-pull output
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; // PB12 pin
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 50MHz speed
	GPIO_Init(GPIOB, &GPIO_InitStructure); // Initialize GPIO configuration

	while (1)
	{
        GPIO_SetBits(GPIOB, GPIO_Pin_12); // SetBits sets to high level
        Delay_ms(500);
		GPIO_ResetBits(GPIOB, GPIO_Pin_12); // ResetBits sets to low level
        Delay_ms(500);
	}
}

3.10 GPIO Input#

Key Debouncing

image-20220829223028287

3.10.1 Key Control LED#

Shortcut key Ctrl + ALT + Space to display code hints

main.c#
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"

/************************************************************************************************************************
* GPIO (General Purpose Input Output) general purpose input output ports
* Can be configured into 8 input/output modes
* Pin level: 0V~3.3V, some pins can tolerate 5V FT
* In output mode, it can control the port to output high or low levels, used to drive LEDs, control buzzers, simulate communication protocol output timing, etc.
* In input mode, it can read the high or low level or voltage of the port, used for reading key inputs, external module level signal inputs, ADC voltage collection, simulating communication protocol receiving data, etc.
* The TTL Schmitt trigger in the GPIO port image should be a Schmitt trigger.
* The Schmitt trigger only changes when above the upper limit or below the lower limit, effectively debouncing.
* Push-pull output, open-drain output, and off are three states.
* In push-pull output, both P-MOS and N-MOS are effective. In this mode, both high and low levels have strong driving capabilities, so push-pull output is also called strong push output mode.
* In push-pull output mode, STM32 has absolute control over the IO port; both high and low levels are determined by STM32.
* In open-drain output mode, P-MOS output is ineffective, and only N-MOS is working. In this mode, only the low level has driving capability; the high level has no driving capability.
* Open-drain mode can be used as a driving method for communication protocols, such as I2C communication pins, which use open-drain mode. In multi-device communication, this mode can avoid mutual interference among devices.
* Additionally, open-drain mode can also be used to output 5V level signals.
* Off occurs when the pin is configured as input mode; both P-MOS and N-MOS are ineffective, output is off, and the port's level signal is controlled by external signals.
************************************************************************************************************************/

/************************************************************************************************************************
* | **Mode Name** | **Nature** | **Features** |
* | ------------ | -------- | -------------------------------------------------- |
* | Floating Input | Digital Input | Can read pin level; if the pin is floating, the level is uncertain |
* | Pull-Up Input | Digital Input | Can read pin level; internally connected to pull-up resistor; defaults to high level when floating |
* | Pull-Down Input | Digital Input | Can read pin level; internally connected to pull-down resistor; defaults to low level when floating |
* | Analog Input | Analog Input | GPIO is invalid; pin is directly connected to internal ADC |
* | Open-Drain Output | Digital Output | Can output pin level; high level is high-impedance state; low level connects to VSS |
* | Push-Pull Output | Digital Output | Can output pin level; high level connects to VDD; low level connects to VSS |
* | Multiplexed Open-Drain Output | Digital Output | Controlled by on-chip peripherals; high level is high-impedance state; low level connects to VSS |
* | Multiplexed Push-Pull Output | Digital Output | Controlled by on-chip peripherals; high level connects to VDD; low level connects to VSS |
* Floating input, pull-up input, and pull-down input have similar circuit structures; the difference is in the connection of pull-up and pull-down resistors.
* Open-drain output and push-pull output also have similar circuit structures; the difference is that the high level of open-drain output presents a high-impedance state with no driving capability.
* Multiplexed open-drain output and multiplexed push-pull output are similar to ordinary outputs, except that the output levels are controlled by on-chip peripherals.
* Only analog input disables the digital input function; in other modes, digital input is valid.
************************************************************************************************************************/ 


/************************************************************************************************************************
* uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
* GPIO_ReadInputDataBit is used to read the input value of a certain port in the input register.
* uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
* GPIO_ReadInputData is used to read the entire input data register; the return value is uint16_t, which is a 16-bit data, with each bit representing a port value.
* uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
* GPIO_ReadOutputDataBit is used to read a certain bit of the output data register; in principle, it is not used to read the input data of the port; this function is generally used in output mode to check what is being output.
* uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
* GPIO_ReadOutputData is used to read the entire output register.
************************************************************************************************************************/

uint8_t Key_Num;

int main(void)
{
	/***********************************************************************************
		GPIO Input
	***********************************************************************************/
	LED_Init();
	Key_Init();
	
	while (1)
	{
		Key_Num = Key_GetNum();
		if (Key_Num == 1)
		{
			LED1_Turn();
		}
		if (Key_Num == 2)
		{
			LED2_Turn();
		}
	}
}
LED.c#
#include "stm32f10x.h"                  // Device header
#include "LED.h"

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_1 | GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_SetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2); // Set to high level
}

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

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

void LED1_Turn(void)
{
	if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) == 0)
	{
		GPIO_SetBits(GPIOA, GPIO_Pin_1);
	}
	else
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_1);
	}
}

void LED2_ON(void)
{
	GPIO_ResetBits(GPIOA, GPIO_Pin_2);
}

void LED2_OFF(void)
{
	GPIO_SetBits(GPIOA, GPIO_Pin_2);
}

void LED2_Turn(void)
{
	if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2) == 0)
	{
		GPIO_SetBits(GPIOA, GPIO_Pin_2);
	}
	else
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_2);
	}
}
key.c#
#include "Key.h"

void Key_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // Pull-up input
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}

uint8_t Key_GetNum(void)
{
	uint8_t KeyNum = 0;
	if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
	{
		Delay_ms(20);
		while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0);
		Delay_ms(20);
		KeyNum = 1;
	}
	
	if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0)
	{
		Delay_ms(20);
		while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0);
		Delay_ms(20);
		KeyNum = 2;
	}
	
	return KeyNum;
}

Summary of GPIO Usage Methods#

Initialize the clock
Define the structure
Assign values to the structure
The GPIO_Init function initializes the specified GPIO peripheral
Read and write the 8 main functions of GPIO

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);
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.