您好,欢迎来到钮旅网。
搜索
您的当前位置:首页volatileunsignedchar详解

volatileunsignedchar详解

来源:钮旅网


volatileunsignedchar详解

标签:*(volatile unsigned char*)

(*(volatile unsigned char *)0x56000010)

以前看到#define SREG (*(volatile unsigned char *)0x5F)这样的定义,总是感觉很奇怪,不知道为什么,今天终于有了一点点心得,请大虾们多多批砖~~~ 嵌入式系统编程,要求程序员能够利用C语言访问固定的内存地址。既然是个地址,那么按照C语言的语法规则,这个表示地址的量应该是指针类型。所以,知道要访问的内存地址后,比如0x5F,

第一步是要把它强制转换为指针类型

(unsigned char *)0x5F,AVR的SREG是八位寄存器,所以0x5F强制转换为指向unsi gned char类型。

volatile(可变的)这个关键字说明这变量可能会被意想不到地改变,这样编译器就不会去假设这个变量的值了。这种“意想不到地改变”,不是由程序去改变,而是由硬件去改变——意想不到。

第二步,对指针变量解引用,就能操作指针所指向的地址的内容了

*(volatile unsigned char *)0x5F

第三步,小心地把#define宏中的参数用括号括起来,这是一个很好的习惯,所以#defi ne 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

默认分类2010-04-07 23:58:38 阅读49 评论0 字号:大中小

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

PS:设计过程的最后阶段,曾出现接受的串口数据结构体变量值不停改变。经讨论后,认为是编译器可能将这个变量优化到CPU寄存器中,从而中断时,寄存器值将保存到堆栈;中断恢复后,堆栈值覆盖回以后的改变值,使得两种值在不断的相互覆盖。考虑到这种情况后,先将该结构体定义为一种类型,再将接受数据的此类型变量同时定义为volatile 类型。此后,具有volatile类型的变量将告诉编译器其内容会被硬件修改,因此,编译器不会对其进行优化。

因此,假如一个变量除了可被程序改变以外还可被其他代理(如硬件)改变,为了保证程序在运行时能每次都读取该变量的最新值,而不是读取因为编译器的优化存放该变量的临时寄存器中的值(存放临时寄存器中的值是不变的),应该使用volatile。

区别:

1、volatile unsigned char *p

2、const unsigned char *p

3、unsigned char * const p

4、volatile const unsigned char *p

1、指明p所指的值(*p)是可被硬件修改的,提示编译器不要对其进行优化。

2、const指明p所指的值(*p)不可被程序修改

3、p不能被程序修改,但p所指的值(*p)可以被修改。

4、p所指的值(*p)不可被程序修改,但是可以被其他代理如硬件修改(如一个变量存放系统时钟),提示编译器不要对其优化。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- niushuan.com 版权所有 赣ICP备2024042780号-2

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务