大学生
最后登录1970-1-1
在线时间 小时
注册时间2018-6-4
|
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; // currentmode 当前IO配置模式 ; currentpin 当前pin脚 ; tmpreg 目标寄存器 ;
/* 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));
/* **********************************************************************
typedef enum
{ GPIO_Mode_AIN = 0x0, // 0000 0000 模拟输入
GPIO_Mode_IN_FLOATING = 0x04, // 0000 0100 浮空输入
GPIO_Mode_IPD = 0x28, // 0010 1000 下拉输入
GPIO_Mode_IPU = 0x48, // 0100 1000 上拉输入
GPIO_Mode_Out_OD = 0x14, // 0001 0100 通用开漏输出
GPIO_Mode_Out_PP = 0x10, // 0001 0000 通用推挽输出
GPIO_Mode_AF_OD = 0x1C, // 0001 1100 复用开漏输出
GPIO_Mode_AF_PP = 0x18 // 0001 1000 复用推挽输出
}GPIOMode_TypeDef;
***********************************************************************/
/*---------------------------- GPIO Mode Configuration -----------------------*/
currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);
// cureenmode = 0000 xx00 ; 00 为 mode值, xx 为CNF值;
// GPIO_InitStruct->GPIO_Mode 为输入模式时(GPIO_Mode_AIN,GPIO_Mode_IN_FLOATING,GPIO_Mode_IPD,GPIO_Mode_IPU),xx00 为设置数据;
// 00表明输入模式,xx 为具体输入模式;
if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00) // 判断是否是输出模式;
// GPIO_InitStruct->GPIO_Mode 的 bit4 为 1时,即为 输出模式 时,进入if
{
/* Check the parameters */
assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
/* Output mode */
currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed; // currentmode = 0000 xxyy ;xx 与 yy 分别取决于初始化 GPIO_Mode 设置 与 speed设置; // 即 GPIO_InitStruct 结构体 初始化数据 ; yy 表明为输出 ,xx为具体输出模式;
}
/*---------------------------- GPIO CRL Configuration ------------------------*/
/* Configure the eight low port pins */
if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00) // GPIO_Pin 为 0~7 时,使用CRL 寄存器;
{
tmpreg = GPIOx->CRL;// 当前 CRL数据放到 tmpreg中;
CRL
for (pinpos = 0x00; pinpos < 0x08; pinpos++) // CRL 32位 寄存器 存放 Pin_0~Pin_7 的配置数据;
{
pos = ((uint32_t)0x01) << pinpos; // pinpos 位当前检查的pin脚 (0~7),
/* Get the port pins position */
currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;// pos 与 GPIO_InitStruct->GPIO_Pin 相等时,就找到了当前要配置的 IO引脚 pinpos;
if (currentpin == pos)
{
pos = pinpos << 2; // pinpos << 2 ; 初看时较不好理解; 看32位的CRL就清楚了, CRL(BIT0~BIT31)以此定义了PIN0~PIN7的配置数据
// 如 引脚3的配置数据在 CRL 的 bit8~bit11 ,引脚6的配置数据在 CRL 的 bit24~bit27 ;
// pinpos << 2; 即 pos = pinpos * 4 ; 现在pos 的 值正好是 需要配置引脚模式的 起始位 ;
// GPIO_Pin 0~7 分别 对应 pos = (0,4,8,12,16,20,24,28)
/* Clear the corresponding low control register bits */
pinmask = ((uint32_t)0x0F) << pos; // 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 << pos ;
tmpreg &= ~pinmask; // 若 是要配置的IO是 GPIO_InitStruct->GPIO_Pin=GPIO_Pin_5,那么 pinpos = 5,pos = pinpos << 2 = 20;
// pinmask = 0000 0000 1111 0000 0000 0000 0000 0000 1111 的位置正好是 CNF5 MODE5 的位置所在;
// ~ pinmask = FFFF FFFF 0000 FFFF ........ ; tmpreg = tmpreg & ~pinmask = 0x 44 44 00 44 44 44 44 44
/* Write the mode configuration in the corresponding bits */
tmpreg |= (currentmode << pos); // 把 currentmode 数据 写入到 tmpreg 的 数据00 位置中;
/* Reset the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
GPIOx->BRR = (((uint32_t)0x01) << pinpos);
// 下拉输入模式 与 上拉输入模式 ,CNF【1:0】数据都是 1 0 ;以相应ODR输出数据 来区分;ODR相应位为 0 下拉输入 ;ODR相应位为 1 上拉输入;
// 向BRR寄存器相应位写 1 ,使相应ODR 输出 0
}
else
{
/* Set the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
GPIOx->BSRR = (((uint32_t)0x01) << pinpos); // 向BSRR寄存器相应位写 1 ,使相应ODR 输出 1
}
}
}
}
GPIOx->CRL = tmpreg;
}
/*---------------------------- GPIO CRH Configuration ------------------------*/
/* Configure the eight high port pins */
if (GPIO_InitStruct->GPIO_Pin > 0x00FF)
{
tmpreg = GPIOx->CRH;
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
{
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 */
pinmask = ((uint32_t)0x0F) << pos;
tmpreg &= ~pinmask;
/* Write the mode configuration in the corresponding bits */
tmpreg |= (currentmode << pos);
/* Reset the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));
}
/* Set the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));
}
}
}
GPIOx->CRH = tmpreg;
}
}
|
|