历史上的今天
今天是:2026年01月04日(星期日)
2023年01月04日 | STM32单片机中C语言操作寄存器的原理
2023-01-04 来源:zhihu
映射的概念
存储器本身不具有地址信息,它的地址是由芯片厂商或用户分配,给存储器分配地址的过程就称为存储器映射,如下图所示的4GB空间(从block0-block7每个block512M)。在梳理STM32芯片的内部架构中提到的被控单元FLASH、RAM、FSMC和APB等功能部件共同排列在这4GB的地址空间内。在编程的时候,可以通过他们的地址找到他们,然后通过C语言对它们进行数据的读和写操作。

存储器映射
在这 4GB 的地址空间中,ARM 已经粗线条的平均分成了 8 个块,每块 512MB,每个块也都规定了用途,具体分类见如下表格。在这 8 个 Block 里面,有 3 个块非常重要,也是我们最关心的三个块。Block0 用来设计成内部FLASH,Block1 用来设计成内部 RAM,Block2 用来设计成片上的外设。其中,Block2 用于设计片内的外设,根据外设的总线速度不同,Block 被分成了AHB、APB1、APB2。

存储器本身没有地址,给存储器分配地址的过程叫存储器映射,那什么叫寄存器映射?寄存器到底是什么?在存储器 Block2 这块区域,设计的是片上外设,它们以四个字节为一个单元,共 32bit,每一个单元对应不同的功能,当我们控制这些单元时就可以驱动外设工作。我们可以找到每个单元的起始地址,然后通过 C 语言指针的操作方式来访问这些单元,如果每次都是通过这种地址的方式来访问,不仅不好记忆还容易出错,这时我们可以根据每个单元功能的不同,以功能为名给这个内存单元取一个别名,这个别名就是我们经常说的寄存器,这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射。
通过C语言操作寄存器的例子
GPIOB端口的输出数据寄存器ODR的地址是0x40010C0C,ODR寄存器是32bit,低16bit有效,对应着16个外部IO,写0、1对应的IO则输出低、高电平。现在我们通过C语言指针的操作方式,让GPIOB的16个IO都输出高电平,见如下代码。
// GPIOB 端口全部输出 高电平
*(unsigned int*)(0x4001 0C0C) = 0xFFFF;
0x40010C0C在我们看来是GPIOB端口ODR的地址,但是在编译器看来,这只是一个普通的变量,是一个立即数,要想让编译器也认为是指针,我们得进行强制类型转换,把它转换成指针,即(unsigned int *)0x4001 0C0C,然后再对这个指针进行*操作。
通过绝对地址访问内存单元不好记忆且容易出错,可以通过寄存器的方式来操作,具体见如下代码。
// GPIOB 端口全部输出高电平
#define GPIOB_ODR (unsigned int *)(GPIOB_BASE+0x0C)
* GPIOB_ODR = 0xFF;
下一篇:详解STM32单片机的堆栈
史海拾趣
|
电子项目合作群QQ:86455552 本人从事电子设计工作10年以上经验,有扎实的模拟及数字电路 专业知识。有一定EMC、ESD、安规知识;懂射频、开关电源的设 计;会C51、PIC、MSP430、ARM等系列单片机编程。有验钞机, 按摩椅,麻将机,工业仪表、工控 ...… 查看全部问答> |
|
还在为送MM的礼品而担心吗 ___花___已不再新兴了 呵呵 只要22元 就为送MM的礼品就搞定! 这是一款新潮的USB或放入3个7号电池双供电实用美观的闪字风扇,不需要电脑可以自由编写内容,彰显你的个性,风扇转动时,编辑的字符会转动,内容 ...… 查看全部问答> |
|
使用keil写单片机程序时,在程序运行阶段是不允许修改code段中的内容的,但是,我现在想实现动态加载模块的功能,需要在程序运行的时候修改code段的内容. 请问有什么办法在程序运行期间修改code段的内容? ...… 查看全部问答> |
|
请问Windows Embedded CE 6.0 为什么只有评估版? 我在网上到处找Windows Embedded CE 6.0的正式版,但是没有。全都是评估版。请问各位哪里有正式版下载?谢谢。… 查看全部问答> |
|
现在网上有种说法。ulink-me和ulink的软硬件是一样的。区别在:P1.25(28PIN) ULINK-ME 接地, ulink2 接高 or float.在使用keil 3.15时,ulink-me 也会update,只是不成功。有哪为DX,试过。… 查看全部问答> |
|
最近在玩这个RL-ARM。 成功init创建几个任务后,在一个任务里,我用 NVIC_EnableIRQ( )打开了一个外设中断。 在Debug时 跑到这个任务,打开中断时 就挂了。hang on在了 HardFault_Handler。 请问如何解决这个问题? 不是说RL与NVIC中断无限制吗 ...… 查看全部问答> |




