入门STM32中的GPIO_Init()初始化函数的详细解析

本文为参考野火stm32教程中的GPIO_Init()函数的个人初步解析。
假定:需使用的引脚为GPIOA的A3口:

控制的引脚是GPIO_Pin_3,
引脚的模式是 GPIO_Mode_Out_PP(通用推挽输出),
引脚的速率是GPIO_Speed_10MHz,

用到的寄存器是CRL(低八位)

将上述的引脚、模式、速率换算成32位的16进制,分别是:

  1. 控制的引脚是GPIO_Pin_3
    换算成32位的16进制是:0x0000 0004
  2. 引脚的模式是 GPIO_Mode_Out_PP(通用推挽输出)
    换算成32位的16进制是:0x0000 0010
  3. 引脚的速率是GPIO_Speed_10MHz
    换算成32位的16进制是:0x0000 0001

然后调用库函数GPIO_Init(),初始化GPIOA
GPIO_Init(GPIOA, &GPIO_InitStruct);

  • GPIO_Init()函数的解析开始如下:

currentmode = ((uint32)GPIO_InitStruct->GPIO_Mode) & ((uint32)0x0F);//GPIO_Mode的低四位暂存在currentmode

  • 可以得出currentmode=0x0000 0010 & 0x0000 000F =0x0000 0000

if ((((uint32)GPIO_InitStruct->GPIO_Mode) & ((uint32)0x10)) != 0x00)//bit4=1为OUT,=0为IN;判断是输入还是输出模式

  • 本例:0x0000 0010 & 0x0000 00010 !=0x 0000 0000

此处结果为1则执行下面语句
{

currentmode |= (uint32)GPIO_InitStruct->GPIO_Speed;	 //若为输出模式则写入输出速度,

可以得出currentmode=currentmode | 0x0000 0001=0x0000 0000 | 0x0000 0001
=0x0000 0001
}

if (((uint32)GPIO_InitStruct->GPIO_Pin & ((uint32)0x00FF)) != 0x00) //判定端口是否为低八位,并配置端口。

  • 本例:0x0000 0004 & 0x 0000 00FF != 0x0000 0000,此处结果为1则执行下面语句
    {
    tmpreg = GPIOx->CRL;

  • 备份原CRL寄存器的值 则是:tmpreg=0x4444 4444

for (pinpos = 0x00; pinpos < 0x08; pinpos++)
{
pos = ((uint32)0x01) << pinpos; // pos的值为1左移pinpos位

  • 本例:pos =0x0000 0001 << 0x03= 0x0000 1000

    currentpin = (GPIO_InitStruct->GPIO_Pin) & pos; // 令pos与输入参数GPIO_PIN作位与运算,为下面的判断作准备。

  • 可得currentpin = 0x0000 1000 & 0x00001000
    =0x0000 1000

    if (currentpin == pos)

  • 由上面得出的pos = 0x0000 1000
    currentpin = 0x0000 1000
    两者相等,则执行下面代码语句

    {
    pos = pinpos << 2;

  • 可得pos = 0x0000 0003 << 2
    =0x 0000 000C

    把控制这个引脚的4个寄存器位清零,其它寄存器位不变
    ①pinmask = ((uint32_t)0x0F) << pos;

  • 可得pinmask=0x0000 000F << 0x0000 000C=0x0000 F000
    相当于把1111左移12个位,0x1111 0000 0000 0000=0xF000,即A3口。
    ②tmpreg &= ~pinmask;

  • 可得 tmpreg = tmpreg & ~pinmask
    = 0x4444 4444 & 0xFFFF 0FFF
    = 0x4444 0444

tmpreg |= (currentmode << pos);

  • 首先,要知道currentmode << pos = 0x0000 0001 << 0x 0000 0003
    = 0x 0000 1000
    可得 tmpreg = tmpreg | 0x0000 1000
    = 0x4444 0444 | 0x0000 1000
    = 0x4444 1444

     if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
      判断是否为下拉输入模式
     {
       GPIOx->BRR = (((uint32_t)0x01) << pinpos);
     }
     else
     {
       /* Set the corresponding ODR bit */
       if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
        判断是否为上拉输入模式
       {
         GPIOx->BSRR = (((uint32_t)0x01) << pinpos);
       }
     }
        结果,两种输入模式都不是,而是通用推挽输出,所以不执行
    

    }
    }

GPIOx->CRL = tmpreg;

  • 把前面处理后的暂存值写入到CRL寄存器之中 也就是GPIOx->CRL = 0x4444 1444
    }
    最终,向GPIOB组的CRL寄存器写入一个值:GPIOx->CRL = 0x4444 4443。转换为二进制是:(0100 0100 0100 0100 0001 0100 0100 0100)B
    因此,Pin3的控制值为(0001)B即CNF:00,MODE:01。其他低八位的IO口的值默认为0x44。从头至尾的例举结果判断此程序编写的效果OK。
  • 15
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值