Renesas_iodefine_address

Renesas I/O寻址操作

    • 写在前面
    • 问题发现
    • 常见处理
    • 追根溯源
    • 精益求精

写在前面

基于Renesas CS+CC编译器中RL78/G13芯片族 编程时对未操作时的错误进行追因,思考与总结的小发现和记录。

问题发现

在瑞萨官方的编译器CS+CC里进行编程中,无法识别我们常用的I/O位操作。例如流水灯实验中,需要频繁的对某个I/O进行位操作赋值来改变他的输出信号,但是编译器只识别整个I/O寄存器。
以下用代码段说明:

//以P11为例,我们希望编译器可以识别以下代码,方便理解与操作。
P11 = 1;
P1.1 = 1

这两句都是我们常用的为P11这位赋值输出高电平的写法,但是在CS+CC这个瑞萨自家的编译器中,并不识别这样的书写规则。

常见处理

以前面对这样的情况,我们往往要通过对整个端口寄存器进行移位赋值的操作。

P1 = P1|(1<<1);

但是代码操作符叠加复杂以及代码长度增加,简单的某一位赋值的操作变得繁琐又容易犯错。

追根溯源

在不断地跳转定义源头和头文件引用后,找到了根源,定义在一个叫iodefine.h的文件中,(这个文件是在硬件资源配置完之后编译器生成的)。在这个文件中定义了像这样的结构体:

typedef struct
{
    unsigned char no0:1;
    unsigned char no1:1;
    unsigned char no2:1;
    unsigned char no3:1;
    unsigned char no4:1;
    unsigned char no5:1;
    unsigned char no6:1;
    unsigned char no7:1;
} __bitf_T;

#define P1           (*(volatile __near unsigned char  *)0xFF01)
#define P1_bit       (*(volatile __near __bitf_T *)0xFF01)

在上面的代码中,CS+CC编译器的iodefine.h文件中定义了一个8bit的结构体__bitf_T(如果是16位,或者32位只需要往上叠加对应个no个数即可),并定义了P5整个寄存器的地址,以及P5_bit这个__bitf_T型的结构体的地址,都指向PORT5的寄存器地址。此时,我们可以通过以下的简单操作即可实现对应I/O的位操作。
P1_bit.no1 = 1
如果是16位的寄存器,可以通过下面的结构体和配置去进行类似的访问与操作。

typedef struct
{
    unsigned char no0:1;
    unsigned char no1:1;
    unsigned char no2:1;
    unsigned char no3:1;
    unsigned char no4:1;
    unsigned char no5:1;
    unsigned char no6:1;
    unsigned char no7:1;
    unsigned char no8:1;
    unsigned char no9:1;
    unsigned char no10:1;
    unsigned char no11:1;
    unsigned char no12:1;
    unsigned char no13:1;
    unsigned char no14:1;
    unsigned char no15:1;
} __bitf_T2;

借用这个结构就可以完成对16位寄存器的单独位操作。

精益求精

  1. 如果这个位操作用的比较频繁,还可以进一步通过宏定义进行封装。
#define P11         P1_bit.no1
//这样就可以用最开始大家都习惯的写法来进行操作
P11 = 1
  1. 还有一种封装思路
#define P11       (((volatile __near __bitf_T *)0xFF01)->no1)
P11 = 1;

#define P11 (((volatile __near __bitf_T *)0xFF01)->no1)
P11 = 1;

这种思路比上面的会少一层对头文件的引用依赖。

你可能感兴趣的:(囹圄起舞,#,Renesas瑞萨,嵌入式,Renesas瑞萨,iodefine.h,单片机寻址,单片机位操作)