STM32F103使用寄存器方式点亮LED流水灯

1 STM32F103系列芯片的地址映射和寄存器映射原理

1.1 什么是寄存器

1.1.1 基本含义

寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。寄存器就是一种常用的时序逻辑电路,但这种时序逻辑电路只包含存储电路。寄存器的存储电路是由锁存器或触发器构成的。寄存器是中央处理器内的组成部分。寄存器是有限存储容量的高速存储部件,它们可用来暂存指令、数据和位址。

1.1.2 基本概念

寄存器最起码具备以下4种功能。
①清除数码:将寄存器里的原有数码清除。
②接收数码:在接收脉冲作用下,将外输入数码存入寄存器中。
③存储数码:在没有新的写入脉冲来之前,寄存器能保存原有数码不变。
④输出数码:在输出脉冲作用下,才通过电路输出数码。
仅具有以上功能的寄存器称为数码寄存器;有的寄存器还具有移位功能,称为移位寄存器。

1.2 地址映射和寄存器映射原理

以STM32为例,操作硬件本质上就是操作寄存器。在存储器片上外设区域,四字节为一个单元,每个单元对应不同的功能。当我们控制这些单元时就可以驱动外设工作,我们可以找到每个单元的起始地址,然后通过C 语言指针的操作方式来访问这些单元。但若每次都是通过这种方式访问地址,不好记忆且易出错。这时我们可以根据每个单元功能的不同,以功能为名给这个内存单元取一个别名,这个别名实质上就是寄存器名字。给已分配好地址(通过存储器映射实现)的有特定功能的内存单元取别名的过程就叫寄存器映射。

1.3 STM32系统架构

STM32 芯片是已经封装好的成品,主要由内核和片上外设组成。若与电脑类比,内核与外设就如同电脑上的 CPU 与主板、内存、显卡、硬盘的关系

  1. 四个驱动单元(CUP)
    Cortex™-M3内核DCode总线
    Cortex™-M3内核系统总线System
    通用DMA1
    通用DMA2

  2. 四个被动单元(外设)
    内部SRAM
    内部闪存存储器FLASH
    FSMC
    AHB到APB的桥,它连接所有的APB外设

  3. 驱动单元

    • ICode 总线
      ICode 中的 I 表示 Instruction,即指令。内核通过ICode 总线读取内部FLASH代码指令来执行程序.。

    • DCode 总线
      DCode 中的 D 表示 Data,即数据,那说明这条总线是用来取数的。因为数据可以被 Dcode 总线和 DMA 总线访问(向flash,SRAM,或外设数据寄存器里面取数据),所以为了避免访问冲突,在取数的时候需要经过一个总线矩阵来仲裁,决定哪个总线在取数,取到的数据可以暂存在Cortex™-M3内核里面的寄存器在进行处理。

    • 系统总线System
      系统总线主要是访问外设的寄存器,我们通常说的寄存器编程,即读写寄存器都是通过这根系统总线来完成的。

    • DMA 总线
      DMA 总线与DCode总线一样主要是用来传输数据,但Dcode总线传输数据要占用内核(cpu)的资源,而DMA总线相当于独立于内核cpu但帮助内核cpu传输数据而不用占用内核(cpu)的资源,就是在DMA传输数据的同时内核cpu可以干别的事情比如点亮一个LED灯

    • 总线矩阵
      总线矩阵协调内核系统总线和DMA主控总线之间的访问仲裁,仲裁利用轮换算法。因为数据可以被 Dcode 总线和 DMA 总线访问,数据可以是在某个外设的数据寄存器,可以在SRAM,可以在内部的 FLASH。所以为了避免访问冲突,在取数的时候需要经过一个总线矩阵来仲裁,决定哪个总线在取数

  4. 被动单元

    • 内部FLASH
      简单介绍在flash存储内容:我们写好的程序编译之后都是一条条指令(二进制代码),存放在 FLASH 中,我们常量或常变量C 语言中的 const 关键字修饰也存放在FLASH

    • 内部SRAM
      就是我们常说的电脑内存条,程序函数内部的局部变量和全局变量,堆(malloc分配)栈(局部变量)等的开销都是基于内部的SRAM。内核通过 DCode 总线来访问它

    • FSMC
      FSMC 的英文全称是 Flexible static memory controller,叫灵活的静的存储器控制器,是 STM32F10xx 中一个很有特色的外设通过FSMC我们可以扩展内存,如外部的SRAM,NANDFLASH 和 NORFLASH。但有一点我们要注意的是,FSMC 只能扩展静态的内存,即名称里面的 S:static,不能是动态的内存,比如 SDRAM 就不能扩展。

    • AHB 到 APB 的桥
      两个AHB/APB桥在AHB和2个APB总线间提供同步连接。APB1操作速度限于36MHz,APB2操作于全速(最高72MHz),上面挂载着 STM32 各种各样的特色外设。我们经常说的 GPIO、串口、I2C、SPI 这些外设就挂载在这两条总线上,这个是我们学习 STM32 的重点,就是要学会编程这些外设去驱动外部的各种设备。

1.4 STM32的存储空间

stm32芯片内部的总线为32根,内存被划分为一个个的内存单元,每个内存单元的大小是一个字节,为了能有效的访问到内存的每个单元就给内存单元进行编号,编号就被称为该内存单元的地址

在这里插入图片描述

2 点亮小灯

2.1 keil建立工程

具体keil软件使用过程见以前文章:
https://blog.csdn.net/apple_52030329/article/details/127146518

  1. 选择stm32f103c8
    在这里插入图片描述
  2. 添加启动文件
    source group 1添加stm32f103c8t6添加启动文件

先介绍一下启动代码:启动代码是一段和硬件相关的汇编代码。
主要作用如下:
(1) 堆栈(sp)的初始化
(2) 初始化程序计数器(pc)
(3) 设置向量表异常事件的入口地址
(4) 调用main函数

ST公司提供了许多个个启动文件给我们,分别用于不同容量的STM32芯片
在这里插入图片描述
其中,ld.s 适用于小容量 产品;md.s 适用于中等容量产品;hd 适用于大容量产品;

这里的容量是指 FLASH 的大小.判断方法如下

小容量:FLASH≤32K
中容量:64K≤FLASH≤128K
大容量:256K≤FLASH

我们查看一下C8T6的手册

在这里插入图片描述

其Flash容量为128k,属于中容量,因此我们这里采用startup_stm32f10x_md.s作为启动文件。
将启动文件拷贝到工程文件夹下

在这里插入图片描述

找到 Target1Source Group1→双击→设置打开文件类型为 Asm Source file→选择 startup_stm32f10x_hd.s→点击 Add,如下图所示

在这里插入图片描述

这里看到的 2 个文件夹:ListingsObjects,是 KEIL 自行创建的,用于保存编译过程中生成的一些文件。

添加完之后,得到如下界面

在这里插入图片描述

2.2 流水灯的C程序

2.2.1 GPIO端口初始化

  1. 时钟配置
    本次实验使用的引脚是PA5,PB9,PC14
    按照stm32手册,找到时钟使能寄存器映射基地址
    在这里插入图片描述

  2. 使能对应端口时钟

//----------------APB2使能时钟寄存器 ---------------------
#define RCC_APB2ENR		*((unsigned volatile int*)0x40021018)

	RCC_APB2ENR|=1<<2|1<<3|1<<4;			//APB2-GPIOA、GPIOB、GPIOC外设时钟使能	

2.2.2 输入输出模式

本次实验用的到A5、B9、C14三个引脚。其中A5、B9属于端口配置低寄存器偏移地址为0x00,C14属于端口配置高寄存器偏移地址为0x04。

查表获得CPIO端口基地址

在这里插入图片描述
根据此配置对应引脚寄存器

基地址+偏移量

//----------------GPIOA配置寄存器 -----------------------
#define GPIOA_CRL		*((unsigned volatile int*)0x40010800)
//----------------GPIOB配置寄存器 -----------------------
#define GPIOB_CRL		*((unsigned volatile int*)0x40010C04)
//----------------GPIOC配置寄存器 -----------------------
#define GPIOC_CRH		*((unsigned volatile int*)0x40011004)

2.2.3 代码实现

C语言实现代码

//--------------APB2使能时钟寄存器------------------------
#define RCC_AP2ENR	*((unsigned volatile int*)0x40021018)
	//----------------GPIOA配置寄存器 ------------------------
#define GPIOA_CRL	*((unsigned volatile int*)0x40010800)
#define	GPIOA_ORD	*((unsigned volatile int*)0x4001080C)
//----------------GPIOB配置寄存器 ------------------------
#define GPIOB_CRH	*((unsigned volatile int*)0x40010C04)
#define	GPIOB_ORD	*((unsigned volatile int*)0x40010C0C)
//----------------GPIOC配置寄存器 ------------------------
#define GPIOC_CRH	*((unsigned volatile int*)0x40011004)
#define	GPIOC_ORD	*((unsigned volatile int*)0x4001100C)
//-------------------简单的延时函数-----------------------
void  Delay_ms( volatile  unsigned  int  t)
{
     unsigned  int  i;
     while(t--)
         for (i=0;i<800;i++);
}
void A_LED_LIGHT(){
	GPIOA_ORD=0x0<<5;		//PA5低电平
	GPIOB_ORD=0x1<<9;		//PB9高电平
	GPIOC_ORD=0x1<<14;		//PC14高电平
}
void B_LED_LIGHT(){
	GPIOA_ORD=0x1<<5;		//PA5高电平
	GPIOB_ORD=0x0<<9;		//PB9低电平
	GPIOC_ORD=0x1<<14;		//PC14高电平
}
void C_LED_LIGHT(){
	GPIOA_ORD=0x1<<5;		//PA5高电平
	GPIOB_ORD=0x1<<9;		//PB9高电平
	GPIOC_ORD=0x0<<14;		//PC14低电平	
}
//------------------------主函数--------------------------
int main()
{
	int j=100;
	RCC_AP2ENR|=1<<2;			//APB2-GPIOA外设时钟使能
	RCC_AP2ENR|=1<<3;			//APB2-GPIOB外设时钟使能	
	RCC_AP2ENR|=1<<4;			//APB2-GPIOC外设时钟使能
	//这两行代码可以合为 RCC_APB2ENR|=1<<3|1<<4;
	GPIOA_CRL&=0xFF0FFFFF;		//设置位 清零	
	GPIOA_CRL|=0x00200000;		//PA5推挽输出
	GPIOA_ORD|=1<<5;			//设置PA5初始灯为灭
	
	GPIOB_CRH&=0xFFFFFF0F;		//设置位 清零	
	GPIOB_CRH|=0x00000020;		//PB9推挽输出
	GPIOB_ORD|=1<<9;			//设置初始灯为灭
	
	GPIOC_CRH&=0xF0FFFFFF;		//设置位 清零
	GPIOC_CRH|=0x02000000;   	//PC14推挽输出
	GPIOC_ORD|=0x1<<14;			//设置初始灯为灭	
	while(j)
	{	
		A_LED_LIGHT();	
		Delay_ms(10000000);
		B_LED_LIGHT();
		Delay_ms(10000000);
		C_LED_LIGHT();
		Delay_ms(10000000);
	}
}
 
 

本次实验采用三个灯实现,亮灯状态用1表示,灭灯状态用0表示。
初始状态为0 0 0,
状态一为1 0 0
状态二为0 1 0
状态三为0 0 1
状态三结束后继续进入状态一,一直循环达到流水灯效果。

2.3 流水灯的硬件配置

  1. 烧录程序
    在这里插入图片描述
    这里我们需要USB转接口来帮助我们完成,接法如上图
    同时,需要下载烧录软件,我使用的是mcuisp
    在这里插入图片描述
    其中,烧录时要注意,boot0置1,boot1随意
    在这里插入图片描述
  2. 面包板组装电路
    如下图所示
    在这里插入图片描述

注意,在运行程序时,烧录后需要断电,将boot0和boot1都置0

运行效果如下:
在这里插入图片描述


总结

经过本次实验熟悉了一遍寄存器方式编程的基本操作,完成了流水灯实验,在学习和实验期间也遇到过许多困难,但经过查阅资料询问老师同学也解决了问题,受益匪浅。

参考
https://blog.csdn.net/weixin_47554309/article/details/120810913
https://blog.csdn.net/qq_53112972/article/details/127153401?spm=1001.2014.3001.5502

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

日常脱发的小迈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值