第8章 自己写库——构建库函数雏形

什么是库函数?

通过函数和宏封装配置寄存器

外设结构体

我们可以定义一种外设结构体结构体的地址等于外设的基地址结构体的成员等于寄存器成员的排列顺序跟寄存器的顺序一样

Volatile类型

volatile表示易变的变量,防止编译器优化,要求程序运行是不要从缓存中取值,而是去数据最原始的位置重新取值。

GPIO 初始化结构体

*定义GPIO_InitTypeDef 结构体类型

typedef struct
 {
uint16_t GPIO_Pin; /*!< 选择要配置的GPIO引脚 */

uint16_t GPIO_Speed; /*!< 选择GPIO引脚的速率 */

uint16_t GPIO_Mode; /*!< 选择GPIO引脚的工作模式 */
} GPIO_InitTypeDef;

枚举类型

* /GPIO输出速率枚举定义
 */
 typedef enum
 {
 GPIO_Speed_10MHz = 1, // 10MHz (01)b , 定义枚举的初始值从1 开始
 GPIO_Speed_2MHz, // 2MHz (10)b
 GPIO_Speed_50MHz // 50MHz (11)b
 } GPIOSpeed_TypeDef;

枚举是int 类型, 就是给枚举元素标号, 默认是从0开始, 但是也可以设置初始值,比如上例中定义从1开始。 后续的两个枚举成员没有定义具体值,因此会使用默认的连续标号, 即2 和3 .

*GPIO 工作模式定义

 */typedef enum

{
GPIO_Mode_AIN = 0x0, // 模拟输入 (0000 0000)b
GPIO_Mode_IN_FLOATING = 0x04, // 浮空输入 (0000 0100)b
GPIO_Mode_IPD = 0x28, // 下拉输入 (0010 1000)b
GPIO_Mode_IPU = 0x48, // 上拉输入 (0100 1000)b

GPIO_Mode_Out_OD = 0x14, // 开漏输出 (0001 0100)b
GPIO_Mode_Out_PP = 0x10, // 推挽输出 (0001 0000)b
GPIO_Mode_AF_OD = 0x1C, // 复用开漏输出 (0001 1100)b
GPIO_Mode_AF_PP = 0x18 // 复用推挽输出 (0001 1000)b
} GPIOMode_TypeDef;

枚举是int 类型, 就是给枚举元素标号,除了按照初始值顺序编号外, 还可以指定具体的枚举值。如上例。

GPIO 初始化结构体赋值

 GPIO_InitTypeDef GPIO_InitStructure;

/* GPIO端口初始化 */
/*选择要控制的GPIO引脚*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
/*设置引脚模式为输出模式*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚的输出类型为推挽输出*/
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO 初始化函数

代码清单8-13 GPIO初始化函数
1 /**
2 *函数功能:初始化引脚模式
3 *参数说明:GPIOx,该参数为GPIO_TypeDef类型的指针,指向GPIO端口的地址
4 * GPIO_InitTypeDef:GPIO_InitTypeDef结构体指针,指向初始化变量
5 */
6 void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
7 {
8 uint32_t currentmode =0x00,currentpin = 0x00,pinpos = 0x00,pos = 0x00;

9 uint32_t tmpreg = 0x00, pinmask = 0x00;
10 
11 /*———————————————— GPIO 模式配置 ————————————————*/
12 //把输入参数GPIO_Mode的低4位暂存在currentmode
13 currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) &((uint32_t)0x0F);
16 //bit4是1表示输出,bit4是0则是输入
17 //判断bit4是1还是0,即首先判断是输入还是输出模式
18 if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) &
19 ((uint32_t)0x10))!= 0x00)
20 {
21 //若是输出模式,则要设置输出速度
22 currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;
23 }


24 /*——————————GPIO CRL 寄存器配置 CRL寄存器控制低8位IO———————*/
25 //配置端口低8位,即Pin0~Pin7
26 if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF))!= 0x00)
28 {
29 //先备份CRL寄存器的值
30 tmpreg = GPIOx->CRL;
31 
32 //循环,从Pin0开始配对,找出具体的Pin
33 for (pinpos = 0x00; pinpos < 0x08; pinpos++)
34 {
35 //若pos的值为1,左移pinpos位
36 pos = ((uint32_t)0x01) << pinpos;
37 
38 //令pos与输入参数GPIO_PIN做位与运算
39 currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;

40 
41 //若currentpin=pos,则找到使用的引脚
42 if (currentpin == pos)
43 {
44 //pinpos的值左移两位(乘以4),因为由寄存器中4位配置一个引脚
45 pos = pinpos << 2;
46 //把控制这个引脚的4个寄存器位清零,其他寄存器位不变
47 pinmask = ((uint32_t)0x0F) << pos;
48 tmpreg &= ~pinmask;
49 
50 //向寄存器写入将要配置的引脚模式
51 tmpreg |= (currentmode << pos);
52 
53 //判断是否为下拉输入模式
54 if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
55 {
56 //若为下拉输入模式,引脚默认置0,对BRR寄存器写1可对引脚置0
57 GPIOx->BRR = (((uint32_t)0x01) << pinpos);
58 }
59 else
60 {
61 //判断是否为上拉输入模式
62 if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
63 {
64 //若为上拉输入模式,引脚默认值为1,对BSRR寄存器写1可//对引脚置1
65 GPIOx->BSRR = (((uint32_t)0x01) << pinpos);
66 }
67 }
68 }
69 }
70 //把前面处理后的暂存值写入CRL寄存器中
71 GPIOx->CRL = tmpreg;

72 }


73 /*——————————GPIO CRH 寄存器配置 CRH寄存器控制高8位IO—————————*/
74 //配置端口高8位,即Pin8~Pin15
75 if (GPIO_InitStruct->GPIO_Pin > 0x00FF)
76 {
77 //先备份CRH寄存器的值
78 tmpreg = GPIOx->CRH;
79 
80 //循环,从Pin8开始配对,找出具体的Pin
81 for (pinpos = 0x00; pinpos < 0x08; pinpos++)
82 {
83 pos = (((uint32_t)0x01) << (pinpos + 0x08));
84 
85 //pos与输入参数GPIO_PIN做位与运算
86 currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos);
87 
88 //若currentpin=pos,则找到使用的引脚
89 if (currentpin == pos)
90 {
91 //pinpos的值左移两位(乘以4),因为由寄存器中4位配置一个引脚
92 pos = pinpos << 2;
93 
94 //把控制这个引脚的4个寄存器位清零,其他寄存器位不变
95 pinmask = ((uint32_t)0x0F) << pos;
96 tmpreg &= ~pinmask;
97 
98 //向寄存器写入将要配置的引脚的模式
99 tmpreg |= (currentmode << pos);
100 
101 //判断是否为下拉输入模式
102 if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)

103 {
104 //若为下拉输入模式,引脚默认置0,对BRR寄存器写1可对引脚置0
105 GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));
106 }
107 //判断是否为上拉输入模式
108 if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
109 {
110 //若为上拉输入模式,引脚默认值为1,对BSRR寄存器写1可对引脚置1
111 GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));
112 }
113 }
114 }
115 //把前面处理后的暂存值写入CRH寄存器中
116 GPIOx->CRH = tmpreg;
117 }
118 }

GPIO 操作的具体流程

创建GPIO初始化结构体()--》初始话时钟是能寄存器,初始GPIO初始化结构体-》使用bitset 等函数操作GPIO

第8章学习总结

书本中对MODEy寄存器,对输出模式的定义有错误。只有MODE有=00的时候是输入模式。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值