STM32中的GPIO_Init()函数的分析
学习STM32时,首先要熟悉流水灯例程,在这里就来分析流水灯中的GPIO_Init()函数
例如:流水灯例程中使用的端口是macLED1_GPIO_PORT=GPIOB,
控制的引脚是GPIO_Pin_0,
引脚的模式是 GPIO_Mode_Out_PP(通用推挽输出),
引脚的速率是GPIO_Speed_50MHz,
用到的寄存器是CRL
将上述的引脚、模式、速率换算成32位的16进制,分别是:
1) 控制的引脚是GPIO_Pin_0
换算成32位的16进制是:0x0000 0001
2) 引脚的模式是 GPIO_Mode_Out_PP(通用推挽输出)
换算成32位的16进制是:0x0000 0010
3) 引脚的速率是GPIO_Speed_50MHz
换算成32位的16进制是:0x0000 0003
然后调用库函数GPIO_Init(),初始化GPIOB
GPIO_Init(macLED1_GPIO_PORT, &GPIO_InitStructure);
GPIO_Init()函数的定义如下:
GPIO Mode Configuration
currentmode=((uint32_t)GPIO_InitStruct->GPIO_Mode)&((uint32_t)0x0F);
可以得出 currentmode=0x0000 0010 & 0x0000 000F
=0x0000 0000
if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)
判断是否是输出模式,“是”,执行下面代码;“否”,不执行
如:0x0000 0010 & 0x0000 00010 !=0x 0000 0000
则执行下面语句
{
/* Output mode */
currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;
可以得出currentmode=currentmode | 0x0000 0003=0x0000 0000
=0x0000 0003
}
GPIO CRL Configuration
if(((uint32_t)GPIO_InitStruct->GPIO_Pin&((uint32_t)0x00FF)) != 0x00)
判断是否是Pin0~Pin7引脚,“是”,执行下面代码;“否”,不执行
如:0x0000 0001 & 0x 0000 00FF != 0x0000 0000
则执行下面语句
{
tmpreg = GPIOx->CRL;
备份原CRL寄存器的值
则是:tmpreg=0x4444 4444
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
{
pos = ((uint32_t)0x01) << pinpos;
pos是0x0000 0001左移 pinpos 位得到的
如:pos =0x0000 0001 << 0x00
= 0x0000 0001
为后面的 if (currentpin == pos) 判断作准备
/* Get the port pins position */
currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
可得currentpin = 0x0000 0001 & 0x0000 0001
=0x0000 0001
为后面的 if (currentpin == pos) 判断作准备
if (currentpin == pos)
由上面得出的pos = 0x0000 0001
currentpin = 0x0000 0001
两者相等,则执行下面代码语句
{
pos = pinpos << 2;
可得pos = 0x0000 0000 << 2
=0x 0000 0000
/* Clear the corresponding low control register bits */
pinmask = ((uint32_t)0x0F) << pos;
可得pinmask=0x0000 000F << 0x0000 0000
= 0x0000 000F
tmpreg &= ~pinmask;
可得 tmpreg = tmpreg & ~pinmask
= 0x4444 4444 & 0xFFFF FFF0
= 0x4444 4440
/* Write the mode configuration in the corresponding bits */
tmpreg |= (currentmode << pos);
首先,要知道currentmode << pos = 0x0000 0003 << 0x 0000 0000
= 0x 0000 0003
可得 tmpreg = tmpreg | 0x0000 0003
= 0x4444 4440 & 0x0000 0003
= 0x4444 4443
/* Reset the corresponding ODR bit */
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 4443
}
最终,向GPIOB组的CRL寄存器写入一个值:
GPIOx->CRL = 0x4444 4443
转换为二进制是:(0100 0100 0100 0100 0100 0100 0100 0011)B
因此,Pin0的控制值为(0011)B
下面是CRL寄存器的说明
对比一下CRL寄存器的说明,Pin0的控制值正好可以把GPIO设置为符合我们输入参数要求的状态,即最大速率为50MHz的通用推挽输出模式。
---------------------
作者:PINLemon
来源:CSDN
原文:https://blog.csdn.net/PINLemon/article/details/72857922
版权声明:本文为博主原创文章,转载请附上博文链接!