一.原理学习
学习和理解STM32F103系列芯片的地址映射和寄存器映射原理;了解GPIO端口的初始化设置三步骤(时钟配置、输入输出模式设置、最大速率设置)。
1.寄存器
(1)寄存器的含义
寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。其实寄存器就是一种常用的时序逻辑电路,但这种时序逻辑电路只包含存储电路。寄存器的存储电路是由锁存器或触发器构成的,因为一个锁存器或触发器能存储1位二进制数,所以由N个锁存器或触发器可以构成N位寄存器。寄存器是中央处理器内的组成部分。寄存器是有限存储容量的高速存储部件,它们可用来暂存指令、数据和位址。
(2)寄存器具有的四个功能
①清除数码:将寄存器里的原有数码清除。 ②接收数码:在接收脉冲作用下,将外输入数码存入寄存器中。 ③存储数码:在没有新的写入脉冲来之前,寄存器能保存原有数码不变。 ④输出数码:在输出脉冲作用下,才通过电路输出数码。 仅具有以上功能的寄存器称为数码寄存器;有的寄存器还具有移位功能,称为移位寄存器。
2.地址映射和寄存器映射原理
通过查看数据手册找到某个寄存器的地址。 手册中没有直接给出所有的寄存器的地址,需要稍加计算。STM32给不同的寄存器分配了不同的地址,有点像划分了片区。在《STM32中文参考手册_V10》的第28页,有不同寄存器的地址范围。 假如我们想读取PB3引脚的电平,需要查询PB3的地址。
第一步
,PB3是在GPIOB端口内,所以要找到GPIOB的基地址 也就是找到GPIOB的地址范围。结论是,所有GPIOB相关的寄存器,地址都在0x4001 0C00到0x4001 0FFF范围内。
第二步
找到端口输入寄存器的地址偏移,找到存储数据的那个屋子,结论是0x4001 0C00+8 = 0x4001 0C08
第三步
找到知道数据的那个人,PB3的数据位于从右往左数第4位。IDR3。 经过这三步查找,我们可以做出以下结论: PB3的输入数据位于0x4001 0C08这个地址上,这个地址上存放数据的右起第4个位就是PB3引脚对应的高低电平。 直接访问这个地址: unsigned int *pGPIOB_IDR = (unsigned int *)0x40010C08; unsigned char PB3 = *pGPIOB_IDR & 0x8;//取出从右往左数的第4位
3、GPIO端口的初始化设置三步骤(时钟配置、输入输出模式设置、最大速率设置)
本次实验采用GPIOA、B、C三个端口。该三个端口都属于APB2总线
1.找到时钟使能寄存器映射基地址
2.使能对应端口时钟
#define RCC_APB2ENR *((unsigned volatile int*)0x40021018)
RCC_APB2ENR|=1<<2|1<<3|1<<4;
输入输出模式和输出速率设置
本次实验采用通用推挽输出模式,最高输出时钟频率2Mhz。分别用到A4、B5、C14三个引脚。其中A4、B5属于端口配置低寄存器偏移地址为0x00,C13属于端口配置高寄存器偏移地址为0x04。
二、假设你手中已有 STM32最小系统核心板(STM32F103C8T6)+面板板+3只红绿蓝LED,并搭建了电路,分别GPIOA-5、GPIOB-9、GPIOC-14 这3个引脚上控制LED灯(最高时钟2Mhz),轮流闪烁,间隔时长1秒。
1.流水灯原理
本次实验采用三个灯实现,亮灯状态用1表示,灭灯状态用0表示。 初始状态为0 0 0, 状态一为1 0 0 状态二为0 1 0 状态三为0 0 1 状态三结束后继续进入状态一,一直循环达到流水灯效果。
2.创建新项目
1.找到stm32f103cB
2.点击system core,进入SYS,在debug下选择serial wire:
3.配置时钟,进入上面的rcc,有两个时钟,一个是hse和lse,我们要用是GPIO接口,而这些接口都在APB2里:
接下来观察时钟架构,APB2总线的时钟由hse控制,同时在这个界面得把PLLCLK右边选上:
4.将hse那里设为Crystal/Ceramic Resonator:
5.接下来就是点击相应的引脚设置输出寄存器了,就是output那一项,一共选了三个,是PA4,PB5,PC14:修改为如图所示
6.点击project manager,配置好自己的路径和项目名,然后IDE那项改为MDK-ARM:
7.进入 code generate界面,选择生成初始化.c/.h文件,后面点击generate code,选择open project,然后就到KEIL5了:
8.进入 code generate界面,选择生成初始化.c/.h文件,后面点击generate code,选择open project,然后就到KEIL5了:
代码
打开main.c文件,滑倒主函数那一部分:
(1)将下面代码放入主函数中(替代里面的内容)
SystemClock_Config();
MX_GPIO_Init();
while (1)
{
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_SET);
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_SET);
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_RESET);
HAL_Delay(1000);
}
随后生成hex文件。 连接线路 根据设计的程序连接电路: 对于USB转TTL模块和stm32f103c8t6连接: GND — GND 3v3 — 3v3 TXD — A10 RXD — A9
红——B5 红——C14 黄——A4 烧录文件。笔者使用的是flymcu 记得取消勾选字节区和勾选编程后执行,不然会出现灯不亮的情况(文件没有烧录成功)。 大致效果如上。
|