1.我们继续打开这个函数,看看第二个变量
我们发现这第二个变量的的结构体里是这个东西,刚好事一个基本的配置GPIO所需要的变量。
uint16_t GPIO_Pin; //无符号型16位变量 代表引脚号
GPIOSpeed_TypeDef GPIO_Speed;//结构体类型 代表速度
GPIOMode_TypeDef GPIO_Mode; 结构体类型 代表引脚模式
2.继续打开第二个变量结构体里的枚举类型(看他们如何赋值)
①这是GPIO_Pin的赋值选择
②这是GPIO_Speed的赋值选择
③这是GPIO_Mode的赋值选择
④我们挑选GPIO_Mode的赋值选择函数来讲解
typedef enum
{ xxxx
}GPIOMode_TypeDef;
//重命名一个枚举类型,他的名字是GPIOMode_TypeDef,他的取值范围只能是大括号{}里的xxx;
这样就限定了这个GPIOMode_TypeDef的取值只能是GPIO的这8种模式。
同理GPIO_Speed的取值范围也用了枚举变量enum去限制
GPIO_Pin的取值则是用了宏定义的方式定义了一大堆数组。
3.现在我们假设这样配置一下GPIO
这个函数是配置PB5为推挽输出输出,速率为50Mhz
3.1把他们赋值的值找出来看是多少
ps:(由于枚举变量的性质,虽然没赋值,GPIO_Speed_50MHz=3 )
3.2把他们的赋值值化成2进制。
GPIO_Pin_5=((uint16_t)0x0020)=0000 0000 0010 0000
GPIO_Mode_Out_PP=0x10=0000 0000 0001 0000
GPIO_Speed_50MHz=3=0000 0000 0000 0000 0000 0000 0000 0011
3.2现在我们打开寄存器手册和结构体的函数情况
这个函数是实现了GPIO_Pin_5 GPIO_Mode_Out_PP GPIO_Speed_50MHz这三个值得移位拼接,c语言一般的应该能看懂,不多赘述,说不清。
总之最后拼接出来的tmpreg值=0000 0000 0011 0000 0000 0000 0000 0000
而GPIOx->CRL = tmpreg;就刚好是对GPIOA的寄存器地址里写入了0000 0000 0011 0000 0000 0000 0000 0000 这个值。对照手册,刚好是对寄存器进行了50MHZ推完输出模式
这样就完成了库函数和寄存器之间的转化了。
关于这个函数实现我没说清楚,也说不清。总之就是将这几个值<<>>&|操作把他们合并在一起,如果认真看看这个函数就会发现是个很精妙的算法。
诸君共勉,加油!