指向外设寄存器的指针 c语言关键词,C中的绝对地址及外设寄存器访问

C51:

#define XBYTE ((unsigned char volatile xdata *) 0)

释:XBYTE被定义成(unsigned char volatile xdata *)

0,0为一个基于寄存器的指针(可理解为:只不过这个指针用一个二进制常量标识,且其指向的内存单元在定义时就以固定为该二进制常量且不可更改.),其存

储内型为2指向xdata,偏移量为0,这样XBYTE成为指向xdata零地址的指针,通过XBYTE[0]可以读写该地址处的数据;同样通过

XBYTE[8000]也可以访问xdata空间绝对地址为8000处的数据。

待证中:通过*XBYTE,*(XBYTE+8000)是否可以对相应地址进行读写?

ARM_ADS:

#define BCFG0  (*((volatile unsigned int *) 0xFFE00000))

释:首先0xFFE00000为一个指针没错,且该指针为unsigned

int型指向0xFFE00000内存单元,BCFG0被定义为对该指针做“*”指针运算,这样,BCFG0可理解为对内存单元0xFFE00000进行

标识的一个int32u型普通变量,同过BCFG0可是实现对该寄存器的读写访问。

转载网络上的一些文章:

------------------------------------------------------------------------

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

这样的定义,总是感觉很奇怪,不知道为什么,今天终于有了一点点心得,请大虾们多多批砖~~~

嵌入式系统编程,要求程序员能够利用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;

zhiwei 发表于 2005-4-30 18:59 AVR 单片机

定义未volatile是因为它的值可能会改变,大家都知道为什么改变了;

果在一个循环操作中需要不停地判断一个内存数据,例如要等待SREG的I标志位置位,因为SREG也是映射在SRAM空间,为了加快速度,编译器可能会编

译出这样的代码:把SREG读取到Register中,然后不停地判断Register相应位。而不会再读取SREG,这样当然是不行了,因为程序或其它

事件(中断等)会改变SREG,结果很可能是一个死循环出不来了。如果定义成volatile型变量,编译的代码是这样的:每次要操作一个变量的时候都从

内存中读取一次。

#define SREG (*(volatile unsigned char *)0x5F) 之后,可以进行如下基本操作,

unsigned char temp,*ptr;

temp=SREG;把SREG值保存到temp中

SREG=temp;把temp的值赋给SREG

ptr = & SREG; 不知对否,大家试一下。

-----------------------------------------------------------------------

对于(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只是个常量,不是指针更不是变量

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值