解析STM32 8种工作模式被赋值为0x00、0x04、0x28等的原因和端口速度

如有错误,还请包涵与指出

1.keil中的GIPO端口配置值与对应寄存器端口配置值

        在配置端口模式时,突然想到为什么stm32f10x_gpio.h文件中配置端口的模式值等于图1这些值,这些值与寄存器上介绍的值又感觉不一样,为什么这8种模式就等于对应的这些值。

//8种输出模式
typedef enum
{ GPIO_Mode_AIN = 0x0,
  GPIO_Mode_IN_FLOATING = 0x04,
  GPIO_Mode_IPD = 0x28,
  GPIO_Mode_IPU = 0x48,
  GPIO_Mode_Out_OD = 0x14,
  GPIO_Mode_Out_PP = 0x10,
  GPIO_Mode_AF_OD = 0x1C,
  GPIO_Mode_AF_PP = 0x18
}GPIOMode_TypeDef;

//端口的三种速度
typedef enum
{ 
  GPIO_Speed_10MHz = 1,
  GPIO_Speed_2MHz, 
  GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;

图1  Keil中配置端口给的值

         在STM32中文参考手册中,可以看到端口配置低寄存器(CRL)的定义,如图2所示,对某个端口配置成推挽输出,速度为50MHz,则这4位为:0011。这里当时想糊涂了,一个是0011,一个是0x10,怎么等价的。去网上百度了一下,在正点原子论坛上有条解释是:这个固件库是为了写代码方便赋值,在GPIO_Init初始化里面进行运算,得到的赋值寄存器的相应位。

图2   CRL寄存器配置

 2. 调试LED流水灯代码

        于是,打开一个LED流水灯程序,对PB5进行推挽输出配置,在Debug下观察程序执行过程。①点击魔术棒按钮,②点击显示符号窗口,③右键点击要查看的变量添加到watch窗口,如图3所示。

图3 调试窗口

        将程序执行到GPIO_Init()函数前,观察watch窗口的变量值变化情况,如图4所示。随后点击单步执行,可以看到GPIO_Pin=0x0020,Speed=0x03,Mode=0x10,这与其宏定义和定义的变量值相等。

图4 调试界面

2.1  GPIO_Pin=0x0020,Speed=0x03,Mode=0x10原因

        GPIO_Pin=0x0020,这在gpio.h文件中进行了宏定义,如图5所示。定义成这样的原因是:

图5 引脚宏定义

        引脚0为  0000 0000 0000 0001

        引脚1为  0000 0000 0000 0010

        引脚2为  0000 0000 0000 0100

        以此类推…

        引脚15为1000 0000 0000 0000

        每个I/O端口都有寄存器配置,在参考手册中说到,ODR寄存器的0-15位分别一一对应16个I/O端口,如图6所示。我们在寄存器中对端口PB5进行置1,寄存器操作一般是:

        GPIOB_ODR | = (1<<5);

        这就与刚刚宏定义相对应起来了,哪个寄存器的位需要置1就选择对应的I/O口。

图6 ODR寄存器 

         对于Speed=0x03与Mode=0x10这里用了一个枚举,程序中让10MHz=1,往后枚举值从2开始递增,所50MHz=0x03,推挽输出的值已经给出,如图7所示。

图7 端口速度与模式

        一直点击单步运行,进入GPIO_Iint初始化函数,会判断是低8位还是高8位的寄存器,即CRL与CRH,寄存器每4个位控制一个端口的模式及速度,每个寄存器32位,控制8个I/O口。随着单步执行,会看到这些变量变化,如图8所示,程序具体执行过程就不再分析,直接单步执行非常清晰。

图8 执行过程

3.程序变量最终执行结果

        执行到最后一步,会看到寄存器CRL和变量tmpreg的值为0x4434444,也就是0x 0100 0100 0011 0100 0100 0100 0100 0100,这与之前最开始说的一致,在PB5端口的值为:0011,正好对应了推挽输出,50MHz,如图9所示。其中也可以看到GIPOB的地址为0x40010C00,偏移量也能对应上。

图9 执行完推挽输出变量值

        正如正点原子论坛中所说,对于端口初始化中的输出模式,输出速度等于多少,都是已经在这个gpio.h文件中已经计算好了,让用户可以更加方便的直接使用。还要注意的是,寄存器与Keil中.h文件中定义的值不是一个东西,不要混淆,但却有联系,.h中的值是经过计算的。

物联沃分享整理
物联沃-IOTWORD物联网 » 解析STM32 8种工作模式被赋值为0x00、0x04、0x28等的原因和端口速度

发表评论