原创 #define UBRRL (*(volatile unsigned char *)0x29)

2010-9-19 13:57 2130 3 3 分类: MCU/ 嵌入式

嵌入式C编译器肯定是要提供一种访问某个特定地址RAM的方法。例如:访问Atmega16中的UBRRL,对应RAM中的0x29单元。ICC提供的头文件是这样描述的:#define UBRRL   (*(volatile unsigned char *)0x29)


*(&i) 表示i,也就是地址为&i RAM单元的内容,那么只要


(*(volatile
unsigned char *)0x29)中的(unsigned char *)0x29表示地址为0x29的RAM单元的地址,(*(volatile unsigned char *)0x29)就是地址为0x29的RAM单元内容了。


那(unsigned char *)0x29是不是表示地址为0x29的RAM单元的地址?先定义个变量unsigned int i ;那(unsigned
char *)i就是将i强制转换成一个指向unsigned char类型变量的指针变量。由于指针变量的内容表示地址,那么(unsigned char *)i也就表示地址。这个地址是变量i中的内容,如果i=0x29,那么就是0x29单元了,(unsigned char *)0x29表示RAM的0x29单元。


简单点,就将(unsigned char *)0x29记作:将常数0x29变成一个地址值得了。


那么volatile的作用又是什么呢?


     一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样编译器就不去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保持在寄存器里的备份。


#include<pic.h>


__CONFIG(0x1832);


#define VAR0
*((unsigned char *)0x21)


#define VAR1
*((volatile unsigned char*)0x22)


void main(void)


{


       unsigned char i=0;


       VAR0 = 0xAA;


       i = VAR0;


       VAR1 = 0x55;


       i = VAR1;


    while(1);


}


 


反汇编出来的代码是:



BCF  0x3, 0x5


BCF  0x3, 0x6


CLRF  0x20


MOVLW 0xaa


MOVWF       0x21


MOVWF       0x20   
;并未重新读取VAR0的值


MOVLW 0x55


MOVWF 0x22


MOVF    0x22,W 
;重新读取了VAR1的值


MOVWF 0x20



这也就是定义寄存器的时候要用volatile的原因吧。

PARTNER CONTENT

文章评论0条评论)

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