C语言(*(volatile unsigned CHAR *)addr)理解

Posted Welljia

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言(*(volatile unsigned CHAR *)addr)理解相关的知识,希望对你有一定的参考价值。

嵌入式中C语言操作寄存器

看ARM程序时,会看到类似如下的代码:

#define SREG     (*(volatile unsigned CHAR *)0x5F)

在嵌入式系统编程中,一般要求程序员能够利用C语言访问固定的内存地址。按C语言的语法来看,这个地址应该由指针类型来表示,所以在操作某个内存地址,比如0x5F时,其步骤如下:

  1. 将地址强制转换为指针类型 :(unsigned CHAR * )0x5F
    假设ARM是8位的寄存器,就用char,是32位,就用long了,这时候地址被强制转换成了指向unsigned CHAR / LONG类型。
  2. 对指针变量解引用: *(unsigned CHAR * )0x5F
    这样就能操作指针所指向的地址内容了
  3. 为了防止编译器的优化,加上volatile关键字:*(volatile unsigned CHAR * )0x5F
    volatile作为类型限定符,会要求C编译不要去优化而省略,每次都直接读值,这在嵌入式中很重要,防止各种意想不到的改变。
  4. 最后规范代码,采用宏定义,用SREG替代,将#define宏中的参数用括号括起来,所以最后的形式就是:
    #define SREG (*(volatile unsigned CHAR * )0x5F )
    这个时候就可以采用如下方式对这个内存地址进行操作了
    实际的例子如下:
#define SREG     (*(volatile unsigned char * )0x5C)
unsigned char temp;
temp = SREG3; // 读这个地方的值
SREG = temp; // 往这个地方写值
  1. 若是将0x5F用变量addr替代,则可以变换形式为:
    #define REG32(addr) (*(volatile unsigned long * )(addr))
  2. 若想使该addr地址所在指针不要改变它的指向,则可以加上const,那形式就变成为:
    #define REG32(addr) (*(volatile unsigned long * const)(addr))

实际例子如下:

#define REG32(addr)     (*(volatile unsigned long const * )(addr))
unsigned long temp;
temp = REG32(addr); // 读addr这个地方的值
REG32(addr) = temp; // 往addr这个地方写值

以上是关于C语言(*(volatile unsigned CHAR *)addr)理解的主要内容,如果未能解决你的问题,请参考以下文章

(*(volatile unsigned long *)详解

(*(volatile unsigned long *)详解

关于C语言中unsigned变量的问题?

在C语言中,unsigned char是啥类型?

在C语言中,unsigned char是啥类型

在C语言中,unsigned char是啥类型