以下使用ST的HAL_GPIO_Init()函数举例。
在ST官方库中,我们可以找到对于某个GPIO初始化的函数 HAL_GPIO_Init()
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
{
uint32_t position;
uint32_t ioposition = 0x00;
uint32_t iocurrent = 0x00;
uint32_t temp = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Init->Pin));
assert_param(IS_GPIO_MODE(GPIO_Init->Mode));
assert_param(IS_GPIO_PULL(GPIO_Init->Pull));
/* Configure the port pins */
for(position = 0; position < GPIO_NUMBER; position++)
{
/* Get the IO position */
ioposition = ((uint32_t)0x01) << position;
/* Get the current IO position */
iocurrent = (uint32_t)(GPIO_Init->Pin) & ioposition;
if(iocurrent == ioposition)
{
...
这段代码的主要目的是根据 GPIO_InitTypeDef结构体中的 Pin来找到对应的要操作的针脚位置
而Pin中储存的值为下列HEX值中的一种或者组合得来
#define GPIO_Pin_0 ((uint16_t)0x0001)
#define GPIO_Pin_1 ((uint16_t)0x0002)
#define GPIO_Pin_2 ((uint16_t)0x0004)
#define GPIO_Pin_3 ((uint16_t)0x0008)
#define GPIO_Pin_4 ((uint16_t)0x0010)
#define GPIO_Pin_5 ((uint16_t)0x0020)
#define GPIO_Pin_6 ((uint16_t)0x0040)
#define GPIO_Pin_7 ((uint16_t)0x0080)
#define GPIO_Pin_8 ((uint16_t)0x0100)
#define GPIO_Pin_9 ((uint16_t)0x0200)
#define GPIO_Pin_10 ((uint16_t)0x0400)
#define GPIO_Pin_11 ((uint16_t)0x0800)
#define GPIO_Pin_12 ((uint16_t)0x1000)
#define GPIO_Pin_13 ((uint16_t)0x2000)
#define GPIO_Pin_14 ((uint16_t)0x4000)
#define GPIO_Pin_15 ((uint16_t)0x8000)
#define GPIO_Pin_All ((uint16_t)0xFFFF)
例如:0x0200 的对应二进制值为 0000 0010 0000 0000 ,从右向左数的第9位(第一位计“0”)被置1。这代表着选择了某个GPIO的第9个针脚 。
那么,为什么要这样一直从第一位枚举到最大位来对比哪个某个针脚被选中,然后进行操作,而不是一开始就直接用位与0x0001然后右移位的方式来直接查找到需要的针脚是哪一个呢?
我们来看一下官方程序的思想:
1.查看第一位是否被选择,如果被选择,进行初始化操作
2.查看第二位是否被选择,如果被选择,进行初始化操作
。。。
到这里不难看出,官方程序的目的是逐个判断传入该函数的GPIO_Init中,Pin值对应的哪些针脚被选择。
这样其实就带来了便利,比如我们要对GPIOA的0、3、5脚使用相同的方法初始化:
如果不使用官方的方法,而是如前所述的先找到从低位开始向高位数的第一个被置1的对应针脚
...
GPIO_InitTypeDef GPIO_InitStructure;
...
GPIO_InitStructure.Pin = GPIO_PIN_0;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
...
GPIO_InitStructure.Pin = GPIO_PIN_3;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
...
GPIO_InitStructure.Pin = GPIO_PIN_5;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
...
而使用官方的方法,我们可以这样
...
GPIO_InitTypeDef GPIO_InitStructure;
...
GPIO_InitStructure.Pin = GPIO_PIN_0 | GPIO_PIN_3 | GPIO_PIN_5;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
参照上文,
GPIO_PIN_0 | GPIO_PIN_3 | GPIO_PIN_5;
则相当于 0000 0000 0010 1001
于是在循环中,程序检测到第0位被选择,于是对第0位对应的针脚初始化。然后检测到第3位被选择,于是对第3位对应的针脚初始化······