#define A (* (volatile unsigned long *) 详解

#defineA (* (volatile unsigned long*) 0x48000000 )

对于不同的计算机体系结构,设备可能是端口映射,也可能是内存映射的。如果系统结构支持独立的IO地址空间,并且是端口映射,就必须使用汇编语言完成实际对设备的控制,因为C语言并没有提供真正的“端口”的概念。如果是内存映射,那就方便的多了。

举个例子,比如像寄存器A(地址假定为0x48000000)写入数据0x01,那么就可以这样设置了。

#define A (*(volatile unsigned long *) 0x48000000 )

...

A = 0x01;

...

这实际上就是内存映射机制的方便性了。其中volatile关键字是嵌入式系统开发的一个重要特点。volatile(可变的)这个关键字说明这变量可能会被意想不到地改变,这样编译器就不会去假设这个变量的值了。这种“意想不到地改变”,不是由程序去改变,而是由硬件去改变

volatile限定编译器不对这个指针的指向的存储单元进行优化, 即不用通用寄存器暂时代替这个指针的指向的存储单元,而是每次取值都直接到指针的指向的存储单元取值.volatile主要用于变量会异步改变的情况下,

主要有三个方面:

1.cpu外设寄存器

2.中断和主循环都会用到的全局变量

3.操作系统中的线程间都会用到的公共变量.上述表达式拆开来分析,

首先(volatile unsigned long *) 0x48000000的意思是把0x48000000强制转换成volatile unsigned long类型的指针,即对指针的操作的范围是从0x48000000开始的4个字节(long型).暂记为p,那么就是#define A *p,即AP指针指向位置的内容了。这里就是通过内存寻址访问到寄存器A,可以读/写操作!

对于不同的计算机体系结构,设备可能是端口映射,也可能是内存映射的。如果系统结构支持独立的IO地址空间,并且是端口映射,就必须使用汇编语言完成实际对设备的控制,因为C语言并没有提供真正的端口的概念。如果是内存映射,那就方便的多了。

#define IOPIN (*((volatile unsigned long *) 0xE0028000))

为例:作为一个宏定义语句,define是定义一个变量或常量的伪指令。首先( volatile unsigned long * )的意思是将后面的那个地址强制转换成 volatile unsigned long * unsigned long * 是无符号长整形,volatile 是一个类型限定符,如const一样,当使用volatile限定时,表示这个变量是依赖系统实现的,以为着这个变量会被其他程序或者计算机硬件修改,由于地址依赖于硬件,volatile就表示他的值会依赖于硬件。

volatile 类型是这样的,其数据确实可能在未知的情况下发生变化。比如,硬件设备的终端更改了它,现在硬件设备往往也有自己的私有内存地址,比如显存,他们一般是通过映象的方式,反映到一段特定的内存地址当中,这样,在某些条件下,程序就可以直接访问这些私有内存了。另外,比如共享的内存地址,多个程序都对它操作的时候。你的程序并不知道,这个内存何时被改变了。如果不加这个voliatile修饰,程序是利用catch当中的数据,那个可能是过时的了,加了 voliatile,就在需要用的时候,程序重新去那个地址去提取,保证是最新的。归纳起来如下:

1. volatile变量可变 允许除了程序之外的比如硬件来修改他的内容

2. 访问该数据任何时候都会直接访问该地址处内容,即通过cache提高访问速度的优化被取消

对于((volatile unsigned long *) 0xE0028000)为随硬件需要定义的一种地址,前面加上“*”指针,为直接指向该地址,整个定义约定符号IOPIN代替,调用的时候直接对指向的地址寄存器写内容既可。这实际上就是内存映射机制的方便性了。其中volatile关键字是嵌入式系统开发的一个重要特点。上述表达式拆开来分析,首先(volatile unsigned long *) 0xE0028000的意思是把0xE0028000强制转换成volatile unsigned long类型的指针,暂记为p,那么就是#define A *p,即AP指针指向位置的内容了。这里就是通过内存寻址访问到寄存器A,可以读/写操作。

对于(volatileunsignedchar*)0x20我们再分析一下,它是由两部分组成:

1)(unsignedchar*)0x200x20只是个值,前面加(unsignedchar*)表示0x20是个地址,而且这个地址类型是unsignedchar,意思是说读写这个地址时,要写进unsignedchar的值,读出也是unsignedchar

2)volatile,关键字volatile确保本条指令不会因C编译器的优化而被省略,且要求每次直接读值。例如用 while(unsignedchar*)0x20)时,有时系统可能不真正去读0x20的值,而是用第一次读出的值,如果这样,那这个循环可能是个死循环。用了volatile则要求每次都去读0x20的实际值。

那么(volatileunsignedchar*)0x20是一个固定的指针,是不可变的,不是变量。而char*u则是个指针变量。

再在前面加"*":*(volatileunsignedchar*)0x20则变成了变量(普通的unsignedchar变量,不是指针变量),如果#definei(*(volatileunsignedchar*)0x20),那么与unsignedchari是一样了,只不过前面的i的地址是固定的。

那么你的问题就可解答了,(*(volatileunsignedchar*)0x20)可看作是一个普通变量,这个变量有固定的地址,指向0x20。而0x20只是个常量,不是指针更不是变量。

源文档 <http://blogold.chinaunix.net/u3/98301/showart_2064027.html>

一、关键字(Keywords) 关键字是C语言预定义的保留标识符,具有特定功能,不可作为变量名使用。例如: 数据类型: i n t int、 f l o a t float、 c h a r char、 d o u b l e double 控制结构: i f if、 e l s e else、 f o r for、 w h i l e while、 s w i t c h switch、 c a s e case 函数相关: r e t u r n return、 v o i d void、 s i z e o f sizeof C int main() { // int和return均为关键字 return 0; } 二、标识符(Identifiers) 标识符用于命名变量、函数等实体,规则包括: 由字母/下划线开头,可包含数字 区分大小写( A g e Age与 a g e age不同) 不可与关键字冲突 C int age; // 合法标识符 float _value; // 合法标识符 char 3year; // 非法(数字开头) 三、常量(Constants) 1. 整型常量 十进制: 123 123 八进制: 0173 0173(以0开头) 十六进制: 0 x 7 B 0x7B 2. 浮点常量 标准形式: 3.14 3.14 科学计数法: 1.23 e − 5 1.23e−5 3. 字符常量 用单引号包裹: ′ A ′ ′ A ′ 、ParseError: KaTeX parse error: Undefined control sequence: \n at position 2: '\̲n̲'(转义字符) 4. 枚举常量 C enum Color { RED, GREEN }; // RED=0, GREEN=1 5. 宏定义常量 C #define PI 3.14159 // 预处理阶段替换 四、字符串字面量(String Literals) 双引号包裹的字符序列,以ParseError: KaTeX parse error: Undefined control sequence: \0 at position 2: '\̲0̲'结尾: C char str[] = "hello"; // 存储为['h','e','l','l','o','\0'] 五、运算符(Operators)3 类型 示例 算术运算符 + +、 − −、 ∗ ∗、 / / 赋值运算符 = =、 + = +=、 ∗ = ∗= 关系运算符 = = ==、 > >、 ! = != 逻辑运算符 ParseError: KaTeX parse error: Expected 'EOF', got '&' at position 1: &̲&、$ 三目运算符 ( a > b ) ? a : b (a>b)?a:b 六、分隔符(Separators)1 大括号 :定义代码块 分号 ; ;:语句结束符 逗号 , ,:变量分隔 冒号 : ::三目运算符/标签 C if(a>b) { // {}为代码块分隔符 printf("%d",a);以下是一份针对C语言基础语法中 **关键字、标识符、常量、字符串字面量、运算符、分隔符** 的详细说明笔记: --- ## **1. 关键字(Keywords)** - **定义**:C语言预定义的保留字,具有特殊含义,不可用作标识符。 - **分类**(C89标准共32个关键字): ```c auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while ``` - **注意事项**: - 所有关键字均为小写(如 `int` 正确,`INT` 不是关键字)。 - 例如:`int num;` 中的 `int` 用于声明整型变量。 --- ## **2. 标识符(Identifiers)** - **定义**:由程序员自定义的名称,用于变量、函数、结构体等。 - **命名规则**: 1. 由字母、数字、下划线组成,且**首字符不
03-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值