寄存器是 CPU 内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。其实寄存器就是一种常用的 时序逻辑电路 ,但这种时序逻辑电路只包含存储电路。 寄存器的存储电路是由锁存器或触发器构成的,因为一个锁存器或触发器能存储1位二进制数,所以由N个 锁存器 或触发器可以构成N位寄存器。寄存器是 中央处理器 内的组成部分。寄存器是有限存储容量的高速存储部件,它们可用来暂存指令、数据和位址。在计算机领域,寄存器是CPU内部的元件,包括 通用寄存器 、专用寄存器和控制寄存器。寄存器拥有非常高的读写速度,所以在寄存器之间的数据传送非常快。
存放数据的寄存器是最好理解的,如果你需要读取一个数据,直接到这个寄存器所在的地方来问问他,数据是多少就行了。问寄存器这个动作,叫做访问寄存器。不同的数据会存放在不同的寄存器,例如引脚PA2与PB8的高低电平数据(1或0)肯定放在不同的寄存器里,那么怎么区分不同的寄存器呢?通过地址,不同的寄存器有不同的地址
**所以需要找到其地址,怎么找到某个寄存器的地址?查看数据手册。**在简单了解寄存器后,我们开始配置
想要配置时钟首先要访问其寄存器,找到地址。
时钟控制名字叫做RCC,属于AHB总线,查看数据手册如下:
得出复位和时钟控制RCC的地址从0x4002 1000开始
手册RCC_APB2ENR,位3是IOPBEN,名字是IO端口B时钟使能,就是我们想要的。把RCC_APB2ENR的位3赋值为1,就是开启GPIOB时钟。
//----------------APB2使能时钟寄存器 ---------------------
#define RCC_APB2ENR *((unsigned volatile int*)0x40021018)
RCC_APB2ENR|=1<<2|1<<3|1<<4; //APB2-GPIOA、GPIOB、GPIOC外设时钟使能
本次实验使用GPIOA-5、GPIOB-9、GPIOC-14 这3个引脚控制LED灯,GPIO是属于APB2的。
同理,也要访问其地址。
结论是,
所有GPIOA相关的寄存器,都住在0x4001 0800到0x4001 0BFF范围内。
所有GPIOB相关的寄存器,都住在0x4001 0C00到0x4001 0FFF范围内。
所有GPIOC相关的寄存器,都住在0x4001 1000到0x4001 13FF范围内。
分别用到A4、B5、C14三个引脚。其中A4、B5属于端口配置低寄存器偏移地址为0x00,C13属于端口配置高寄存器偏移地址为0x04。
相应端口配置器GPIOA_CRL地址为GPIOA的基址+上偏移量
//----------------GPIOA配置寄存器 -----------------------
#define GPIOA_CRL *((unsigned volatile int*)0x40010800)
//----------------GPIOB配置寄存器 -----------------------
#define GPIOB_CRL *((unsigned volatile int*)0x40010C00)
//----------------GPIOC配置寄存器 -----------------------
#define GPIOC_CRH *((unsigned volatile int*)0x40011004)
我们需要的是输出高低电平,所以要设置为输出。输出模式又有好几种输出:
推挽输出:可以输出高,低电平,连接数字器件;推挽结构一般是指两个三极管分别受两互补信号的控制,总是在一个三极管导通的时候另一个截止。
开漏输出:输出端相当于三极管的集电极,要得到高电平状态需要上拉电阻才行,适合于做电流型的驱动,其吸收电流的能力相对强(一般20ma以内)。
开漏是需要外接上拉电阻才可以输出高电平的,这里并不适合。所以需要设置为推挽输出,没有复用,输出速度按要求设置为2Mhz
GPIOA_CRL&=0xFFF0FFFF; //设置位 清零
GPIOA_CRL|=0x00020000; //PA4推挽输出,把第19、18、17、16位变为0010
GPIOB_CRL&=0xFF0FFFFF; //设置位 清零
GPIOB_CRL|=0x00200000; //PB5推挽输出,把第23、22、21、20变为0010
GPIOC_CRH&=0xFF0FFFFF; //设置位 清零
GPIOC_CRH|=0x00200000; //PC14推挽输出,把第23、22、21、20变为0010
本次实验采用三个灯实现,亮灯状态用1表示,灭灯状态用0表示。
初始状态为0 0 0,
状态一为1 0 0
状态二为0 1 0
状态三为0 0 1
状态三结束后继续进入状态一,一直循环达到流水灯效果。
点击【project】->[New…】
选择STM32F103C8开发板
在source group里创建led.c,选择【Add New Item to Group… …】
添加代码文件,设置名称
注意项目结构,使用的引脚是PA7,PB9,PC15
代码如下:
#include "stm32f10x.h"
//----------------APB2使能时钟寄存器 ---------------------
#define RCC_APB2ENR *((unsigned volatile int*)0x40021018)
//----------------GPIOA配置寄存器 -----------------------
#define GPIOA_CRL *((unsigned volatile int*)0x40010800)
#define GPIOA_ODR *((unsigned volatile int*)0x4001080C)
//----------------GPIOB配置寄存器 -----------------------
#define GPIOB_CRL *((unsigned volatile int*)0x40010C00)
#define GPIOB_ODR *((unsigned volatile int*)0x40010C0C)
//----------------GPIOC配置寄存器 -----------------------
#define GPIOC_CRH *((unsigned volatile int*)0x40011004)
#define GPIOC_ODR *((unsigned volatile int*)0x4001100C)
//延时函数
void Delay()
{
u32 i=0;
for(;i<5000000;i++);
}
int main(void)
{
RCC_APB2ENR|=1<<2|1<<3|1<<4; //APB2-GPIOA、GPIOB、GPIOC外设时钟使能
GPIOA_CRL&=0xFFF0FFFF; //设置位 清零
GPIOA_CRL|=0x00020000; //PB5推挽输出
GPIOA_ODR&=~(1<<4); //设置初始灯为灭
GPIOB_CRL&=0xFF0FFFFF; //设置位 清零
GPIOB_CRL|=0x00200000; //PB5推挽输出
GPIOB_ODR&=~(1<<5); //设置初始灯为灭
GPIOC_CRH&=0xF0FFFFFF; //设置位 清零
GPIOC_CRH|=0x02000000; //PB5推挽输出
GPIOC_ODR&=~(1<<14); //设置初始灯为灭
while(1){
//A灯
GPIOA_ODR|=1<<4; //PB5高电平
Delay();
GPIOA_ODR&=~(1<<4); //PB5低电平,因为是置0,所以用按位与
//B灯
GPIOB_ODR|=1<<5; //PB5高电平
Delay();
GPIOB_ODR&=~(1<<5); //PB5低电平,因为是置0,所以用按位与
//C灯
GPIOC_ODR|=1<<14; //PB5高电平
Delay();
GPIOC_ODR&=~(1<<14); //PB5低电平,因为是置0,所以用按位与
}
}
对于USB转TTL模块和stm32f103c8t6连接
1、TXD-接 PA10/USART1_RX
2、RXD-接 PA9/USART1_TX
3、3V3 GND 接供电,将BOOT0接3V3后再供电,即可进入下载模式。
在build之后会在object文件夹下有对应的hex文件生成
连接到电脑,打开mcuisp,上传HEX文件到stm32f103c8t6上:
首先读取器件信息
然后开始编程
程序烧录完毕
根据题目要求,使用GPIOB,GPIOC,GPIOD端口来控制LED灯,在查询C8T6数据手册后,选用了PA7,PB9,PC15管脚分别连接红绿黄三种颜色的灯,实物图如下:
让 STM32 一按复位键就开始运行代码,则需要配置 BOOT0 为 0,在将C8T6连接到电路板之前,一定要先将BOOT0置位0,否则电路无效。
流水灯成功运行!
通过这次使用C语言,在Keil 5上编译生成HEX文件并使用STM32寄存器方式进行的点亮LED流水灯实验,让我有了一番不一样的体验,虽然在过程中遇到了一些硬件上的问题,但询问同学后还是得以解决,让我明白了在仿真器上操作和使用硬件进行操作还是存在区别的,使用硬件进行操作的过程中会学到更多的基础知识,能进一步的学习和理解STM32F103系列芯片的地址映射和寄存器映射原理,了解GPIO端口的初始化设置三步骤,总之收获很大。
https://blog.csdn.net/weixin_47554309/article/details/120810913
https://blog.csdn.net/geek_monkey/article/details/86293880