【MSP432】完全学习指南——寄存器和库函数

寄存器和库函数介绍


相关例程请访问gitee仓库

1 寄存器介绍

  1. 认识存储器
  2. 存储器映射
  3. 存储器映射表
  4. 认识寄存器
  5. 寄存器映射
  6. 寄存器重映射
  7. 外设寄存器地址
  8. 如何操作寄存器

1.1 认识存储器

​ 存储器按使用类型可分为只读存储器(ROM)和随机存储器(RAM)。存储器是许多存储单元的集合,主要用来存储程序和各种数据信息的部件

1.2 存储器映射

存储器本身是不具有地址的,是一块具有特定功能的内存单元,它的地址是由芯片厂商或用户分配,给存储器分配地址的过程就叫做存储区映射。给内存单元分配地址之后,就可以通过指针去操作内存地址。

1.3 存储器映射表

我们知道,MSP432是一个32位的单片机,它的地址范围为2的32次方,也就是4GB的地址空间。为了降低不同客户在相同应用时的软件复杂度,存储映射是按Cortex-M4F处理器提供的规则预先定义的。在存储器映射表中,一部分地址空间由Arm Cortex-M4F的系统外设所占用,且不可更改。其余部分地址空间可由芯片供应商定义使用。

关于外设存储器映射表的内容,大家可以去查看datasheet第93页点击跳转

1.4 什么是寄存器

寄存器是具有特定功能的内存单元,通过操作这些内存单元可以驱动外设工作。寄存器按功能又可分为指令寄存器、地址寄存器和数据寄存器,处理器可以使用相互独立的总线来读取指令和加载/存储数据。

1.5 寄存器映射

程序存储器,数据存储器,寄存器和I / O端口都在同一个线性的4 GB的地址空间之内。每一个寄存器都对应不同的功能,操作相应的寄存器就可以配置不同的功能。如果我们要控制某个外设工作,那我们可以找到这个单元的起始地址,然后通过c语言指针的方式来访问这些内存单元。但通常我们会给这个特殊的内存单元取一个名字,这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射,这个别名就是我们所说的寄存器。

1.6 寄存器重映射

给寄存器再分配一个地址的过程叫做寄存器重映射。

1.7 总线基地址

​ 片上外设区域在一条AHB总线上,AHB总线最高时钟可达48MHZ,总线上挂载着不同的外设,总线的最低地址我们称为该总线的基地址,总线基地址也是挂载在该总线上的首个外设的地址。

1.8 外设基地址

每个总线上都挂载着很多外设,这些外设也都有自己的地址范围。

关于Timer这个外设的地址映射信息如表所示。

外设名称外设基地址
Timer_A00x4000_0000
Timer_A10x4000_0400
Timer_A20x4000_0800
Timer_A30x4000_0C00

1.9 外设寄存器地址

​ 在外设的地址范围内,分布着该外设的寄存器。

以Timer外设为例,Timer外设地址范围内有很多个寄存器,每一个都有特定的功能,通过操作对应的寄存器来配置Timer的功能。

这里我们以Timer A0端口的一部分寄存器进行介绍。

寄存器名称地址偏移相对于Timer A0的地址
Timer_A0 Control0x00Timer_A0_BASE + 0x00U
Timer_A0 Capture/Compare Control 00x02Timer_A0_BASE + 0x02U
Timer_A0 Capture/Compare Control 10x04Timer_A0_BASE + 0x04U
Timer_A0 Capture/Compare Control 20x06Timer_A0_BASE + 0x06U
Timer_A0 Capture/Compare Control 30x08Timer_A0_BASE + 0x08U
Timer_A0 Capture/Compare Control 40x0ATimer_A0_BASE + 0x0AU

1.10 如何操作寄存器

上面我们了解到了寄存器映射和外设寄存器的相关地址,那我们怎么去编写代码操作寄存器呢?下面我们就来简单介绍一下。

GPIO寄存器

中断向量寄存器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-etDwQGFk-1690452730735)(…/…/res/Register/PxIV_Register.png)]

数据输入寄存器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0bJDlvCz-1690452730736)(…/…/res/Register/PxIN_Register.png)]

数据输出寄存器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pIV3OJdH-1690452730736)(…/…/res/Register/PxOUT_Register.png)]

数据方向寄存器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KO37ZeU2-1690452730736)(…/…/res/Register/PxDIR_Register.png)]

上下拉使能寄存器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-09Yo5rkw-1690452730736)(…/…/res/Register/PxREN_Register.png)]

驱动选择寄存器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QlDRP7lW-1690452730737)(…/…/res/Register/PxDS_Register.png)]

复用选择寄存器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VkaFMdLB-1690452730737)(…/…/res/Register/PxSEL0_Register.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l2D489tQ-1690452730737)(…/…/res/Register/PxSEL1_Register.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zp7lo0dg-1690452730737)(…/…/res/Register/ioFunctionSelection.png)]

功能同变化寄存器

通过这个寄存器可以判断引脚复用的功能是否切换成功

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hiJ2eFe3-1690452730738)(…/…/res/Register/PxSELC_Register.png)]

端口触发寄存器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ze2xFe4A-1690452730738)(…/…/res/Register/PxIES_Register.png)]

端口中断使能寄存器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2Iu54q2o-1690452730738)(…/…/res/Register/PxIE_Register.png)]

端口中断标志寄存器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t5sQiwN6-1690452730738)(…/…/res/Register/PxIFG_Register.png)]

1. 通过绝对地址访问内存单元

/* GPIOA 端口的16个引脚全部输出高电平 */

*(unsigned int*)(0x40020014) = 0xFFFF;

说明:

(unsigned int*)的作用是将0x40020014这个立即数强制类型转化为无符号整形地址,告诉编译器这是一个地址。

(unsigned int)是相当于地址,也就是对这个地址对应的内存空间的值,(unsigned int*)(0x40020014) = 0xFFFF;就是相当于对0x40020014这个内存空间赋值为0xFFFF。

2. 通过别名访问内存单元

通过上面的方式确实可以对寄存器地址进行操作,但是操作起来很麻烦,用户也不能清晰的明白这个地址对应的功能。如果我们给每个地址都起一个名字,这样看到名字是不是就知道这个地址对应什么功能了呢。

/* GPIOA 端口的16个引脚全部输出高电平 */

#define GPIOA_OCTL *(unsigned int*)(0x40020014)

GPIOA_OCTL = 0xFFFF;

2 库函数介绍

2.1 为什么要使用库函数

从前面我们了解到如何去用寄存器驱动外设,但我们也同时了解到MSP432的寄存器数量非常多,这么多的寄存器光是定义就需要花费很多的时间,更不用说还要去查找对应的功能,找到对应的地址,然后配置需要的值,这在难度和时间上都是不可取的。为此,库函数就在这种情况下应运而生,库函数能使我们的开发效率大大提高。关于MSP432的标准外设库函数,TI的官方已经给我们开发好了,我们只需要移植到我们的工程使用即可。库函数的使用不需要让我们去了解硬件的机制,只需要根据需要的功能去查找对应的函数,然后调用即可,大大降低了开发要求。

2.2 库函数简单介绍

从前面可以知道创建的工程模板里面有MSP432的标准外设库,我们可以打开其中的gpio.h和gpio.c文件进行查看,也可以参考固件库使用手册进行参考。

2.3 如何操作库函数

首先,我们如果想操作的功能是关于GPIO的,那么首先要从GPIO外设库中去寻找。打开gpio.h头文件,拉到最下面可以看到所有声明的有关GPIO的API函数。我们是让GPIOA的某个引脚置1,也就是对引脚进行操作,我们寻找对应的功能函数,从函数名可以知道GPIO_setOutputHighOnPin这个函数是对引脚进行写数据操作1可见这个功能函数是我们需要的。

3 寄存器和库函数的区别

从上面,我们了解到使用寄存器和库函数最终都是对地址进行操作,那它们之间有什么区别呢?什么时候用寄存器什么时候用库函数呢?

  • 寄存器更能理解原理,更直观,库函数相对来说屏蔽底层,直接面向应用。
  • 使用库函数较寄存器代码量会增大,库函数会把所有情况都考虑到函数里,有时会造成代码的冗余。
  • 库函数使用起来相对简单,容易上手,可快速开发应用,大大提高效率。
  • 寄存器占用内存少,速度快,在资源有限或者要求执行速度的情况下寄存器是一个不错的选择。
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值