在点灯的时候遇到一个问题:
GPIO_ResetBits(GPIOF,GPIO_Pin_9); //LED0对应引脚GPIOF.9拉低,亮 等同LED0=0;
GPIO_SetBits(GPIOF,GPIO_Pin_9); //LED0对应引脚GPIOF.0拉高,灭 等同LED0=1;
为啥通过GPIO_Pin_9 这个参数就可以设置GPIOF中引脚9的高低电平呢,我找到了GPIO相应的置位和复位函数:
//复位函数 设置IO引脚为低电平,点亮led
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Pin));
GPIOx->BSRRH = GPIO_Pin;
}
//置位函数 设置IO引脚为高电平,熄灭led
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Pin));
GPIOx->BSRRL = GPIO_Pin;
}
这两段函数都是先检查传入参数的有效性,然后执行这个代码:
GPIOx->BSRRL = GPIO_Pin;
GPIO_Pin就是传入的参数,在这里其实就是调用函数时候填写的GPIO_Pin_9,那为啥填写这个就可以配置GPIOx->BSRRL寄存器呢,这也不是变量啊,怎么给寄存器GPIOx->BSRRH赋值的呢:
在如下代码位置右击,点击红框处:
就看到这个界面:
原来是通过宏定义啊:
#define GPIO_Pin_9 ((uint16_t)0x0200)
其实换成16进制,也就是:
#define GPIO_Pin_9 0000 0010 0000 0000
再来看一下BSRR寄存器:
0000 0010 0000 0000正好就是对寄存器的第9位(BS9)写1置位,引脚9输出高电平,这个时候LED熄灭(低电平点亮); 同样,对寄存器的第25位(BR9)写1复位,引脚9输出低电平,这个时候LED点亮。
说明:置位 复位都是操作同一个寄存器,只不过分为低 16 位和高 16 位:
- 低 16 位(0-15),我们往相应的位写 1,那么对应的 IO 口会输出高电平
- 高 16 位(16-31)作用刚好相反,对相应的位写 1 会输出低电平
总结:STM32对宏定义的使用较多,写成这样当然也是可以的:
GPIOx->BSRRL = ((uint16_t)0x0200);
或者这样:
GPIOx->BSRRL = 0000 0010 0000 0000
但是问题就是不那么清晰明了,采用宏定义的方式给这些变量起个名字,这样一眼就可以看出这个是设置哪个引脚的,要不然还得去看手册,查寄存器:
GPIOx->BSRRL = GPIO_Pin; //这里的GPIO_Pin 就是传入的参数GPIO_Pin_9