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) ports

Can be configured into 8 different input/output modes

Pin levels: 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 levels or voltage of the port, used for reading button inputs, external module level signal inputs, ADC voltage collection, simulating communication protocol data reception, etc.

3.2 Basic Structure of GPIO#

In STM32, all GPIOs are mounted on the APB2 peripheral bus, named 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 and reading levels. Each bit of this register corresponds to a pin, where writing 1 to the output register causes the corresponding pin to output a high level, and writing 0 outputs 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, the internal registers are all 32 bits, but the ports are only 16 bits, so this register only uses the lower 16 bits corresponding to the ports, while the upper 16 bits are unused. This driver is used to increase the driving capability of the signal; the register only stores data. If operations like lighting up an LED are needed, the driver is still required 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 section, and the lower part is the output section.

3.3.1 Input Section#

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 conducts, and the current generated by the input voltage will flow directly into VDD instead of the internal circuit, thus avoiding damage to the internal circuits from excessive voltage. If the input voltage is below 0V, this voltage is relative to VSS, so negative voltage can exist. In this case, the lower diode conducts, allowing current to flow directly from VSS, preventing current from being drawn from the internal circuit, which also protects the internal circuit. If the input voltage is between 0~3.3V, both diodes do not conduct, and the diodes have no effect on the circuit; this is the purpose of the protection diodes. The current passes through pull-up and pull-down resistors, with the pull-up resistor connected to VDD and the pull-down resistor to VSS. This switch can be configured through the program; if the upper diode conducts and the lower is off, it is in pull-up input mode; if the lower conducts and the upper is off, it is in pull-down input mode; if both are off, it is in 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, pull-up or pull-down resistors are needed. If a pull-up resistor is connected, when the pin is floating, the pull-up resistor ensures a high level at the pin, so pull-up input can also be called default high level input mode; similarly, pull-down is the default 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 Schottky 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; when the input voltage falls below a certain threshold, the output will instantly drop to a low level. For a Schmitt trigger, only outputs above the upper limit or below the lower limit will 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, as the ADC needs to receive analog signals, so this line needs to connect before the Schmitt trigger. The other is a multiplexed function input, which connects to other peripherals that need to read the port, such as the input pin of a serial port, etc. This line receives digital signals, so it connects after the Schmitt trigger.

3.3.2 Output Section#

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 control is chosen through the output data register, it is a normal IO port output; writing to a certain bit of this data register can operate 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 specific port without affecting others, some special operation methods are needed. 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 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 in 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 in the output data register to 1, while keeping the other bits unchanged. This ensures that only one bit is operated without affecting others, and it is a one-step operation. If you want to clear a certain bit, just write 1 to the corresponding bit in 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 at the mapped position; this is the operation method of the bit band. This method will not be used in this course; we mainly use library functions to operate, which utilize the method of reading and writing the bit set/clear register. After output control, it connects to two MOSFETs; the upper one is P-MOS, and the lower one is N-MOS. This MOSFET acts as an electronic switch, with our signal controlling the switch's conduction and closure, responsible for connecting the IO port to VDD or VSS. Here, three output modes can be selected: push-pull, open-drain, or off. 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 is off, directly connecting the output to VDD, which means outputting a high level; when the data register is 0, the upper tube is off, 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 capability, so push-pull output can also be called strong push output mode. In push-pull output mode, STM32 has absolute control over the IO port, determining both high and low levels. In open-drain output mode, P-MOS is ineffective, and only N-MOS is working. In this mode, only low levels have driving capability, while high levels do not. Open-drain mode can serve as a driving method for communication protocols, such as the I2C communication pins, which use open-drain mode to avoid interference between multiple devices during multi-device communication. Additionally, open-drain mode can also be used to output 5V level signals. When the pin is configured as input mode, both P-MOS and N-MOS are ineffective, meaning output is off, and the port's level signal 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:

Floating input, pull-up input, and pull-down input have similar circuit structures, differing only in the connection of 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 inactive, 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, but they are multiplexed outputs, with pin levels 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, input is valid.

Mode NameNatureFeatures
Floating InputDigital InputCan read pin levels; if the pin is floating, the level is uncertain
Pull-up InputDigital InputCan read pin levels; internally connected to pull-up resistor; defaults to high level when floating
Pull-down InputDigital InputCan read pin levels; internally connected to pull-down resistor; defaults to low level when floating
Analog InputAnalog InputGPIO is inactive; the pin is directly connected to the internal ADC
Open-drain OutputDigital OutputCan output pin levels; high level is high-impedance state; low level connects to VSS
Push-pull OutputDigital OutputCan output pin levels; 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 treated; otherwise, if it directly connects 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 an inactive state. Most of the GPIO is unused, leaving only the connection from the pin to the on-chip peripherals, which is the ADC. Therefore, when we use the ADC, we configure the pin as an analog input; otherwise, analog input is generally not used.

image-20220821193914682

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

Output is controlled by the output data register. If P-MOS is inactive, it is open-drain output; if both P-MOS and N-MOS are active, 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, internal input can also occur.

image-20220821193955149

3.8 Multiplexed Open-Drain/Push-Pull Output#

The output control on the left is generally off, and the control of the pin is transferred to the on-chip peripherals, which control it. In the input section, the on-chip peripherals can also read the pin levels, while normal input is also valid, receiving level signals simultaneously.

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) ports
* Can be configured into 8 different input/output modes
* Pin levels: 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 levels or voltage of the port, used for reading button inputs, external module level signal inputs, ADC voltage collection, simulating communication protocol data reception, etc.
* The TTL Schottky 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, providing good 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 capability, so push-pull output is also called strong push output mode.
* In push-pull output mode, STM32 has absolute control over the IO port, determining both high and low levels.
* In open-drain output mode, P-MOS output is ineffective, and only N-MOS is working; in this mode, only low levels have driving capability, while high levels do not.
* Open-drain mode can serve as a driving method for communication protocols, such as the I2C communication pins, which use open-drain mode to avoid interference between multiple devices during multi-device communication.
* Additionally, open-drain mode can also be used to output 5V level signals.
* When the pin is configured as input mode, both P-MOS and N-MOS are ineffective, meaning 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 levels; if the pin is floating, the level is uncertain           |
* | Pull-up Input | Digital Input | Can read pin levels; internally connected to pull-up resistor; defaults to high level when floating |
* | Pull-down Input | Digital Input | Can read pin levels; internally connected to pull-down resistor; defaults to low level when floating |
* | Analog Input | Analog Input | GPIO is inactive; the pin is directly connected to the internal ADC                      |
* | Open-drain Output | Digital Output | Can output pin levels; high level is high-impedance state; low level connects to VSS        |
* | Push-pull Output | Digital Output | Can output pin levels; 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, differing only in the connection of pull-up and pull-down resistors.
* Open-drain output and push-pull output have similar circuit structures, differing in 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, but 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 (analog in)
	GPIO_Mode_IN_FLOATING Floating input (in floating)
	GPIO_Mode_IPD Pull-down input (in pull down)
	GPIO_Mode_IPU Pull-up input (in pull up)
	GPIO_Mode_Out_OD Open-drain output (out open drain)
	GPIO_Mode_Out_PP Push-pull output (out push pull)
	GPIO_Mode_AF_OD Multiplexed open-drain output (alt open drain)
	GPIO_Mode_AF_PP Multiplexed push-pull output (alt push pull)
	**********************************************************/
	// 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 can be Bit_RESET or Bit_SET
	void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal); // PortVal: value to write to the 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 corresponding 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#

Button Debouncing

image-20220829223028287

3.10.1 Button 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) ports
* Can be configured into 8 different input/output modes
* Pin levels: 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 levels or voltage of the port, used for reading button inputs, external module level signal inputs, ADC voltage collection, simulating communication protocol data reception, etc.
* The TTL Schottky 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, providing good 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 capability, so push-pull output is also called strong push output mode.
* In push-pull output mode, STM32 has absolute control over the IO port, determining both high and low levels.
* In open-drain output mode, P-MOS output is ineffective, and only N-MOS is working; in this mode, only low levels have driving capability, while high levels do not.
* Open-drain mode can serve as a driving method for communication protocols, such as the I2C communication pins, which use open-drain mode to avoid interference between multiple devices during multi-device communication.
* Additionally, open-drain mode can also be used to output 5V level signals.
* When the pin is configured as input mode, both P-MOS and N-MOS are ineffective, meaning 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 levels; if the pin is floating, the level is uncertain           |
* | Pull-up Input | Digital Input | Can read pin levels; internally connected to pull-up resistor; defaults to high level when floating |
* | Pull-down Input | Digital Input | Can read pin levels; internally connected to pull-down resistor; defaults to low level when floating |
* | Analog Input | Analog Input | GPIO is inactive; the pin is directly connected to the internal ADC                      |
* | Open-drain Output | Digital Output | Can output pin levels; high level is high-impedance state; low level connects to VSS        |
* | Push-pull Output | Digital Output | Can output pin levels; 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, differing only in the connection of pull-up and pull-down resistors.
* Open-drain output and push-pull output have similar circuit structures, differing in 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, but 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, returning a uint16_t value, 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#

  1. Initialize the clock
  2. Define the structure
  3. Assign values to the structure
  4. Use the GPIO_Init function to initialize the specified GPIO peripheral
  5. 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.