1、寄存器介绍
1.1、寄存器介绍
存储器本身是不具有地址的,是一块具有特定功能的内存单元,它的地址是由芯片厂商或用户分配,给存储器分配地址的过程就叫做存储区映射。给内存单元分配地址之后,就可以通过指针去操作内存地址。
1.2、存储器映射表
我们知道,R7FA6E2BB3CNE#BA0 是一个 32 位的单片机,它的地址范围为 2 的 32 次方,也就是 4GB 的地址空间。为了降低不同客户在相同应用时的软件复杂度,存储映射是按 Cortex-M33 处理器提供的规则预先定义的。在存储器映射表中,一部分地址空间由 Arm Cortex-M33 的系统外设所占用,且不可更改。其余部分地址空间可由芯片供应商定义使用。
1.3、什么是寄存器
寄存器是具有特定功能的内存单元,通过操作这些内存单元可以驱动外设工作。寄存器按功能又可分为指令寄存器、地址寄存器和数据寄存器,处理器可以使用相互独立的总线来读取指令和加载/存储数据。
1.4、寄存器映射
程序存储器,数据存储器,寄存器和 I / O 端口都在同一个线性的 4 GB 的地址空间之内。每一个寄存器都对应不同的功能,操作相应的寄存器就可以配置不同的功能。如果我们要控制某个外设工作,那我们可以找到这个单元的起始地址,然后通过 c 语言指针的方式来访问这些内存单元。但通常我们会给这个特殊的内存单元取一个名字,这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射,这个别名就是我们所说的寄存器。
1.5、寄存器重映射
给寄存器再分配一个地址的过程叫做寄存器重映射。
1.6、总线基地址
1.7、外设基地址
每个总线上都挂载着很多外设,这些外设也都有自己的地址范围,例如。
寄存器名称 | 寄存器地址 | 相对于基础偏移地址 |
---|---|---|
PCNTR1/PODR/PDR | 0x4008_0000 + 0x0020 + 0x0020 | 0x000 |
PCNTR2/PODR/PDR | 0x4008_0000 + 0x0020 + 0x0024 | 0x004 |
PCNTR3/PODR/PDR | 0x4008_0000 + 0x0020 + 0x0028 | 0x008 |
PCNTR4/PODR/PDR | 0x4008_0000 + 0x0020 + 0x002c | 0x00c |
注:其他的可以参考文档 RA6E2 Group User's Manual:Hardware 第438页
1.8、如何操作寄存器地址
在外设的地址范围内,分布着该外设的寄存器。
解释:
- 寄存器名字。
- 外设模块基地址及其寄存器偏移地址。
- Bit position:位号,指该位寄存器中的实际位置。
- Bit field : 为位域,一般不同的位域有不同的作用。
- Value after reset : 为复位值与初始值。
- 方块:具体功能说明。
1.9、如何操作寄存器
上面我们了解到了寄存器映射和 GPIO 外设寄存器的相关地址,那我们怎么去编写代码操作寄存器呢?下面我们就来简单介绍一下。
如果我们想去让 P100 端口输出置高,我们需要去配置端口输出寄存器 PCNTR1/PODR/PDR ,通过查找用户手册 438 页可以知道寄存器基地为 PORTm = 0x4008_0000 + 0x0020 × m (m = 0 to 5, 8),我们控制的 P100 则 m = 1 ,则实际的基地址则为 PORT1 = 0x4008_0000 + 0x0020 × 1,那我们就是对这个地址进行操作。那如何操作呢?
关于端口位操作寄存器说明如图所示:
通过上图可知,我们需要把 P100 端口输出置高,则只需要将第0位于第16位置1即可,换算成十六进制就是 0x00010001
通过绝对地址访问内存单元:
P100 端口输出置高
*(uint32_t*)(0x40080000+0x0020*1) = 0x00010001;
2
说明:
(unsigned int*) 的作用是将 0x40080020 这个数字量 强制类型转化为 无符号整形的 地址,告诉编译器这是一个地址。
*(unsigned int) 是相当于控制地址里的内容,也就是对这个地址对应的内存空间的值,
*(uint32t)(0x40080000+0x0020*1) = 0x00010001; 就是相当于对 0x40080020 这个内存空间赋值为 0x10001。
2、寄存器点灯
2.1、新建工程
首先我们打开 E2 studio 工具,如下图所示:
接下来需要选择一个文件夹作为一个工作空间,用来存放例程,如下图所示:
点击 启动 按钮,进入下一个界面,进入下一个界面后点击 文件->新建->瑞萨 C/C++ 项目 -> Renesas RA 即可,如下图所示:
接下来,新建Renesas RA 项目模版工程,选择 ALL -> Renesas RA C/C++ Poroject -> 下一步(N),如下图所示:
然后创建工程项目名称(项目名称:rgb_led),如下图所示:
接下来选择器件与编辑环境等,我们选择的型号为:R7FA6E2BB3CNE ,其余都保持不变,如下图所示:
下方的 Toolchains 栏里选择工具链 GNU ARM Embedded ,也就是 GCC 编译器,选择这个如下图所示:
这里选择的是 debug 的仿真工具,根据自己的需求进行选择,保持默认后面会教大家如何修改,这个如下图所示:
点击下一步,这个界面保持默认,如下图所示:
点击下一步,这个界面保持默认,如下图所示:
点击 完成 即可,如下图所示:
加载完成后,会出现一个透视图,点击 打开透视图 ,如下图所示:
加载完成后,我们需要点击关闭欢迎页面,就会显示如下图所示的透视图界面。
接下来我们要使用 FSP Configuration 配置 GPIO 的 P402 输出,且初始化为低电平,如下图所示:
Pin Configuration 页面的 IOPORT 属性介绍:
Pin Configuration | 描述 |
---|---|
Mode | IO 引脚的工作模式,包括输入模式和输出模式。 |
Pull up/down | IO 引脚输入是否上拉。 |
IRQ | IO 引脚是否中断模式。 |
Output type | IO 引脚的输出类型。可以选 CMOS 推挽输出或开漏输出。 |
Drive Capacity | IO 引脚的驱动能力设置。 |
配置好后,最右边的芯片的P402引脚将有白色变为绿色,代表你对这个引脚做了功能设置,接下来按下 Ctrl + S 键进行保存,在点击 Generate Project Content 生成对应的配置文件,如下图所示:
注:必须先保存,然后再点击 Generate Project Content 。
生成完毕后我们打开 reg_led -> src -> hal_entry.c 文件进行添加应用程序。
2.2、编写代码
我们需要再 halentry() 函数里面的 / TODO: add your own code here _/ 下面添加你的代码,如下图所示:
//P402 端口输出置高
*(uint32_t*)(0x40080000+0x0020*4) = 0x00040004;
2
接下来进行编译构建,如下图所示:
也可以直接点击小锤子进行构建,如下图所示:
编译结果如下所示:
至此我们的寄存器驱动IO就完成。