你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32:GPIO口的使用

[复制链接]
STMCU小助手 发布时间:2022-2-6 19:49
前言
  "GPIO的使用1"中主要从内核代码开始,从寄存器的地址映射开始,对GPIO的封装和操作执行逻辑详细分析了一下;
  内核的函数接口标准是都是一样的CMSIS,了解了GPIO外设的原理,也就了解了其他外设是如何封装的;
  GPIO使用时先确定是否为外设复用;目的是确定输入输出数据是给外设处理,还是存放在GPIO寄存器里就完了;
  然后确定IO的输入输出模式;目的是通过软件配置,选择端口在芯片内部的电路连接方式;
  GPIO上电默认为浮空输入模式,禁止了上下拉电阻;上下拉电阻默认30-50kΩ;保护二极管防止电流反向击穿;

1371863-20201107110810180-995672057.png

  0.1 输入模式
    上拉输入:使能上拉电阻的连接,断开下拉电阻的连接;
    下拉输入:断开上拉电阻的连接,使能下拉电阻的连接;
    模拟输入:将IO引脚连接至内部ADC;  
  0.2 输出模式
    推挽输出:将P-MOS管和N-MOS管以推挽方式连接;通过两个MOS管的导通与截止来输出高低电平;配置上下拉电阻不使能;
            特点是既可以消耗负载的拉电流,也可以向负载输出拉电流,开关时间快;
    开漏输出:P-MOS管始终截止,通过N-MOS管结合上下拉电阻,控制输出高低电平;配置上下拉电阻同时使能;
            特点是输出高电平的驱动能力完全由上拉电阻决定,输出低电平的驱动能力十分稳定;
  0.3 可以将多个开漏输出并连至同一个上拉电阻,形成"线与"逻辑;当其中一个开漏输出输出低电平时,相当于并联回路被导线短路;其他输出也被接到地了;
  0.4 TSM32H7IO口总的电流最大值为140mA,单个IO口的电流最大值为20mA;具体硬件参数见数据手册;
  0.5 TTL和CMOS电平标准手册可以查看安富莱论坛:http://www.armbbs.cn/forum.php?mod=viewthread&tid=87676
1 GPIO port
  STM32一共有7组GPIO port,分别是GPIOA[15:0]~GPIOG[15:0],每组GPIO port 有16个 pin;每组GPIO port都有一组寄存器;
  GPIO寄存器的控制单位是GPIO port,而不是pin;所以寄存器的最小处理单位是一个16位的字长(0xFFFF);
  至于寄存器的配置我们之后小节在解析,首先来了解一下标准库是如何将GPIO映射到地址上的;
  
1371863-20200516110102171-1093576858.png

  1. /*stm32f10x.h 1408-1414行声明如下*/
  2. #define GPIOA               ((GPIO_TypeDef *) GPIOA_BASE)
  3. #define GPIOB               ((GPIO_TypeDef *) GPIOB_BASE)
  4. #define GPIOC               ((GPIO_TypeDef *) GPIOC_BASE)
  5. #define GPIOD               ((GPIO_TypeDef *) GPIOD_BASE)
  6. #define GPIOE               ((GPIO_TypeDef *) GPIOE_BASE)
  7. #define GPIOF               ((GPIO_TypeDef *) GPIOF_BASE)
  8. #define GPIOG               ((GPIO_TypeDef *) GPIOG_BASE)

  9. /* stm32f10x.h  1001-1010行;
  10. *把结构体的首地址映射到GPIO的首寄存器地址,就可以通过该结构体对硬件寄存器操作;
  11. *结构体的地址通过结构体指针来赋值对应上*/
  12. #define __IO  volatile /*core_cm3.h  NO.116*/
  13. typedef struct
  14. {
  15.   __IO uint32_t CRL;
  16.   __IO uint32_t CRH;
  17.   __IO uint32_t IDR;
  18.   __IO uint32_t ODR;
  19.   __IO uint32_t BSRR;
  20.   __IO uint32_t BRR;
  21.   __IO uint32_t LCKR;
  22. } GPIO_TypeDef;

  23. /*stm32f10x.h 1315-1321;*/
  24. #define GPIOA_BASE            (APB2PERIPH_BASE + 0x0800)
  25. #define GPIOB_BASE            (APB2PERIPH_BASE + 0x0C00)
  26. #define GPIOC_BASE            (APB2PERIPH_BASE + 0x1000)
  27. #define GPIOD_BASE            (APB2PERIPH_BASE + 0x1400)
  28. #define GPIOE_BASE            (APB2PERIPH_BASE + 0x1800)
  29. #define GPIOF_BASE            (APB2PERIPH_BASE + 0x1C00)
  30. #define GPIOG_BASE            (APB2PERIPH_BASE + 0x2000)

  31. /*stm32f10x.h 1282-1283; GPIO都属于APB2总线,使用的时候要使能APB2总线的时钟源;*/
  32. #define APB1PERIPH_BASE       PERIPH_BASE
  33. #define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)

  34. /*stm32f10x.h 1274*/
  35. #define PERIPH_BASE           ((uint32_t)0x40000000)
复制代码

2 GPIO 寄存器
  GPIO涉及的寄存器较多,复用功能和重映射功能都需要配置专门的AFIO寄存器,但是本节暂时没有涉及;
  本节主要介绍了通用GPIO口涉及到的7个寄存器,具体寄存器的说明和使用如下;
  2.1 CRL端口配置低寄存器,CRH端口配置高寄存器 control register low,control register high;
    CRL和CRH都是32位寄存器,如下图所示,一起用来控制该组GPIO port的16个引脚配置;

1371863-20200515102909983-458893530.png
   
    2.1.1 CRL和CRH寄存器复位值为0x4444_4444;CRL偏移地址:0x00,CRH偏移地址:0x04;配置信息封装如下;
  1. //定义了CRH和CRL寄存器需要的参数;以下声明在stm32f10x_gpio.h的前200行;
  2. typedef struct
  3. {
  4.   uint16_t GPIO_Pin;                /*用16位bit的每一位分别表示一个引脚*/            
  5.   GPIOSpeed_TypeDef GPIO_Speed;     /*用2位bit来表示输出模式的最大速度*/
  6.   GPIOMode_TypeDef GPIO_Mode;       /*CNF MODE,具体见结构体*/
  7. }GPIO_InitTypeDef;

  8. #define GPIO_Pin_0                 ((uint16_t)0x0001)  /*0000 0000 0000 0001b*/
  9. #define GPIO_Pin_1                 ((uint16_t)0x0002)  /*0000 0000 0000 0010b*/
  10. #define GPIO_Pin_2                 ((uint16_t)0x0004)  /*0000 0000 0000 0100b*/
  11. #define GPIO_Pin_3                 ((uint16_t)0x0008)  /*0000 0000 0000 1000b*/
  12. #define GPIO_Pin_4                 ((uint16_t)0x0010)  /*0000 0000 0001 0000b*/
  13. #define GPIO_Pin_5                 ((uint16_t)0x0020)  /*0000 0000 0010 0000b*/
  14. #define GPIO_Pin_6                 ((uint16_t)0x0040)  /*0000 0000 0100 0000b*/
  15. #define GPIO_Pin_7                 ((uint16_t)0x0080)  /*0000 0000 1000 0000b*/
  16. #define GPIO_Pin_8                 ((uint16_t)0x0100)  /*0000 0001 0000 0000b*/
  17. #define GPIO_Pin_9                 ((uint16_t)0x0200)  /*!< Pin 9 selected */
  18. #define GPIO_Pin_10                ((uint16_t)0x0400)  /*!< Pin 10 selected */
  19. #define GPIO_Pin_11                ((uint16_t)0x0800)  /*!< Pin 11 selected */
  20. #define GPIO_Pin_12                ((uint16_t)0x1000)  /*!< Pin 12 selected */
  21. #define GPIO_Pin_13                ((uint16_t)0x2000)  /*!< Pin 13 selected */
  22. #define GPIO_Pin_14                ((uint16_t)0x4000)  /*!< Pin 14 selected */
  23. #define GPIO_Pin_15                ((uint16_t)0x8000)  /*!< Pin 15 selected */
  24. #define GPIO_Pin_All               ((uint16_t)0xFFFF)  /*!< All pins selected */
  25. #define IS_GPIO_PIN(PIN) ((((PIN) & (uint16_t)0x00) == 0x00) && ((PIN) != (uint16_t)0x00))

  26. typedef enum
  27. {
  28.   GPIO_Speed_10MHz = 1,     /*output MODE[1:0]*/
  29.   GPIO_Speed_2MHz,          /*output MODE[1:0]*/
  30.   GPIO_Speed_50MHz          /*output MODE[1:0]*/
  31. }GPIOSpeed_TypeDef;
  32. #define IS_GPIO_SPEED(SPEED) (((SPEED) == GPIO_Speed_10MHz) || ((SPEED) == GPIO_Speed_2MHz) || \
  33.                               ((SPEED) == GPIO_Speed_50MHz))
  34.                               
  35. typedef enum
  36. { GPIO_Mode_AIN = 0x0,                /*0000 0000b [4]0 input [3:0]CNF+MODE*/
  37.   GPIO_Mode_IN_FLOATING = 0x04,       /*0000 0100b [4]0 input [3:0]CNF+MODE*/
  38.   GPIO_Mode_IPD = 0x28,               /*0010 1000b [4]0 input [5]下拉,[3:0]CNF+MODE*/
  39.   GPIO_Mode_IPU = 0x48,               /*0100 1000b [4]0 input [6]上拉,[3:0]CNF+MODE*/
  40.   GPIO_Mode_Out_OD = 0x14,            /*0001 0100b [4]1 output,[3:2]CNF*/
  41.   GPIO_Mode_Out_PP = 0x10,            /*0001 0000b [4]1 output,[3:2]CNF*/
  42.   GPIO_Mode_AF_OD = 0x1C,             /*0001 1100b [4]1 output,[3:2]CNF*/
  43.   GPIO_Mode_AF_PP = 0x18              /*0001 1000b [4]1 output,[3:2]CNF*/
  44. }GPIOMode_TypeDef;
  45. #define IS_GPIO_MODE(MODE) (((MODE) == GPIO_Mode_AIN) || ((MODE) == GPIO_Mode_IN_FLOATING) || \
  46.                             ((MODE) == GPIO_Mode_IPD) || ((MODE) == GPIO_Mode_IPU) || \
  47.                             ((MODE) == GPIO_Mode_Out_OD) || ((MODE) == GPIO_Mode_Out_PP) || \
  48.                             ((MODE) == GPIO_Mode_AF_OD) || ((MODE) == GPIO_Mode_AF_PP))
  49. #define IS_GET_GPIO_PIN(PIN) (((PIN) == GPIO_Pin_0) || ((PIN) == GPIO_Pin_1) ||((PIN) == GPIO_Pin_2) || \
  50.                               ((PIN) == GPIO_Pin_3) || ((PIN) == GPIO_Pin_4) || ((PIN) == GPIO_Pin_5) || \
  51.                               ((PIN) == GPIO_Pin_6) || ((PIN) == GPIO_Pin_7) || ((PIN) == GPIO_Pin_8) || \
  52.                               ((PIN) == GPIO_Pin_9) || ((PIN) == GPIO_Pin_10) || ((PIN) == GPIO_Pin_11) || \
  53.                               ((PIN) == GPIO_Pin_12) ||((PIN) == GPIO_Pin_13) || ((PIN) == GPIO_Pin_14) || \
  54.                               ((PIN) == GPIO_Pin_15))

  55. typedef enum
  56. { Bit_RESET = 0,
  57.   Bit_SET
  58. }BitAction;
复制代码

    2.1.2 配置CRL和CRH的初始化代码如下;
  1. /*以下代码位于stm32f10x_gpio.c中,配置相应port的CRL和CRH*/
  2. void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
  3. {
  4.   uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;
  5.   uint32_t tmpreg = 0x00, pinmask = 0x00;
  6.   assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  7.   assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));
  8.   assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));  
  9.   
  10.   currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F); //currentmode保留了GPIO_Mode[3:0];

  11.   if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)//如果GPIO_Mode[4]为1,表示为输出模式;
  12.   {
  13.      /*if(输出模式),将CNF[1:0]和MODE[1:0]的信息保存到currentmode[3:0]*/
  14.     assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
  15.     currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;//currentmode或上GPIO_Speed[1:0];
  16.   }
  17.   
  18.   /*以下部分为CRL Configuration*/
  19.   if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)        //if(是低8位pin);
  20.   {
  21.     tmpreg = GPIOx->CRL;                                //temreg存放CRL寄存器的信息;
  22.     for (pinpos = 0x00; pinpos < 0x08; pinpos++)        //pinpos为几,表示引脚几;        
  23.     {
  24.       pos = ((uint32_t)0x01) << pinpos;                    
  25.       currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;    //currentpin:要么为当前pin值,要么为0;
  26.       if (currentpin == pos)
  27.       {
  28.         pos = pinpos << 2;                                //pos:引脚对应的CRL配置位
  29.         pinmask = ((uint32_t)0x0F) << pos;                //pinmask:引脚对应的CRL[3:0]置1
  30.         tmpreg &= ~pinmask;                                //temreg中对应引脚的[3:0]清0
  31.         tmpreg |= (currentmode << pos);                    //temreg中对应引脚的[3:0]配置成currentmode[3:0]

  32.         //此处的if else应该是通过ODR来配置硬件,由中文参考手册8.1.7原理图推测可知      
  33.         if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD) //if(输入连下拉电阻)
  34.         {
  35.           GPIOx->BRR = (((uint32_t)0x01) << pinpos);     //通过配置ODR的16bit,对应pin的bit置0,连接下拉电阻;
  36.         }
  37.         else
  38.         {
  39.           if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)//if(输入连上拉电阻)
  40.           {
  41.             GPIOx->BSRR = (((uint32_t)0x01) << pinpos);     //通过配置ODR的16bit,对应pin的bit置1,连接上拉电阻;
  42.           }
  43.         }
  44.       }
  45.     }
  46.     GPIOx->CRL = tmpreg;  //把配置好对应pin脚的temreg放回CRL中
  47.   }
  48.   
  49. /*---------------------------- GPIO CRH Configuration ------------------------*/
  50.   /* Configure the eight high port pins */
  51.   if (GPIO_InitStruct->GPIO_Pin > 0x00FF)
  52.   {
  53.     tmpreg = GPIOx->CRH;
  54.     for (pinpos = 0x00; pinpos < 0x08; pinpos++)
  55.     {
  56.       pos = (((uint32_t)0x01) << (pinpos + 0x08));
  57.       /* Get the port pins position */
  58.       currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos);
  59.       if (currentpin == pos)
  60.       {
  61.         pos = pinpos << 2;
  62.         /* Clear the corresponding high control register bits */
  63.         pinmask = ((uint32_t)0x0F) << pos;
  64.         tmpreg &= ~pinmask;
  65.         /* Write the mode configuration in the corresponding bits */
  66.         tmpreg |= (currentmode << pos);
  67.         /* Reset the corresponding ODR bit */
  68.         if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
  69.         {
  70.           GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));
  71.         }
  72.         /* Set the corresponding ODR bit */
  73.         if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
  74.         {
  75.           GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));
  76.         }
  77.       }
  78.     }
  79.     GPIOx->CRH = tmpreg;
  80.   }
  81. }
复制代码

    2.1.3 推挽输出,开漏输出,上拉输入和下拉输入的原理推荐参考安富莱文档的解释
  2.2 LCKR端口配置锁定寄存器:lock register
    复位值为0x0000_0000;偏移地址:0x18;
    用来锁存对应端口的CRL,CRH寄存器的配置;修改完LCK[15:0]然后锁定[LCKK],对应的CRL,CRH配置将会持续到下次系统复位信号来临;

1371863-20200515135452426-1739367378.png
    
  2.3 IDR端口输入数据寄存器,ODR端口输出数据寄存器:input data register,output data register;
    复位值为0x0000_0000;IDR偏移地址:0x08;ODR偏移地址:0x0C
    对于输入数据而言,每个APB2时钟会采样I/O脚上的数据存入数据寄存器中,对寄存器的读取可以获得输入数据;
    对于输出数据而言,应该也是通过APB2时钟控制,把数据放入ODR即可;

1371863-20200515110114147-1808242956.png
 
    2.3.1 IDR寄存器的使用函数
  1. /*以下代码位于stm32f10x_gpio.c中*1 读取IDR寄存器某一位的值,即pin值;*2 读取IDR寄存器的值,即port值;*/
  2. uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
  3. {
  4.   uint8_t bitstatus = 0x00;
  5.   
  6.   /* Check the parameters */
  7.   assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  8.   assert_param(IS_GET_GPIO_PIN(GPIO_Pin));

  9.   /*先读取整个IDR寄存器,然后通过&来读取bit,IDR寄存器的最小处理单位是16bit*/
  10.   if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET)
  11.   {
  12.     bitstatus = (uint8_t)Bit_SET;
  13.   }
  14.   else
  15.   {
  16.     bitstatus = (uint8_t)Bit_RESET;
  17.   }
  18.   return bitstatus;
  19. }

  20. uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx)
  21. {
  22.   /* Check the parameters */
  23.   assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  24.   
  25.   return ((uint16_t)GPIOx->IDR);
  26. }
复制代码
    2.3.2 ODR寄存器的使用函数
  1. /*以下代码位于stm32f10x_gpio.c中;
  2. *1 读取ODR寄存器某一位的值;即读取pin值;
  3. *2 读取ODR寄存器的值;即读取port值;
  4. *3 向ODR寄存器写入port值;*/
  5. uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
  6. {
  7.   uint8_t bitstatus = 0x00;
  8.   assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  9.   assert_param(IS_GET_GPIO_PIN(GPIO_Pin));

  10.    /*先读取整个ODR寄存器,然后通过&来读取bit,ODR寄存器的最小处理单位是16bit*/
  11.   if ((GPIOx->ODR & GPIO_Pin) != (uint32_t)Bit_RESET){
  12.     bitstatus = (uint8_t)Bit_SET;
  13.   }
  14.   else{
  15.     bitstatus = (uint8_t)Bit_RESET;
  16.   }
  17.   return bitstatus;
  18. }

  19. uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx)
  20. {
  21.   assert_param(IS_GPIO_ALL_PERIPH(GPIOx));   
  22.   return ((uint16_t)GPIOx->ODR);
  23. }

  24. void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal)
  25. {
  26.   assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  27.   GPIOx->ODR = PortVal;
  28. }
复制代码
  2.4 BSRR端口置位/复位寄存器,BRR端口复位寄存器:bit set/reset register,bit reset register;
    复位值为0x0000_0000;BSRR偏移地址:0x10;BRR偏移地址:0x14;
    对BSRR,BRR的操作,就是对该组GPIO口的ODR寄存器寄存器的操作;

1371863-20200515113753656-753752303.png
    
    2.4.1 BSRR寄存器:pin置1
  1. void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
  2. {
  3.   assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  4.   assert_param(IS_GPIO_PIN(GPIO_Pin));
  5.   
  6.   GPIOx->BSRR = GPIO_Pin;
  7. }
复制代码

    2.4.2 BRR寄存器:pin清0
  1. void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
  2. {
  3.   assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  4.   assert_param(IS_GPIO_PIN(GPIO_Pin));
  5.   
  6.   GPIOx->BRR = GPIO_Pin;
  7. }
复制代码

    2.4.3 设置pin脚相应的数值:pin的置1清0
  1. void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal)
  2. {
  3.   assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  4.   assert_param(IS_GET_GPIO_PIN(GPIO_Pin));
  5.   assert_param(IS_GPIO_BIT_ACTION(BitVal));
  6.   
  7.   if (BitVal != Bit_RESET)
  8.   {
  9.     GPIOx->BSRR = GPIO_Pin;
  10.   }
  11.   else
  12.   {
  13.     GPIOx->BRR = GPIO_Pin;
  14.   }
  15. }
复制代码

  虽然BSRR和BRR都可以用来设置单独bit位,但是它们也是通过16bit长度来设置的,不要被函数具有迷惑性的名字给欺骗;
3 GPIO的复用和重映射寄存器
  3.1 GPIO的复用
    复用功能具体见中文参考手册8.1.11小节;
    看起来只要把输入输出模式配置成相应的外设模式,就可以使用外设了;
    看起来好像没有区分通用GPIO模式和复用GPIO模式啊,而且有的引脚有两三个复用功能的,感觉结构比较琐碎;;
  3.2 GPIO的重映射
    重映射功能具体见<中文参考手册>8.3和8.4小节;
    8.3小节主要是列出了外设的重映射引脚;8.4小节是外设的重映射寄存器的配置;
    3.1.1 外设的重映射功能需要通过AFIO_MAPR寄存器来映射到GPIO口;然后配置GPIO口复用该外设;这时候就可以使用该外设了;
    3.1.2 芯片为GPIO的复用外设提供了16个可设置的中断,对应16个引脚号;
      AFIO_EXTICRx中断寄存器配置端口号;EXTICR1配置引脚[3:0]的端口号,EXTICR4配置引脚[15:12]的端口号;
    3.1.3 外设应该有外设自己的中断函数的吧,这里为什么又为复用的外设提供了16个中断呢?这些中断对应哪些中断处理函数呢?
  3.3 位带操作
    另外标准库还为GPIO口提供了位带操作,主要就是有两个区域地址块的寄存器是可以直接以bit为单位进行设置;
    相当于给GPIO开了个小灶方便某些不想使用标准库的人可以直接设置寄存器,个人不太中意这个功能;
4 通用GPIO的示例代码
  配置GPIO端口,在寄存器层面来说:首先使能所在外设的时钟源,然后配置完CRL和CRH后GPIO口就可以使用了;
  如果GPIO pin 配置成了输入引脚,则从IDR读取数据即可;
  如果GPIO pin 配置成了输出引脚,输出的信号可以直接写入ODR寄存器,也可以通过BSRR和BRR来设置;
  1. #include "delay.h"

  2. int main(void)
  3. {
  4.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  5.     GPIO_InitTypeDef GPIO_Struct;

  6.     //portA pin1 as input;     
  7.     GPIO_Struct.GPIO_Pin = GPIO_Pin_1;            
  8.     GPIO_Struct.GPIO_Mode =GPIO_Mode_IPD ;     
  9.     GPIO_Init(GPIOA, &GPIO_Struct);
  10.    
  11.     //portA pin2 as output;                        
  12.     GPIO_Struct.GPIO_Pin = GPIO_Pin_2;
  13.     GPIO_Struct.GPIO_Speed = GPIO_Speed_50MHz;
  14.     GPIO_Struct.GPIO_Mode = GPIO_Mode_Out_PP;
  15.     GPIO_Init(GPIOA, &GPIO_Struct);                                          
  16.     while(1)
  17.     {
  18.         GPIO_SetBits(GPIOA,GPIO_Pin_2);
  19.         delay_ms(100);
  20.         GPIO_ResetBits(GPIOA,GPIO_Pin_2);
  21.         delay_ms(100);
  22.     }
  23. }
复制代码

5 小结
  本文主要是结合通用GPIO口的寄存器,对标准库中通用GPIO口的代码进行了分析和概括;
  然后提供了一个代码示例;如果只是使用而不想理解标准库原理,则直接使用接口函数即可,如代码示例所示;

收藏 评论0 发布时间:2022-2-6 19:49

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版