c语言_结构体封装寄存器的用法,以及typedef、 volatile、static、 inline关键字用法

#define ELFIN_TIMER_BASE		0xE2500000 //定义寄存器基地址

typedef unsigned char		uchar;
typedef volatile unsigned long	vu_long;
typedef volatile unsigned short vu_short;
typedef volatile unsigned char	vu_char;
//volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。volatile 提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。所以遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。
//一个变量也许会被后台程序改变,关键字 volatile 是与 const 绝对对立的。它指示一个变量也许会被某种方式修改,这种方式按照正常程序流程分析是无法预知的,变量该变量加了volatile修饰符,则会从内存重新装载内容,而不是直接从寄存器拷贝内容。
//总结一下:volatile的作用是作为指令关键字,确保本条指令不会因为编译器的优化而省略,且要求每次直接读值,volatile可以保证对特殊地址的稳定访问。

typedef vu_char		S5PC11X_REG8;   //1字节 == 8bit 位
typedef vu_short	S5PC11X_REG16;  //2字节 == 16bit 位
typedef vu_long		S5PC11X_REG32;  //4字节 == 32bit 位

typedef struct {
	S5PC11X_REG32	TCFG0;
	S5PC11X_REG32	TCFG1;
	S5PC11X_REG32	TCON;
	S5PC11X_TIMER	ch[4];
	S5PC11X_REG32	TCNTB4;
	S5PC11X_REG32	TCNTO4;
}  S5PC11X_TIMERS; //用结构体封装了32位寄存器

/*
typedef 的作用是给已知的数据类型命名别名,因为有时使用别名更方便,语义更清晰。
1. 复杂的数据类型名称简化
    typedef 的典型应用就是可以用一个较为简短的别名去表示一个复杂数据类型 。例如,如果程序需要一个如下形式的函数指针类型
void (*)(int, int);
    并且程序中还需要定义较多这种类型的指针变量,那么每定义一个变量就写一遍这个类型,不仅麻烦而且还容易出错,所以关键字 typedef 为它定义一个简短的别名就会好得多,例如如下定义:
typedef void (*PFON)(int, int);
    这样再定义一个void (*)(int, int)类型的函数指针变量function的语句便是:
PFON function;
    显然,现在比原来清楚多了。

2.用typedef 定义与平台无关的数据类型
    众所周知,不同的程序运行平台,它们所支持的数据类型会有少许区别,如果不采取措施,程序的跨平台应用就会很困难。
    例如A平台64为数据类型为 long double,而B平台的64为数据类型为double,那么基于A平台开发的程序就不能在B平台运行。
    对于上述问题,在程序设计时,凡是64为数据的定义都是用一个别名REAL表示,如果希望程序运行于A平台,则在程序代码之前作如下声明:
typedef long double REAL;
    同理,如果希望程序运行于B平台,则在程序代码之前作如下声明:
typedef double REAL;
    因此,当跨平台时,只需修改typedef本身就行,不需对其他源码做任何修改。
    
3.增强代码可读性
    在程序设计中,经常会出现不同用途的数据属于同一种数据类型的情况,由于数据类型的标识不含有用途的信息,因此当程序规模特别大时,程序的可读性会变得非常差。此时最好为这种数据类型声明多个别名,而且在选择别名的标识时使之带有用途的信息。例如:
typedef int AGE;      // 年龄
typedef int SIZE;     // 尺寸
typedef int NUM;      // 数量
typedef int WITH;     // 宽度
typedef int FIGH;     // 高度

4.避免错误
    定义指针变量时要使用符号“*”,但这个符号可能会使人们产生误解。例如下面的定义:
int *pa, pb;   // 定义一个整型指针,一个整型变量
int *pa, *pb;  // 定义两个整型指针
    可能会将定义两个整型指针写成第一种情况,为了避免上述问题的发生,使用typedef为int*这个类型定义一个别名。如下:
typedef int * PINT;
    在这个定义之后,再定义两个整型指针就可以写成如下形式:
PINT pa, pb;
*/


static inline S5PC11X_TIMERS * S5PC11X_GetBase_TIMERS(void)
{
	return (S5PC11X_TIMERS *)ELFIN_TIMER_BASE;
}
//头文件里定义的函数,如果不加inline,就会报冲突.inline的意思是函数体在调用的地方直接展开,有点类似宏的意思.但实际上inline只是给编译器一个建议,具体采用不采用编译器自己说了算.使用inline的最实际的好处就是可以在.h文件中定义函数体而不会报冲突.
//static 表示函数只在本文件被调用
//inline 是内联函数,编译的时候会在调用该函数的地方将函数展开,优点是程序运行时省去了函数调用耗费的时间,缺点是占用了空间。 

S5PC11X_TIMERS *const timers = S5PC11X_GetBase_TIMERS(); //获取寄存器基地址
timers->TCFG0 = 0x0f00; //操作寄存器TCFG0
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值