Function analysis of GPIO used by STM32

Publisher:心满愿望Latest update time:2016-07-30 Source: eefocusKeywords:STM32 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
This article was written after I learned a little about STM32. It is the simplest program for programming STM32 using the firmware library, and it analyzes part of the firmware library function. If there are any errors, please correct them. I would be very grateful.

1. GPIO_Init function analysis 1

1. Parameter GPIO_TypeDef 1

2. Parameter GPIO_InitStruct 2

3. Detailed explanation of function code 4

4. Note 6

 

1. GPIO_Init function analysis

First, let's look at the prototype of the GPIO_Init function void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct). This function is implemented in the Stm32f10x_gpio.c file. If you want to use this function, include the Stm32f10x_gpio.h header file in front of the corresponding application.

1. Parameter GPIO_TypeDef

The first parameter of this function is GPIO_TypeDef, which is a structure type defined in Stm32f10x.h. The prototype of the definition is:

typedef struct

{

  __IO uint32_t CRL;

  __IO uint32_t CRH;

  __IO uint32_t IDR;

  __IO uint32_t ODR;

  __IO uint32_t BSRR;

  __IO uint32_t BRR;

  __IO uint32_t LCKR;

}GPIO_TypeDef;

There are 7 32 (8-byte) bit variables in this structure type, and the addresses of these variables in the storage space are adjacent. It is not difficult to see from the STM32 data sheet that each port corresponds to 16 pins, and 7 registers control the GPIO behavior, and the order of these 7 registers is also continuous. Each port has the same structure. The STM32 firmware library abstracts this structure into a type GPIO_TypeDef. Before operating the register, you must have a register mapping operation, otherwise you cannot access the specified register. Here we only need to map once instead of 7 times. Isn't it very convenient to do this? It also improves the readability of the code and makes the code standardized.

Since the first parameter of GPIO_Init is the pointer variable of GPIO_TypeDef, this pointer variable stores the first address of a certain port. The calling statement of a certain program is as follows GPIO_Init(GPIOD,&GPIO_InitStructure); //Initialize GPIOD

GPID is a macro defined in the firmware library. It will be expanded during compilation. The macro definitions related to the GPIOD port address mapping are listed as follows:

#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)

#define GPIOD_BASE (APB2PERIPH_BASE + 0x1400)

#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)

#define PERIPH_BASE ((uint32_t)0x40000000) 

Are you familiar with the number 0x4000 0000? It is the first address of the peripheral. There are two STM32s inside the STM32 chip, one is called APB1 and the other is called APB2. Each APB bridge manages many peripherals. STM32F10x puts the peripheral register access addresses of these two APBs in different storage spaces. 0x10000 is the offset of the first address of the storage space of the APB2 peripheral relative to the entire peripheral. And 0x1400 is the offset of the first address of the GPIOD port peripheral relative to the first address of the storage space of the APB2 peripheral. In this way, the base address of the GPIOD peripheral is found! And ((GPIO_TypeDef *) GPIOD_BASE) can simultaneously realize the mapping of all 7 registers that control the GPIOD port. If you want to access a certain register, you only need to use a pointer to the GPIO_TypeDef variable.

2. Parameter GPIO_InitStruct

The second parameter is GPIO_InitTypeDef* GPIO_InitStruct. It is an address pointing to GPIO _InitTypeDef. The first parameter only finds the target register to be configured, and the second parameter is the data parameter for how to configure the corresponding port. These parameters are stored at the first address pointing to the GPIO_InitTypeDef variable. First, a piece of code from which this parameter comes

GPIO_InitTypeDef GPIO_InitStructure; 

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;

GPIO_InitTypeDef is a structure variable, which is defined in the Stm32f10x_gpio.h header file. The prototype is as follows:

typedef struct

{

  uint16_t GPIO_Pin;

  GPIOSpeed_TypeDef GPIO_Speed;  

  GPIOMode_TypeDef GPIO_Mode;  

 }GPIO_InitTypeDef;

 

The first variable of GPIO_InitTypeDef is GPIO_Pin, which is a 16-bit unsigned number. This number has only 16 bits, and each bit represents a pin. To configure a pin of a port, you only need to set the corresponding bit to 1. The following pin number definitions are available in the STM32 firmware library:

#define GPIO_Pin_0 ((uint16_t)0x0001) /*!< Pin 0 selected */

#define GPIO_Pin_1 ((uint16_t)0x0002) /*!< Pin 1 selected */

#define GPIO_Pin_2 ((uint16_t)0x0004) /*!< Pin 2 selected */

#define GPIO_Pin_3 ((uint16_t)0x0008) /*!< Pin 3 selected */

#define GPIO_Pin_4 ((uint16_t)0x0010) /*!< Pin 4 selected */

#define GPIO_Pin_5 ((uint16_t)0x0020) /*!< Pin 5 selected */

#define GPIO_Pin_6 ((uint16_t)0x0040) /*!< Pin 6 selected */

#define GPIO_Pin_7 ((uint16_t)0x0080) /*!< Pin 7 selected */

#define GPIO_Pin_8 ((uint16_t)0x0100) /*!< Pin 8 selected */

#define GPIO_Pin_9 ((uint16_t)0x0200) /*!< Pin 9 selected */

#define GPIO_Pin_10 ((uint16_t)0x0400) /*!< Pin 10 selected */

#define GPIO_Pin_11 ((uint16_t)0x0800) /*!< Pin 11 selected */

#define GPIO_Pin_12 ((uint16_t)0x1000) /*!< Pin 12 selected */

#define GPIO_Pin_13 ((uint16_t)0x2000) /*!< Pin 13 selected */

#define GPIO_Pin_14 ((uint16_t)0x4000) /*!< Pin 14 selected */

#define GPIO_Pin_15 ((uint16_t)0x8000) /*!< Pin 15 selected */

#define GPIO_Pin_All ((uint16_t)0xFFFF) /*!< All pins selected */

It is much more convenient to use these defined macros. To configure some pins, you only need to OR the corresponding pins. If you want to configure all the bits of a certain port, you only need to use a macro GPIO_Pin_All. Simple, right? Haha!

GPIOSpeed_TypeDef is an enumeration variable that is used to store the parameters of GPIO speed. Its definition is as follows:

typedef enum

  GPIO_Speed_10MHz = 1,

  GPIO_Speed_2MHz, 

  GPIO_Speed_50MHz

}GPIOSpeed_TypeDef;

From the definition, we can know that the variable of GPIOSpeed_TypeDef has three values, so there are three GPIO speeds.

The value of the enumeration variable

Corresponding speed

1

10MHZ

2

2MHZ

3

50MHZ

 

GPIOMode_TypeDef is also an enumeration variable, which is used to store the GPIO working mode. Its definition is as follows:

typedef enum

{GPIO_Mode_AIN = 0x0,

  GPIO_Mode_IN_FLOATING = 0x04,

  GPIO_Mode_IPD = 0x28,

  GPIO_Mode_IPU = 0x48,

  GPIO_Mode_Out_OD = 0x14,

  GPIO_Mode_Out_PP = 0x10,

  GPIO_Mode_AF_OD = 0x1C,

  GPIO_Mode_AF_PP = 0x18

}GPIOMode_TypeDef;

The design of the possible values ​​of this enumeration variable has a certain significance. In the fourth bit, only the upper two bits are used. These two bits are used to store the mode control bit MODEx[1:0] of a certain pin, while the upper four bits are used to mark certain flags.

 

 

The value of the upper four bits

significance

0

Input Mode

1

Output Mode

2

Pull-down input

4

Pull-up input

 

3. Detailed explanation of function code

The above is the explanation of the parameters of the GPIO_Init function. Now we can go inside the GPIO_Init function and take a look.

First, list the function code, and put the explanation of the code in the comments, as follows:

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)

{

  uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;

  uint32_t tmpreg = 0x00, pinmask = 0x00;

  /* Check the parameters */

  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

  assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));

  assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));  

  

/*------------------------------- GPIO Mode Configuration ------------------ ------*/

  currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);

  if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00) //If it is output pull-up, the GPIO speed will be configured

  { 

    /* Check the parameters */

    assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));

    /* Output mode */

    currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;

  }

/*------------------------------- GPIO CRL Configuration ------------------ -------*/

  /* Configure the eight low port pins */

  if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)//If the eighth pin is configured, the pin will be configured if a bit of the value of GPIO_Pin is 1

  {

    tmpreg = GPIOx->CRL; //temporarily store the original value of the GPIO control register

    for (pinpos = 0x00; pinpos < 0x08; pinpos++) //Scan 8 times to determine which pin needs to be configured. If //configuration is required, configure it

    {

      pos = ((uint32_t)0x01) << pinpos; //Get the value of 1 corresponding to a pin to be viewed

      /* Get the port pins position */

      currentpin = (GPIO_InitStruct->GPIO_Pin) & pos; //The value of currentpin is 0 or pos

      if (currentpin == pos) //If it is pos, it means that this position needs to be configured

      {

        pos = pinpos << 2; //Multiply the value of pinpos by 4 to get the lowest bit number of a pin configuration bit: 0, 4, 8......28

        /* Clear the corresponding low control register bits *///Used to mask the configuration bits of a certain pin and make these 4 bits 0

        pinmask = ((uint32_t)0x0F) << pos;

        tmpreg &= ~pinmask;

        /* Write the mode configuration in the corresponding bits */

        tmpreg |= (currentmode << pos); //Because the numbers corresponding to the mode are stored in the fourth bit, it is necessary to shift left to the lowest bit of the configuration bit corresponding to a pin, and then store it in tmpreg

        /* Reset the corresponding ODR bit */

        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD) //If it is input pull-down, you need to turn on the corresponding switch

        {

          GPIOx->BRR = (((uint32_t)0x01) << pinpos);

        }

        else

        {

          /* Set the corresponding ODR bit */

          if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU) //If it is input pull-down, you need to turn on the corresponding switch

          {

            GPIOx->BSRR = (((uint32_t)0x01) << pinpos);

          }

        }

      }

    }

    GPIOx->CRL = tmpreg; // Assign values ​​to the lower 8 pin configuration registers

  }

/*------------------------------- GPIO CRH Configuration ------------------ -------*/

  /* Configure the eight high port pins */

  if (GPIO_InitStruct->GPIO_Pin > 0x00FF)

  {

    tmpreg = GPIOx->CRH;

    for (pinpos = 0x00; pinpos < 0x08; pinpos++)

    {

      pos = (((uint32_t)0x01) << (pinpos + 0x08));

      /* Get the port pins position */

      currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos);

      if (currentpin == pos)

      {

        pos = pinpos << 2;

        /* Clear the corresponding high control register bits */

        pinmask = ((uint32_t)0x0F) << pos;

        tmpreg &= ~pinmask;

        /* Write the mode configuration in the corresponding bits */

        tmpreg |= (currentmode << pos);

        /* Reset the corresponding ODR bit */

        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)

        {

          GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));

        }

        /* Set the corresponding ODR bit */

        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)

        {

          GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));

        }

      }

    }

    GPIOx->CRH = tmpreg;

  }

}

4. Notes

The assert_param function is used to check the parameters. The parameters are either logical 0 or 1. IS_GPIO_ALL_PERIPH is also a macro, which is defined as:

#define IS_GPIO_ALL_PERIPH(PERIPH) (((PERIPH) == GPIOA) || \

                                    ((PERIPH) == GPIOB) || \

                                    ((PERIPH) == GPIOC) || \

                                    ((PERIPH) == GPIOD) || \

                                    ((PERIPH) == GPIOE) || \

                                    ((PERIPH) == GPIOF) || \

                                    ((PERIPH) == GPIOG))

The macros used in other parameter detection functions are similar. You can refer to the corresponding macro definitions for details. They are not listed here one by one.

 

The configuration principle of the lower 8 bits is the same as that of the upper 8 bits, so only the configuration of the lower 8 pins is explained here.

Keywords:STM32 Reference address:Function analysis of GPIO used by STM32

Previous article:I2C communication of STM32
Next article:Analysis and understanding of stm32f10x.h file

Recommended ReadingLatest update time:2024-11-17 03:45

Read protection for STM8S/32
1. Steps for code writing and read protection: 1. Preparation: After the HEX file and JLINK driver (JLinkARM_V420 or above, secure chip may appear gray and unselectable in 4.08) are installed, you can open the application in Start--All Programs--SEGGER--J-Flash ARM First set the chip to be written and the writing me
[Microcontroller]
STM32 Series Chapter 20 - DAC
Features: 2 DAC converters: each converter corresponds to 1 output channel (corresponding to PA4 and PA5) 8-bit or 12-bit monotonic output In 12-bit mode, data is left-aligned or right-aligned Synchronous update function Noise waveform generation Triangle waveform generation Dual DAC channels convert simultaneo
[Microcontroller]
Porting FATFS for STM32 to read FAT12/16/32 file system on SD card
Transplanting fatfs file system to stm32, finally achieved a phased victory today. Only a few functions need to be provided:  DSTATUS disk_initialize (BYTE);  DSTATUS disk_status (BYTE);  DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);  DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE); // If a read-only file system i
[Microcontroller]
STM32_TIM outputs PWM waveform
Preface Today we will explain "STM32F103 TIM output PWM waveform". The software engineering provided supports a maximum output of 18MHz PWM waveform. The function interface has only two parameters: frequency Freq and duty cycle Dutycycle. The timer is very powerful. The PWM explained today belongs to the output compar
[Microcontroller]
STM32_TIM outputs PWM waveform
Experts show you how to analyze STM32 BSRR BRR ODR registers
 1. Usage You will often see macro definition statements similar to the following, which are used to output high or low levels to the initialized IO ports. #define SET_BL_HIGH() GPIOA- BSRR=GPIO_Pin_0 #define SET_BL_LOW() GPIOA- BRR=GPIO_Pin_012 Its function is similar to the following two library functions: v
[Microcontroller]
The relationship between EXTI (external interrupt) and NVIC (nested vector interrupt) in STM32
NVIC is part of the Cortex-M3 core. Information about it is not in the "STM32 Technical Reference Manual". You should refer to ARM's "Cortex-M3 Technical Reference Manual" The vector interrupts of Cortex-M3 are uniformly managed by NVIC. EXTI is the external interrupt control extended by ST on its STM32 products. It
[Microcontroller]
STM32 external interrupt operation
The core supports 256 interrupts, including 16 core interrupts and 240 external interrupts, and has 256 levels of programmable interrupt settings. However, STM32 does not use all of the CM3 core, but only uses part of it. STM32 has 76 interrupts, including 16 core interrupts and 60 maskable interrupts, with 16 levels o
[Microcontroller]
Design of analog voltage acquisition card for STM32 microcontroller
Require: Collect 16 analog voltage values ​​(0~5V) plan: Interface: Connect to the computer USB port. Use USB to serial port chip to convert into serial port, which is convenient for developing board host software. Main MCU: STM32 F103RBT6 Hardware principle: CH340+STM32+LM324 CH340: USB to serial port chip It is conv
[Power Management]
Design of analog voltage acquisition card for STM32 microcontroller
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号