首页 > 其他分享 >CH32V003在MRS中的头文件定义

CH32V003在MRS中的头文件定义

时间:2023-08-17 22:33:57浏览次数:45  
标签:__ 头文件 CH32V003 MRS BASE IO RCC uint32 define

在MRS的头文件core_riscv.h中有如下的定义。 

#define     __I     volatile const
#define     __O     volatile
#define     __IO    volatile 

上述定义,通过define语句把__IO等效为volatile,把__O等效为volatile,把__I等效为volatile const。一般来说宏定义都用大写形式,但因为这里用的字母比较少(只有I或O或IO),所以在其前面添加双下划线来进行区分,这样做可以有效避免命名冲突问题。volatile本身是一个关键字,表示其后面定义的变量不让编译器进行优化,即每次读取或者修改值的时候,都必须重新从内存或者寄存器中读取或者修改。例如在单片机开发中,经常会用到软件延时,但若想让软件延时不被编译器优化掉,就必须在变量定义前加上关键字volatile,如“for(volatile unsigned int k=0;k<60000;k++);”。volatile const则表示其后面定义的变量为只读,比如用它来定义一个只读的状态寄存器。定义为volatile是因为它的值可能会被硬件意想不到地改变,而定义为const则是因为程序不应该试图去修改它的值。通俗的说,就是它定义的是一个“只读变量”而不是常量,它的值是由硬件来改变的,不能通过程序写入来改变。
归纳一下:
__I:定义输入口。既然是输入,那么寄存器的值就随时会被外部修改,所以不能对它进行优化,每次都必须从寄存器中读取。也不能写(只读),否则就不是输入而是输出了。
__O:定义输出口,也不能对它进行优化,不然端口连续两次输出相同的值,编译器就会认为没有变化,而忽略后那一次输出,假如外部在两次输出中间修改了值,那就会影响输出的正确性。可写,否则就不能称为输出了。
__IO:定义输入输出口,也不能对它进行优化,原因同上。可读可写。 

在头文件ch32v00x.h中,使用结构体的形式封装了GPIO端口所有的寄存器,代码如下所示。

typedef struct
{
    __IO uint32_t CFGLR;
    __IO uint32_t CFGHR;
    __IO uint32_t INDR;
    __IO uint32_t OUTDR;
    __IO uint32_t BSHR;
    __IO uint32_t BCR;
    __IO uint32_t LCKR;
} GPIO_TypeDef;

在以同样的方式,封装了时钟配置相关的寄存器,代码如下所示。

typedef struct
{
    __IO uint32_t CTLR;
    __IO uint32_t CFGR0;
    __IO uint32_t INTR;
    __IO uint32_t APB2PRSTR;
    __IO uint32_t APB1PRSTR;
    __IO uint32_t AHBPCENR;
    __IO uint32_t APB2PCENR;
    __IO uint32_t APB1PCENR;
    __IO uint32_t RESERVED0;
    __IO uint32_t RSTSCKR;
} RCC_TypeDef;

封装完成后,还需要把它与具体的物理地址关联起来。下图给出了CH32V003的整个32位寻址空间及其相关设备地址的分配情况。 

从大体上来看,从0x00000000到0x20000000的空间分配给了FLASH_ROM,在其中又进行了细分,这里先不作讨论。从0x20000000到0x20000800的空间分配给了RAM,共计2KB。从0x40000000到0x50050400的空间分配给了外设(Peripherals)。从0xE0000000到0xE0100000的空间被分配给了内核私有外设(Core Private Peripherals)它包含了属于内核的一些外设,如SysTick定时器,全局中断系统等等。除了以上分配的地址空间之外,其余地址均为保留地址。在外设空间Peripherals中,被细分出了很多设备地址,在MRS中把它们归成3个大类,即APB1、APB2和AHB。 APB1的基址为0x40000000,APB2的基址为0x40010000(即Peripherals的基址+0x10000的偏移量),AHB的基址为0x40020000(即Peripherals的基址+0x20000的偏移量)。一般来说,APB属于低速总线,AHB属于高速总线。从上图中可见,RCC被划分到AHB中,而GPIO则被划分到APB2中。

对照上面的地址分布,就很容易弄清外设在头文件中如与地址进行关联了。在ch32v00x.h中,RCC的地址关联通过以下代码实现(提取整理过)。 

#define PERIPH_BASE                             ((uint32_t)0x40000000)
#define AHBPERIPH_BASE                          (PERIPH_BASE + 0x20000)
#define RCC_BASE                                (AHBPERIPH_BASE + 0x1000)
#define RCC                                     ((RCC_TypeDef *)RCC_BASE) 

上述代码中,第1行定义了Peripherals外设的基地址,第2行定义了AHB的基地址,第3行定义了RCC的基地址,第4行对RCC进行地址映射(地址关联)。通过define语句来给前面定义的RCC_TypeDef结构体指针取个“别名”(即RCC),这样RCC就成为了这个结构体指针类型,通过“RCC->”这样的方式就可以引用它的内部成员变量(即时钟配置模块的各个寄存器)了。这样一来,就把芯片底层的地址用高级语言名称的形式来表示,既直观又方便易用。

同理,GPIO的地址关联通过以下代码实现(提取整理过)。 

#define PERIPH_BASE                             ((uint32_t)0x40000000)
#define APB1PERIPH_BASE                         (PERIPH_BASE)
#define APB2PERIPH_BASE                         (PERIPH_BASE + 0x10000)
#define GPIOA_BASE                              (APB2PERIPH_BASE + 0x0800)
#define GPIOC_BASE                              (APB2PERIPH_BASE + 0x1000)
#define GPIOD_BASE                              (APB2PERIPH_BASE + 0x1400)
#define GPIOA                                   ((GPIO_TypeDef *)GPIOA_BASE)
#define GPIOC                                   ((GPIO_TypeDef *)GPIOC_BASE)
#define GPIOD                                   ((GPIO_TypeDef *)GPIOD_BASE)

上述代码中,第1行定义了Peripherals外设的基地址,第2行定义了APB1的基地址,第3行定义了APB2的基地址,第4~6行分别定义了GPIOA、GPIOC和GPIOD的基地址,第7~9行对3个GPIO端口进行地址映射(地址关联)。

通过以上的结构体封装及地址映射,在C语言中就可以很方便的引用设备中的寄存器了。比如要选择外部晶体振荡,执行语句“RCC->CFGR0 |= 0x00010000;”就可以了。上面只针对RCC及GPIO这两个模块的结构体进行了分析,没有提及其他模块的结构体,但它们所采用的方法是完全一样的,可参考上面的分析方法来研究其他模块结构体的定义,就不一一赘述了。

 

标签:__,头文件,CH32V003,MRS,BASE,IO,RCC,uint32,define
From: https://www.cnblogs.com/fxzq/p/17400411.html

相关文章

  • 《控制台篇》头文件h和源文件cpp的区别
    头文件和源文件区别参考链接:https://zhidao.baidu.com/question/940855602014421372.html头文件和源文件在本质上没有任何区别。只不过一般:后缀为.h的文件是头文件,内含函数声明、宏定义、结构体定义等内容。后缀为.c的文件是源文件,内含函数实现,变量定义等内容。而且是什么后......
  • CH32V003在MRS中的初始化过程
    在MRS的默认配置中,在main函数执行之前,就已经执行了时钟的初始化配置程序,这部分程序被放在了一个名为system_ch32v00x.c的文件中,这个文件默认被加载到MRS的User目录下(可双击打开它)。在该文件中,最重要的一个函数就是SystemInit,它负责系统的初始化工作,其代码如下所示。 voidSyste......
  • CH32V003及其开发环境
    CH32V003是南京沁恒微电子股份有限公司推出的一颗工业级通用微控制器芯片(单片机)。它基于32位RISC-V指令集及架构设计,采用该公司自主开发的青稞V2A(QingKeV2)内核,基于RV32EC指令集,具有2级流水线,支持2级中断嵌套,支持2级硬件堆栈。支持48MHz系统主频,具有宽压(3.3/5V)、单线调试(SWDIO)、低......
  • CH32V003开发环境MRS配置
    MRS是MounRiver工作室采用开源项目Eclipse制作的一款易于使用的开发工具,它几乎是为WCH系列芯片量身定制的,相对于其他一些开发环境,它具有编译速度快,使用简洁方便,支持多种平台等特点,可访问MounRiver的官网(www.mounriver.com)下载最新版本。MRS的安装可全部采用默认选项进行,安装完成......
  • C++ #pragma once指令:保护C++头文件不被重复包含
    一、#ifndef/#define/#endif指令的问题在C++中,头文件的作用就是将代码以模块的形式组织起来,便于复用和维护。但是,头文件很容易出现重复定义的问题。比如,某个头文件被多个源文件包含,这些源文件又有可能被其他源文件包含,那么就有可能出现一个头文件被重复包含的情况。这样就会......
  • MRS大企业ERP流程实时数据湖加工最佳实践
    本文分享自华为云社区《MRS大企业ERP流程实时数据湖加工最佳实践》,作者:晋红轻。本文将以ERP流程实践为例介绍MRS实时数据湖方案的演进案例实践需求解析:业务描述AE表:会计分录表,主要记录财务相关信息,可用于成本核算等业务计算。为业务最主要的表,称驱动表。四通道表:实际为四个......
  • MRS大企业ERP流程实时数据湖加工最佳实践
    本文分享自华为云社区《MRS大企业ERP流程实时数据湖加工最佳实践》,作者:晋红轻。本文将以ERP流程实践为例介绍MRS实时数据湖方案的演进案例实践需求解析:业务描述AE表:会计分录表,主要记录财务相关信息,可用于成本核算等业务计算。为业务最主要的表,称驱动表。四通道表:实际为四个门店业......
  • ue 遇到的头文件小问题
    CompilerResultsLog:Error:C:/Users/ppx/Documents/UnrealProjects/CryptRaider/Source/CryptRaider/Mover.h(8):Error:#includefoundafter.generated.hfile-the.generated.hfileshouldalwaysbethelast#includeinaheader出现的问题情况编译失败,因为.ge......
  • 关于Objective-C头文件中的property为readonly,外部还能set成功
    起初是同事和我说,property为readonly,外部还能set成功。实在没想明白。常规的写法,.m中可以直接set成功,而外部创建的FCTest对象,无法set成功(见FCObject)。FCTest.h@interfaceFCTest:NSObject@property(nonatomic,copy,readonly)NSString*name;@endFCTest.m@inte......
  • LTE 参考信号 CRS DMRS SRS
    PCI(小区物理编号)PCI=PSS+3*SSS     一共504种(主、辅同步信号)PSS的取值范围为(0/1/2)SSS的取值范围为(0~167) 下行RS(ReferenceSignal)参考信号,也成导频信号RSRP,参考信号信号功率作用:信号质量的评估通俗解释:发送一个双方已知的序列,当序列里面出错较多的时候,说明......