野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 18503|回复: 7

STM32库函数个人浅析实现之以void GPIO_Init()开始

[复制链接]
发表于 2018-6-5 23:43:05 | 显示全部楼层 |阅读模式
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;                                        //  currentmode  当前IO配置模式 ; currentpin 当前pin脚  ; tmpreg  目标寄存器  ;
  /* 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));  

/* **********************************************************************
typedef enum
{ GPIO_Mode_AIN = 0x0,                          //        0000     0000    模拟输入
  GPIO_Mode_IN_FLOATING = 0x04,          //        0000     0100    浮空输入
  GPIO_Mode_IPD = 0x28,                        //         0010     1000    下拉输入
  GPIO_Mode_IPU = 0x48,                        //         0100     1000    上拉输入
  GPIO_Mode_Out_OD = 0x14,                  //         0001     0100   通用开漏输出
  GPIO_Mode_Out_PP = 0x10,                  //          0001     0000   通用推挽输出
  GPIO_Mode_AF_OD = 0x1C,                   //         0001     1100   复用开漏输出
  GPIO_Mode_AF_PP = 0x18                     //         0001     1000   复用推挽输出
}GPIOMode_TypeDef;




***********************************************************************/
/*---------------------------- GPIO Mode Configuration -----------------------*/
  currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);  
   //  cureenmode = 0000 xx00 ;   00 为 mode值,   xx 为CNF值;
   // GPIO_InitStruct->GPIO_Mode 为输入模式时(GPIO_Mode_AIN,GPIO_Mode_IN_FLOATING,GPIO_Mode_IPD,GPIO_Mode_IPU),xx00 为设置数据;
   //  00表明输入模式,xx 为具体输入模式;

  if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)  //  判断是否是输出模式;
  // GPIO_InitStruct->GPIO_Mode   的 bit4 为 1时,即为 输出模式 时,进入if
  {
    /* Check the parameters */
    assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
    /* Output mode */
    currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;    //  currentmode =  0000 xxyy ;xx 与 yy 分别取决于初始化 GPIO_Mode 设置 与 speed设置;     //  即 GPIO_InitStruct 结构体 初始化数据 ; yy 表明为输出 ,xx为具体输出模式;
  }

/*---------------------------- GPIO CRL Configuration ------------------------*/
  /* Configure the eight low port pins */
  if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)  //  GPIO_Pin 为 0~7 时,使用CRL 寄存器;
  {
    tmpreg = GPIOx->CRL;//  当前 CRL数据放到 tmpreg中;

CRL

CRL

    for (pinpos = 0x00; pinpos < 0x08; pinpos++)  // CRL 32位 寄存器 存放 Pin_0~Pin_7 的配置数据;
    {
      pos = ((uint32_t)0x01) << pinpos;  // pinpos 位当前检查的pin脚 (0~7),
      /* Get the port pins position */
      currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;//  pos 与 GPIO_InitStruct->GPIO_Pin 相等时,就找到了当前要配置的 IO引脚 pinpos;
      if (currentpin == pos)
      {
        pos = pinpos << 2;                //   pinpos << 2 ;   初看时较不好理解; 看32位的CRL就清楚了, CRL(BIT0~BIT31)以此定义了PIN0~PIN7的配置数据   
                                                   //    如 引脚3的配置数据在 CRL 的  bit8~bit11  ,引脚6的配置数据在 CRL 的  bit24~bit27  ;
                                                   //    pinpos << 2; 即 pos = pinpos * 4 ; 现在pos 的 值正好是 需要配置引脚模式的 起始位 ;
                                                   //    GPIO_Pin 0~7 分别 对应  pos = (0,4,8,12,16,20,24,28)
        /* Clear the corresponding low control register bits */
        pinmask = ((uint32_t)0x0F) << pos;  //  0000 0000   0000 0000   0000 0000   0000 0000   0000 1111  << pos ;   
        tmpreg &= ~pinmask;         //  若 是要配置的IO是  GPIO_InitStruct->GPIO_Pin=GPIO_Pin_5,那么 pinpos = 5,pos = pinpos << 2 = 20;
                                                 //     pinmask =  0000 0000   1111 0000    0000 0000   0000 0000     1111 的位置正好是 CNF5 MODE5 的位置所在;
                                                 //  ~ pinmask =  FFFF FFFF   0000  FFFF   ........          ;  tmpreg  = tmpreg & ~pinmask = 0x 44 44  00 44  44 44  44 44
                                                
        /* Write the mode configuration in the corresponding bits */
        tmpreg |= (currentmode << pos);  //   把 currentmode 数据 写入到 tmpreg 的 数据00  位置中;
        /* Reset the corresponding ODR bit */
        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)  
        {
          GPIOx->BRR = (((uint32_t)0x01) << pinpos);      
          //   下拉输入模式  与 上拉输入模式  ,CNF【1:0】数据都是  1 0 ;以相应ODR输出数据 来区分;ODR相应位为 0  下拉输入  ;ODR相应位为 1  上拉输入;
          //   向BRR寄存器相应位写 1   ,使相应ODR 输出 0
        }
        else
        {
          /* Set the corresponding ODR bit */
          if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
          {
            GPIOx->BSRR = (((uint32_t)0x01) << pinpos);   //   向BSRR寄存器相应位写 1   ,使相应ODR 输出 1
          }
        }
      }
    }
    GPIOx->CRL = tmpreg;
  }
/*---------------------------- 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;
  }
}

回复

使用道具 举报

发表于 2018-6-6 11:52:21 | 显示全部楼层
不错,写下来自己就更了解了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-6-10 00:06:41 | 显示全部楼层
SystemInit()说了什么 分析,如有错误,多谢指正。 stm32-SystemInit()分析.rar (82.36 KB, 下载次数: 13)

[url=]stm32-SystemInit()分析. ...[/url]
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-6-10 00:48:15 | 显示全部楼层
启动文件  SystemInit()时钟初始化函数分析

stm32-SystemInit()分析.rar

82.36 KB, 下载次数: 12

stm32-库函数SystemInit()分析

回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-6-10 12:45:39 | 显示全部楼层
stm32-SystemInit()分析.rar (82.36 KB, 下载次数: 8)



回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-6-13 15:45:11 | 显示全部楼层
中断流程概况

stm32中断概况.rar

1.66 MB, 下载次数: 14

中断流程概况

回复 支持 反对

使用道具 举报

发表于 2018-6-22 09:17:07 | 显示全部楼层
写的蛮详细的,
回复 支持 反对

使用道具 举报

发表于 2018-7-1 08:53:10 | 显示全部楼层
不错,好东西谢谢分享
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2025-12-6 21:59 , Processed in 0.046676 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表