TI Cotex M3/4单片机关于寄存器操作详解

  • 前备知识
    • 寄存器与偏移量
    • 位带操作、位带区
  • TI单片机寄存器操作详解
    • 快速在TI的手册里面确认某外设某寄存器的确切地址
    • 寄存器操作介绍
    • 本文参考

前备知识

  当前单片机的开发方式多种多样,寄存器,库函数,图形化编程等等,可以说是越发的方便,开发速度也是越来越快,库函数开发固好,但是了解一些寄存器操作也绝不是一件多余的事情,因为有很多库函数其底层其实就是寄存器操作编写而成的,能够看懂、理解寄存器操作,对于库函数也会有更深入的理解,有时候也能更快更好地解决一些你以前认为很无厘头的bug。

寄存器与偏移量

  在学习单片机过程中我们不可避免的要接触了解一点寄存器的内容,初学者刚刚听到这个名字往往有些不知所云,脑子里对寄存器没有一个具象的概念,所以我们就先从寄存器介绍开始吧。
  什么是寄存器?
  给有特定功能的内存单元取一个别名,这个别名就是我们经常说的寄存器,这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射。给一个我们不能直观理解的数字(这里指地址)一个名字,就会让我们在进行操作时更快更省力的完成任务。
  偏移地址以及如何计算:
  偏移地址是微控制器里的内存分段后,在段内某一地址相对于段首地址(段地址)的偏移量。偏移地址也成为偏移量。最后硬件电路山所应用的物理地址,是由相应段地址加上偏移地址组成的,在单片机中即为:物理地址=寄存器首位地址+偏移量。

  计算方法:物理地址 = 基地址+偏移量。

  关于单片机寄存器地址的计算实际上是非常简单的,举个例子就可以明白:关于MSP432E401Y单片机来说GPIO_PORTA的寄存器的值=0x40058000H,我们认为这就是基地址。RCGCGPIO Register的偏移地址是是0x608H。

GPIO Port A (AHB): 0x40058000 (ending address of 0x40058FFF)
RCGCGPIO Register (Offset = 0x608) [reset = 0x00]

  我们如果想操作GPIO_PORTA的RCGCGPIO这个寄存器的话,我们就可以算出:
  GPIO_PORTA的RCGCGPIO的物理地址=0x40058000H+0x608H=0x4005 8608H

位带操作、位带区

  位带操作这个概念很早就存在了,要说其起始那还要说到51 单片机的位寻址操作。为了控制篇幅,在此就不再过多介绍其中渊源,我们当前只需了解CortexM3/4 就是将位寻址操作能力进化,就得到了威力大幅加强的位带操作。
  概念明析:
  位寻址操作: 许多嵌入式使用者的第一块单片机都是51单片机,这是大家非常熟悉的。51单片机中,假设P1.5的IO口上挂了一个LED,那么你单独对LED的操作就是P1.5 = 0或P1.5 = 1,在51单片机中你可以单独的对P1端的第5个IO口进行操作,这种操作就叫位寻址操作。然而在像STM32、MSP432等等资源量更大的单片机中是不允许这样做的,那么为了像51单片机一样能够单独的对某个端的某一个IO单独操作,就引入了位带操作这样的概念,简而言之,就是为了去单独操作更大资源量单片机里面某个GPIO_PORT口中的某一个IO口(当然也支持同时操作几个),所以就有了位带这样的操作机制。
  位带操作: 就是指可以使用普通的加载/存储指令来对单一的比特(bit)来进行读写。打个比喻,就相当于是为位带区的每一位都起了一个别名,或者说是为为带区的每一位新建了一个快捷方式,通过对指定别名的访问来代替对指定位的访问。说明:指定位与别名之间的映射过程是由内核完成的,无需人工干预。
  位带区: 支持位带操作的地址范围,在CortexM4中有两个位置实现了位带操作,一个是SRAM的最低1MB范围,另一个是片内外设区的最低1MB范围。这两个区中的地址除了可以像普通的RAM 一样使用外,它们还都在“位带别名区”有自己的位带别名,位带别名区把每个比特膨胀成一个32 位的字。当你通过位带别名区访问这些字时,就可以达到访问原始比特的目的。为了能使用普通指令来加载和存储那么这个别名肯定得膨胀成32位(一个字),不过这个32位只有低位有效。所以这样就可以通过对别名的访问来代替对位带区指定位的访问了。
  位带别名区: 对别名地址的访问最终会作用到位带区对应位,注意这个过程中有一个地址映射的过程。
  

图 1-MSP432E401Y数据手册中对CotexM4中的位带操作的介绍

  其实TI的手册是及其详尽的,缺点就是它对英文不太好的朋友不是很友好。对于位带的这部分内容上面手册中讲解的这部分内容就很直观清楚了,我谨在下进行少量的内容总结与补充。

  在CotexM4中支持位带操作的两个内存区的范围是:
  SRAM区最低的1M:从 0x2000.0000 到 0x2006.FFFF
  片上外设区的最低1M:从 0x4000.0000 到 0x400F.FFFF

  对于SRAM位带区的某个比特,记它所在字节地址为A,位序号为n(0<=n<=7),则该比特在别名区的地址为:
  AliasAddr = 0x2200.0000+((A-0x2000.0000)*8+n)*4=0x2200.0000+(A-0x2000.0000)*32+n*4
  对于片上外设位带区的某个比特,记它所在字节地址为A,位序号为n(0<=n<=7),则该比特在别名区的地址为:
  AliasAddr = 0x4200.0000+((A-0x4000.0000)*8+n)*4=0x4200.0000+(A-0x4000.0000)*32+n*4
  上式中,“*4”表示为一个字4个字节,“*8”表示为一个字节中有8个比特。
本部分内容到此结束,如果实在看不懂也请不要放弃,看起来复杂,你只需要会用就可以,接下来本文将进入实操内容,会对如何进行实际操作进行尽可能详细的介绍。

TI单片机寄存器操作详解

快速在TI的手册里面确认某外设某寄存器的确切地址

  首先我们手里要确保有一本你正在使用的单片机型号相相对应的手册,TI各系列单片机的手册均可在官网下载得到,在此不赘述。
  (以下以寻找MSP432E401Y单片机GPIO_PORTA的GPIODIR寄存器为例)
1.从目录找到对应外设的寄存器内容描述部分,获得基地址GPIO Port A (AHB): 0x40058000 (ending address of 0x40058FFF)。

图 2-获取基地址

2.根据手册中的寄存器表,找到GPIODIR寄存器,详细查看。

图 3-找到GPIODIR寄存器

3.了解该寄存器的偏移量及其功能。

图 4-了解该寄存器的偏移量及其功能

我们就可以知道GPIO_PORTA的GPIODIR的首地址为: 0x40058000 + 0x400 = 0x40058400 。

寄存器操作介绍

  以下内容适用于目前大多数TI单片机。本文均以MSP432E401Y单片机为例。

//*****************************************************************************
//
// types.h - Macros used when accessing the comparator hardware.
// Copyright (c) 2017 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
//
//*****************************************************************************
#ifndef __TYPES_H__
#define __TYPES_H__//*****************************************************************************
//
// Macros for hardware access, both direct and via the bit-band region.
//
//*****************************************************************************
#define HWREG(x)//HWREG 就是用来取外设寄存器地址                              \(*((volatile uint32_t *)(x)))
#define HWREGH(x)                                                             \(*((volatile uint16_t *)(x)))
#define HWREGB(x)                                                             \(*((volatile uint8_t *)(x)))
#define HWREGBITW(x, b)                                                       \HWREG(((uint32_t)(x) & 0xF0000000) | 0x02000000 |                     \(((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2))
#define HWREGBITH(x, b)                                                       \HWREGH(((uint32_t)(x) & 0xF0000000) | 0x02000000 |                    \(((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2))
#define HWREGBITB(x, b)                                                       \HWREGB(((uint32_t)(x) & 0xF0000000) | 0x02000000 |                    \(((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2))#endif // __TYPES_H__

  在MSP432E401Y(TIVA系列同)的开发过程当中,使用的SDK开发都是库函数操作,即只需要调用相关的函数,确定相应的入口参数就可以实现特定功能。但是库函数归根结底的功能是操作寄存器中的相关位,通过一层一层的调用关系,而归结到最底层,凡是对硬件的操作最终都会以上几条语句。
  前面3句是直接的取寄存器操作,后面三句是通过“位带操作”取寄存器。
  位带操作最主要是理解位带区和未带别名区的对应关系。接下来是对HWREGBITW()操作进行解析:

 HWREG(((uint32_t)(x) & 0xF0000000) | 0x02000000 |  (((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2))  :bit_word_offset = (byte_offset x 32) + (bit_number x 4)bit_word_addr = bit_band_base + bit_word_offset其中:bit_word_offset-在位带区中的目标位的位置。(((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2)bit_word_addr-在别名区中与目标位映射的字的地址。(((uint32_t)(x) & 0xF0000000) | 0x02000000 | (((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2)bit_band_base-别名区的起始地址  ((uint32_t)(x) & 0xF0000000) | 0x02000000byte_offset-字节在包含目标位的位带区中的编号((uint32_t)(x) & 0x000FFFFF)bit_number-目标位的位置,0-7。

  接下来是直接操作寄存器位的C语言语句: (*((volatile uint8_t *)
  1、(volatile uint32_t )(x)表示将X强制转化为uint32-t型指针;
  2、
((volatile uint32_t )(x)),设(volatile uint32_t )(x)=P,则表达式为P,我们可以对P进行取值和赋值。
  3、volatile是告诉编译器这段代码不要优化,也就是每次取值,都是从内存里面取,而不是从寄存器里面直接取。

  最后我们现在再来看一下GPIODirModeSet()这个函数的原型,相信各位已经可以看懂了。

//Sets the direction and mode of the specified pin(s).
//设置具体的引脚的方向与模式
void
GPIODirModeSet(uint32_t ui32Port, uint8_t ui8Pins, uint32_t ui32PinIO)
{//// Check the arguments.//ASSERT(_GPIOBaseValid(ui32Port));ASSERT((ui32PinIO == GPIO_DIR_MODE_IN) ||(ui32PinIO == GPIO_DIR_MODE_OUT) ||(ui32PinIO == GPIO_DIR_MODE_HW));//// Set the pin direction and mode.//HWREG(ui32Port + GPIO_O_DIR) = ((ui32PinIO & 1) ?(HWREG(ui32Port + GPIO_O_DIR) | ui8Pins) :(HWREG(ui32Port + GPIO_O_DIR) & ~(ui8Pins)));HWREG(ui32Port + GPIO_O_AFSEL) = ((ui32PinIO & 2) ?(HWREG(ui32Port + GPIO_O_AFSEL) |ui8Pins) :(HWREG(ui32Port + GPIO_O_AFSEL) &~(ui8Pins)));
}

本文参考

[1]: 《MSP432E4 SimpleLink™ 微控制器技术参考手册》
[2]: “ti\simplelink_msp432e4_sdk_4_20_00_12\source\ti\devices\msp432e4\driverlib\types.h”

TI Cotex M3/4单片机关于寄存器操作详解相关推荐

  1. 单片机最小系统 原理图详解 PCB操作 个人备忘

    印象笔记链接: 单片机最小系统 原理图详解 PCB操作 总结(图解) - CSDN资源下载 -  点击打开链接

  2. 3.堆栈指针寄存器 SP 详解

    堆栈指针寄存器 SP 详解 堆栈是一种具有"后进先出"(LIFO---Last In First Out)特殊访问属性的存储结构.堆栈一般使用RAM 物理资源作为存储体,再加上LI ...

  3. ILI9341的使用之【四】RGB接口操作详解

    <ILI9341的使用之[一]TFT-LCD原理(转载)> <ILI9341的使用之[二]ILI9341介绍> <ILI9341的使用之[三]ILI9341系统通信接口模 ...

  4. Cisco 3945路由器密码恢复,rommon模式操作详解

    Cisco 3945路由器密码恢复,rommon模式操作详解 在一次客户的网络出现故障,网络中断,排除故障的原因,发现到达路由器地址不通: 观察到路由器接口灯全部熄灭,电源状态正常: 然后使用cons ...

  5. 单片机_PWM输出原理详解

    单片机_PWM输出原理详解 理论篇   博主自己的经历告诉我,PWM波的理解和应用确实还是挺重要的,这里专门花一期详细介绍一下 什么是PWM?   PWM,英文名Pulse Width Modulat ...

  6. MATLAB与51单片机进行串口通信详解

    目录 一.51单片机与电脑进行串口通信 二.MATLAB串口通信函数 三.串口属性 四.示例Demo 4.1 MATLAB接收单片机发来的数据 4.2 MATLAB向单片机发送数据控制LED 五.总结 ...

  7. 核心要素及常用操作详解

    核心要素及常用操作详解 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5z6s4kZN-1678660733651)(http://49.7.203.222:3000/ ...

  8. NandFlash操作详解(一)

    NandFlash的分类: 根据物理结构上的区别,NandFlash主要分为以下两种: SLC(SingleLevel Cell):单层式存储 MLC(MultiLevel Cell):多层式存储 S ...

  9. python输入参数改变图形_Python基于Tensor FLow的图像处理操作详解

    本文实例讲述了Python基于Tensor FLow的图像处理操作.分享给大家供大家参考,具体如下: 在对图像进行深度学习时,有时可能图片的数量不足,或者希望网络进行更多的学习,这时可以对现有的图片数 ...

最新文章

  1. 【并发编程】Future模式及JDK中的实现
  2. 50 xen虚拟化技术基础、xen虚拟化技术进阶
  3. java验证码实现简单_java实现简单的验证码功能
  4. python语言怎么学-如何学习Python,以及新手如何入门?
  5. Leetcode 167. 两数之和 II - 输入有序数组 解题思路及C++实现
  6. CasperJS基于PhantomJS抓取页面
  7. SessionState详解
  8. redis主从复制_技术干货分享:一文了解Redis主从复制
  9. MySQL 中删除的数据都去哪儿了?
  10. php做姓名隐藏,PHP只显示姓名首尾字符,隐藏中间字符并用*替换
  11. K3/Cloud 用插件打开一张已存在的单据
  12. openCV 下载地址
  13. 「自然语言处理(NLP)论文推送」(中文诗歌生成) 上下文增强Transformer【ACL 微信AI团队 北交】
  14. 【Qt】用setValue()设置UI控件内的内容,如何避免valuechange()被触发
  15. 关于一次生产环境项目线程数一直增长问题排查记录
  16. CSS calc()函数的用法
  17. 圆方树总结 [uoj30]Tourists
  18. 农夫山泉有点牛!港股打新把暗盘系统都整崩溃了
  19. (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  20. 长难句结构分析最新经典一百句

热门文章

  1. 用友nc65 uap开发参照多选三种显示情况总结
  2. EMD 在无损检测中超声检测中的应用
  3. c++图形库编写点灯小游戏
  4. 未达款项 银行余额调节表及EBS的实现
  5. python-- 模拟淘宝自动回复--文件读写的问题//记录用户的登录日志(记录登录时间)
  6. OpenSSL 基础命令
  7. 动手学强化学习第六章(Dyna-Q算法)
  8. 美团面试准备之数据库
  9. electron-vue使用教程
  10. 故障分析 | MongoDB Sharding QPS 分布不均案例一则