原创 理解#define SREG (*(volatile unsigned char *)0x5F)

2010-11-29 15:43 1524 4 4 分类: MCU/ 嵌入式
嵌入式系统编程,要求程序员能够利用C语言访问固定的内存地址。既然是个地址,那么按照C语言的语法规则,这个表示地址的量应该是指针类型。所以,知道要访问的内存地址后,比如0x5F,
   第一步是要把它强制转换为指针类型
(unsigned char *)0x5F,AVR的SREG是八位寄存器,所以0x5F强制转换为指向
unsigned char类型。
   volatile(可变的)这个关键字说明这变量可能会被意想不到地改变,这样编译器就不会去假设这个变量的值了。这种“意想不到地改变”,不是由程序去改变,而是由硬件去改变——意想不到。
   第二步,对指针变量解引用,就能操作指针所指向的地址的内容了
   *(volatile unsigned char *)0x5F
   第三步,小心地把#define宏中的参数用括号括起来,这是一个很好的习惯,所以#define SREG    (*(volatile unsigned char *)0x5F)

    类似的,如果使用一个32位处理器,要对一个32位的内存地址进行访问,可以这样定义#define RAM_ADDR     (*(volatile unsigned long  *)0x0000555F)
    然后就可以用C语言对这个内存地址进行读写操作了
    读:tmp = RAM_ADDR;
    写:RAM_ADDR = 0x55;


对于(volatile unsigned char *)0x20我们分析一下,它是由两部分组成:
 1)(unsigned char *)0x20,0x20只是个值,前面加(unsigned char *)表示0x20是个地址,而且这个地址类型是unsigned char ,意思是说读写这个地址时,要写进unsigned char 的值,读出也是unsigned char 。
 2)volatile,关键字volatile 确保本条指令不会因C 编译器的优化而被省略,且要求每次直接读值。例如用while((unsigned char *)0x20)时,有时系统可能不真正去读0x20的值,而是用第一次读出的值,如果这样,那这个循环可能是个死循环。用了volatile 则要求每次都去读0x20的实际值。那么(volatile unsigned char *)0x20
是一个固定的指针,是不可变的,不是变量。而char  *u则是个指针变量。再在前面加"*":*(volatile unsigned char *)0x20则变成了变量(普通的unsigned char变量,不是指针变量),如果#define i (*(volatile unsigned char *)0x20),那么与unsigned char i是一样了,只不过前面的i的地址是固定的。
=》(*(volatile unsigned char *)0x20)可看作是一个普通变量,这个变量有固定的地址,指向0x20。而0x20只是个常量,不是指针更不是变量

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
4
关闭 站长推荐上一条 /3 下一条