参考资料: GPIO相关介绍
stm32的寄存器都是32位的。
GPIO_TypeDef
/**
* @brief General Purpose I/O
*/
typedef struct
{
__IO uint32_t CRL;
__IO uint32_t CRH;
__IO uint32_t IDR;
__IO uint32_t ODR;
__IO uint32_t BSRR;
__IO uint32_t BRR;
__IO uint32_t LCKR;
} GPIO_TypeDef;
配置寄存器:CRL, CRH
对于一组GPIO,工作模式配置用2个32位的寄存器实现(16个IO口每个分到4位)。第一个32位寄存器CRL(端口配置低寄存器)对应0到7的GPIO,第二个32位寄存器CRH(端口配置高寄存器)则对应着8到15.
从手册出看出来,以低寄存器为例,每个IO口有4位寄存器,分别是两位的MODEx和两位CNFx,其中MODE是用来配置输出/输入以及最大速度的,而CNF用来配置具体的输入输出模式的,例如推挽输出之类。
输入数据寄存器:IDR
IDR是端口输入数据寄存器,也是一个只读寄存器。它有32位,但是只用了16位。在库函数 GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 中,可以看见对于IDR的使用实例,在 GPIO_ReadInputData(GPIO_TypeDef* GPIOx)
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
uint8_t bitstatus = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GET_GPIO_PIN(GPIO_Pin));
if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET)
{
bitstatus = (uint8_t)Bit_SET;
}
else
{
bitstatus = (uint8_t)Bit_RESET;
}
return bitstatus;
}
输出数据寄存器:ODR
类似IDR,ODR也只用了16位。但是这是一个可读写寄存器。向其中写数据可以控制IO口的输出电平,读其中的数据可以得到IO口的电平状态。
例如,点灯实验中,我们在采用按键控制LED灯的亮灭时,可以使用ODR与位运算异或操作来直接实现状态改变,不需要再判断当前状态了:
GPIOA->ODR^=GPIO_Pin_5;
置位/复位寄存器:BSRR
这也是一个可以设置GPIO口输出为1或0的寄存器。不过和ODR不同的是,在写入BSRR时,只有二进制1起作用,0没有作用。若用0到15位来写,有1的位置被设为高电平;若用16到31位来写,有1的位置被设为低电平,即被清楚为0。同时,如果一个位置同时被设了高低电平,那么就是被设为高电平。