经过差不多一个下午,读了一遍GPIO初始化函数,差不多理解了固件库是怎么设置寄存器的,但是无法理解写固件库的牛人是如何想出的这几个值的,程序中有我看不懂的我用红色字标记出来了,希望懂得大神给讲解一下
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;
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{
uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;
uint32_t tmpreg = 0x00, pinmask = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));
assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));
/*---------------------------- GPIO Mode Configuration -----------------------*/
/*取出GPIO_Mode中的低4位,这4位中的高两位对应寄存器中CNFy对应的两位*/
currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);
/*用来判断是输入状态还是输出状态,条件成立为输出模式,条件不成立为输入模式,只有输出模式才设置speed*/
if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)
{
/* Check the parameters */
assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
/* Output mode */
currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;
/*此时的currentmode即为一个GPIO的端口配置寄存器的值,这样说不完全对,在下面的判断中还需要将这4位值进行移位*/
}
/*---------------------------- GPIO CRL Configuration ------------------------*/
/* Configure the eight low port pins */
/*用来判断是不是每组IO口的低8位IO口*/
if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)
{
/*读出一组GPIO的低8位端口配置寄存器的值,这个一个32位的数值,每4位对应一个GPIO口*/
tmpreg = GPIOx->CRL;
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
{
/*循环8次,pos和pinpos的值分别为
pos pinpos pinpos << 2
0000 0001 0000 0000 0000 0000 0
0000 0010 0000 0001 0000 0100 4
0000 0100 0000 0010 0000 1000 8
0000 1000 0000 0011 0000 1100 12
0001 0000 0000 0100 0001 0000 16
0010 0000 0000 0101 0001 0100 20
0100 0000 0000 0110 0001 1000 24
1000 0000 0000 0111 0001 1100 28 */
pos = ((uint32_t)0x01) << pinpos;
/* Get the port pins position */
currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
if (currentpin == pos)
{
pos = pinpos << 2;
/* Clear the corresponding low control register bits */
/*清空该GPIO口对应的配置寄存器的值*/
pinmask = ((uint32_t)0x0F) << pos;
tmpreg &= ~pinmask;
/* Write the mode configuration in the corresponding bits */
/*把当前设置的GPIO配置寄存器的值写入到对应的位置,其他GPIO对应的配置寄存器的值未做改动*/
tmpreg |= (currentmode << pos);
/* Reset the corresponding ODR bit */
/*如果是下拉输入清除对应的ODRy为0,不知道为何要这样做*/
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
GPIOx->BRR = (((uint32_t)0x01) << pinpos);
}
else
{
/* Set the corresponding ODR bit */
/*如果是上拉输入设置对应的ODRy为1,不知道为什么要这么做*/
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
GPIOx->BSRR = (((uint32_t)0x01) << pinpos);
}
}
}
}
/*将改变之后的的值重新写入端口配置低寄存器中*/
GPIOx->CRL = tmpreg;
}
/*---------------------------- GPIO CRH Configuration ------------------------*/
/* Configure the eight high port pins */
/*判断是不是每组IO口的高8位IO口*/
if (GPIO_InitStruct->GPIO_Pin > 0x00FF)
{
/*读出一组GPIO的高8位端口配置寄存器的值,这个一个32位的数值,每4位对应一个GPIO口*/
tmpreg = GPIOx->CRH;
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
{
/*循环8次,pos和(pinpos + 0x08)的值分别为
pos pinpos + 0x08 pinpos << 2
0000 0001 0000 0000 0x08 0
0000 0010 0000 0000 0x09 4
0000 0100 0000 0000 0x0A 8
0000 1000 0000 0000 0x0B 12
0001 0000 0000 0000 0x0C 16
0010 0000 0000 0000 0x0D 20
0100 0000 0000 0000 0x0E 24
1000 0000 0000 0000 0x0F 28
*/
pos = (((uint32_t)0x01) << (pinpos + 0x08));
/* Get the port pins position */
currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos);
if (currentpin == pos)
{
pos = pinpos << 2;
/* Clear the corresponding high control register bits */
/*清空该GPIO口对应的配置寄存器的值*/
pinmask = ((uint32_t)0x0F) << pos;
tmpreg &= ~pinmask;
/* Write the mode configuration in the corresponding bits */
/*把当前设置的GPIO配置寄存器的值写入到对应的位置,其他GPIO对应的配置寄存器的值未做改动*/
tmpreg |= (currentmode << pos);
/* Reset the corresponding ODR bit */
/*如果是下拉输入清除对应的ODRy为0,不知道为何要这样做*/
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));
}
/* Set the corresponding ODR bit */
/*如果是上拉输入设置对应的ODRy为1,不知道为什么要这么做*/
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));
}
}
}
/*将改变之后的的值重新写入端口配置高寄存器中*/
GPIOx->CRH = tmpreg;
}
} |