学习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的通用推挽输出模式。
『本文转载自网络,凯发旗舰的版权归原作者所有,如有侵权请联系删除』