我们实现一个流水灯的操作,且用寄存器来初始化GPIO口
使用寄存器必须查询对应GPIO 和时钟的地址,才能进行操作
查询结果如下
GPIOA 对应地址为 0x4001 0800
GPIOB 对应地址为 0x4001 0C00
GPIOC 对应地址为 0x4001 1000
一个32位的寄存器当然只能配置8个IO口
所以这里还分为高位寄存器 CRH 只能配置 p0-p7
低位寄存器 CRL 只能配置 p8-p15
所以必须提前想好自己对应的接口的寄存器不同
高位寄存器有地址偏移 为 0x04 而低位寄存器没有这个设置
如 我要配置 GPIO A_P_5 明显 这是一个低位口 则地址为0x40010800
若 我要配置 GPIO A_P_11 明显 这是一个高位口 则地址为0x40010804
而在配置GPIO 之前,需要先配置我们的对应时钟使能
查询时钟地址表可以得:
时钟地址为0x4002 1000
在时钟使能寄存器中可以看到其地址偏移为0x18
所以我们使能时钟地址为0x40021018
我们也是用ODR 来直接控制对应得接口高低电平,对应1为高 0
为低 非常方便。
所以,我们可以直接开始配置初始化了,代码如下。
#define RCC_AP2ENR *((unsigned volatile int*)0x40021018)
// 找到时钟使能寄存器映射基地址为0x40021018
//我们可以清楚的看到使能时钟的表上 标明 第二位是 IOPA/EN 第三位是 IOPB/EN 第四位是 IOPC/EN
//所以直接进行左移就可以实现时钟设置
//先要使用寄存器来初始化IO口 才能开始程序
#define GPIOA_CRL *((unsigned volatile int*)0x40010800)// 经过查询 gpio A 口为 0X4001 0800 使用crl不需要偏移
#define GPIOA_ODR *((unsigned volatile int*)0x4001080C)//我们使用odr来直接控制接口输出,可读可写 输出1为高反之为低
#define GPIOB_CRL *((unsigned volatile int*)0x40010C00)//经过查询 GPIO B 口为 0X4001 0C00
#define GPIOB_ODR *((unsigned volatile int*)0x40010C0C)
#define GPIOC_CRH *((unsigned volatile int*)0x40011004)//经过查询 GPIO C口为 0X4001 1000 但是这里是1004
//是因为使用的CRH要偏移四位
#define GPIOC_ODR *((unsigned volatile int*)0x4001100C)
初始化结束后我们就要开始配置对应得的O口和时钟了,具体看你想要用那几个口,按需配置。
先看时钟
RCC_AP2ENR|=1<<2; //APB2-GPIOA时钟使能 具体为什么左移可以看下面的注释
RCC_AP2ENR|=1<<3; //APB2-GPIOB时钟使能
RCC_AP2ENR|=1<<4; //APB2-GPIOC时钟使能
为什么要进行左移?左移多少位?
我们通过查询使能时钟寄存器表可以得知
第一位是保留位 后面 2 3 4 5 位依次对应着 IO-A IO-B IO-C IO-D 的对应时钟使能
注意stm32 不像c51 就一个时钟,一动就全部启动 stm32 可以按照配置来启动需要的时钟,明显这可以大幅减少耗能。
接下来需要设置对应的接口位置,将其清零和配置输出模式。
一般我们使用 推挽输出模式 来进行配置 如下
GPIOA_CRL&=0xFF0FFFFF; //设置位 清零 设置位和 你的IO口要一一对应
GPIOA_CRL|=0x00200000; //PA5推挽输出 这边由于使用的是CRL相当于是从第0位开始数起,自然这第6个就是pa5
GPIOA_ODR|=1<<5; //设置初始灯为亮
GPIOC_CRH&=0xFF0FFFFF; //配置pc13 口 点亮内置led灯
GPIOC_CRH|=0x00200000;
GPIOC_ODR|=1<<13;
GPIOB_CRL&=0xFFFFFF0F; //设置位 清零
GPIOB_CRL|=0x00000020; //PB1推挽输出 这边定位和上面一样,不再赘述
GPIOB_ODR|=1<<1; //设置初始灯为灭
GPIOC_CRH&=0xF0FFFFFF; //设置位 清零
GPIOC_CRH|=0x02000000; //PC14推挽输出 这边由于是CRH 高位开始 就是从第七位开始 所以这里的第7位就是第14个口
GPIOC_ODR|=1<<14; //设置初始灯为灭
注意在设置推挽输出接口的位置上 要根据你是高位寄存器还是低位寄存器 来判断对应接口的位置
如 我们高位寄存器是从p8开始到p15所以高位寄存器的第一位就是第八个接口
反过来讲 低位寄存器 的最高位 也就是第7个接口 至于清零,需要和你配置的接口对应就行了,注意细节。
全部配置完过后就直接使用ODR来进行操作就行了,直接左移1 or 0 到对应的接口位置上,接口位置就是你在上面配置的位置。
如下
GPIOA_ODR=0x1<<5;//PA5高电平
Delay_ms(1000);
GPIOA_ODR=0x0<<5;//PA5低电平 直接使用odr 进行左移的高低电平转换就行了
使用方法非常简单。
注意:这里我们需要配置的pc13接口的内置led灯是低电平点亮,注意顺序就行。
然后我们写完程序过后就直接使用flymcu烧录进去
我这里使用的接口是ch340 注意对应接口不要接错了, 还有boot1 和boot0的短接问题,烧录的时候boot0 短接3.3v boot1接地
执行程序时 boot0和boot1都要接地。
每次烧录都要重新插拔接口。
最后硬件结果如下
参考文献如下:
- https://blog.youkuaiyun.com/sunjiajiang/article/details/9031033
- https://blog.youkuaiyun.com/zxp_124/article/details/120868624