typedef enum//自定义的软件实现,限定了模式的取值
{
GPIO_Mode_AIN = 0x0, //模拟输入(0000 0000)b
GPIO_Mode_IN_FLOATING = 0x04,//浮空输入(00000100)b
GPIO_Mode_IPD = 0x28, //下拉输入(0010 1000)b
GPIO_Mode_IPU = 0x48, //上拉输入(0100 1000)b
GPIO_Mode_Out_OD =0x14, //开漏输出(00010100)b
GPIO_Mode_Out_PP = 0x10, //推挽输出(0001 0000)b
GPIO_Mode_AF_OD = 0x1C, //复用开漏输出(0001 1100)b
GP1O_Mode_AF_PP = 0x18 //复用推挽输出(0001 1000)b
}GPIOMode_TypeDef;
typedef struct{//用于模式配置的结构体
uint16_t GPIO_Pin; //要配置的引脚
uint16_t GPIO_Speed; //速率,只有输出模式使用
uint16_t GPIO_Mode; //模式
}GPIO_InitTypeDef;
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)//初始化GPIO
{
uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;
uint32_t tmpreg = 0x00, pinmask = 0x00;
/* GPIO 模式配置 */
currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);//把输入参数GPIO_Mode的低4为暂存
if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)//bit4如果是1为输出模式,0为输入模式
{
/* 输出模式 */
currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;;//配置速度
}
/* GPIO CRL 寄存器配置,CRL控制GPIO某一端口的低8位 */
if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)
{
tmpreg = GPIOx->CRL; //暂存CRL的值
for (pinpos = 0x00; pinpos < 0x08; pinpos++)//寻找对应引脚
{
pos = ((uint32_t)0x01) << pinpos;
/* Get the port pins position */
currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
if (currentpin == pos) //找到了对应引脚
{
pos = pinpos << 2; //乘4,因为CRL中每4位配置一个引脚
pinmask = ((uint32_t)0x0F) << pos;
tmpreg &= ~pinmask; //把这几个位先清零
tmpreg |= (currentmode << pos);//写入模式的值
//GPIO_Mode_IPD和GPIO_Mode_IPU是自定义的宏,可以自己设置
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)//判断是上拉还是下拉
{ //下拉
GPIOx->BRR = (((uint32_t)0x01) << pinpos);//将BRR最低位置1
}
else//上拉
{
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
GPIOx->BSRR = (((uint32_t)0x01) << pinpos);//将BSRR最低位置1
}
}
}
}
GPIOx->CRL = tmpreg;//写入寄存器
}
/* GPIO CRH 寄存器配置 ,过程和CRL配置基本相同*/
if (GPIO_InitStruct->GPIO_Pin > 0x00FF)
{
tmpreg = GPIOx->CRH;
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
{
pos = (((uint32_t)0x01) << (pinpos + 0x08));
currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos);
if (currentpin == pos)
{
pos = pinpos << 2;
pinmask = ((uint32_t)0x0F) << pos;
tmpreg &= ~pinmask;
tmpreg |= (currentmode << pos);
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));
}
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));
}
}
}
GPIOx->CRH = tmpreg;
}
}
int main()
{
GPIO_InitTypeDef GPIO_Inits;
//打开GPIOC的时钟
RCC->APB2ENR |=((1)<<4);
//在此,GPIO模式的配置也实现了屏蔽寄存器,在不知道寄存器取值的情况下可以编程,逐步将寄存器编程进化至固件库编程
GPIO_Inits.GPIO_Pin=GPIO_Pin_8; //对第8个引脚进行配置
GPIO_Inits.GPIO_Mode=GPIO_Mode_Out_PP; //推挽输出模式
GPIO_Inits.GPIO_Speed=SPIO_Speed_50MHZ;//推挽输出50mhz
GPIO_Init(GPIOC,&GPIO_Inits);//初始化GPIOC
while(1)
{
GPIO_ResetBits(GPIOC,GPIO_Pin_8);//开启LED
delay(0x10000);
GPIO_SetBits(GPIOC,GPIO_Pin_8);//关闭LED
delay(0x10000);
}
}
void delay(uint32_t time)
{
while(time--)
;
}`
|
原文链接:https://blog.csdn.net/qq_42424228/article/details/103674875