ST提供的库函数对开发stm32很有帮助,但是方便的同时,库函数就是个黑箱,总让人不够放心
(以前用了个读ms5611的库,居然等传感器读数的时候用的是延时函数!这要是上天了岂不是要掉下来)
这次对最常用的GPIO_Init() 做个简单的探究并简化
原库函数内容就不贴了,在stm32f10x_gpio.c中可以找到,以下是库自带的帮助文件相关内容
其主要作用就是对GPIOx用GPIO_InitStruct这个初始化结构体去初始化,很傻瓜得填进去就可以初始化GPIO了
接下来
初始化结构体主要内容就是,IO脚,IO模式,IO速度,这里我们自己定义一个初始化结构体
typedef struct {
uint16_t pin;
GPIO_Mode mode;
GPIO_Speed speed;
} gpio_config_t;
以下是简化的初始化函数:(相关寄存器请自行查阅参考手册,对,就是七百多页那个)
void gpioInit(GPIO_TypeDef *gpio, gpio_config_t *config)
{
uint32_t pinpos;
for (pinpos = 0; pinpos < 16; pinpos++)
{
//选定设置IO口
if (config->pin & (0x1 << pinpos))
{
// 根据引脚选择CRL还是CRH
__IO uint32_t *cr = &gpio->CRL + (pinpos / 8);
// 留下最后4位
uint32_t currentmode = config->mode & 0x0F;
// 计算配置该IO口的4位在CRx中的位置
uint32_t shift = (pinpos % 8) * 4;
// 读出CRx的值
uint32_t tmp = *cr;
// 若为输出模式,设置速度
if (config->mode & 0x10)
currentmode |= config->speed;
// 清零要设置的4位
tmp &= ~(0xF << shift);
// 设置
tmp |= currentmode << shift;
*cr = tmp;
// 上拉输出和下拉输出的设置
if (config->mode == Mode_IPD) {
gpio->ODR &= ~(1U << pinpos);
} else if (config->mode == Mode_IPU) {
gpio->ODR |= (1U << pinpos);
}
}
}
}
参考资料:https://github.com/multiwii/baseflight