2012年1月16日 星期一

單晶片一些相關的用法

指標:
[ 定義 ]
一個變數,用來存放變數位址。

[ 宣告方式 ]
1.
int i = 100;
int *ptr = &i; //宣告ptr為指標,存入i的位址

2.
int i = 100;
int * ptr; //宣告ptr為指標
ptr = &i; //存入i的位址。不可以寫成*ptr = &i
函式型態的別名:
很多寫 C/C++ 的人都把 typedef 當成#define 來使用。
誠然,像這樣的定義
typedef unsigned short WORD;
就相當於
#define WORD unsigned short
但就本義來說,#define 是字串的取代,例如
#define WORD Hello!
在程式任何使用到 WORD 的地方會用 Hello! 取代 WORD

typedef看來不怎麼有用是吧!?非也,由於所謂 C/C++ 的型態是很廣義的,使用typedef
可以使程式看起來簡潔易懂且不容易出錯。下面是幾個typedef的應用例子:

簡單型態的別名
typedef unsigned char BYTE;//定義無號單字節的型態
typedef unsigned short WORD;//定義無號雙字節的型態
typedef unsigned long DWORD;//定義無號四字節的型態
//嗯!這三行沒什麼大不了,用#define也可以做

結構型態的別名
typedef struct StructTag{
int mA;
int mB;
}STRUCTTAG, *PSTRUCTTAG;
當要建立這個結構的物件時,就可以用別名 STRUCTTAG 和 PSTRUCTTAG,例如
STRUCTTAG StructObj;
PSTRUCTTAG pStructObj;
就相當於
struct StructTag StructObj;
struct StructTag *pStructObj;

函式型態的別名
如果你有一個 library 提供了字串轉整數的函式
int HexToInt(char *str);//十六進位字串轉整數
int DecToInt(char *str);//十進位字串轉整數
當你的程式要使用這些函式時,就必需include這些函式的定義,但用typedef會
更簡潔:
typedef int ToInt(char *str);
//上面這行定義了一個需傳入字串(char *)且返回整數(int)的函式型態別名
//叫 ToInt
ToInt HexToInt,DecToInt;//宣告HexToInt,DecToInt這兩個函式
現在你的程式可以呼叫HexToInt(...),DecToInt(...)了。

在Windows,通常是應用程式呼叫API來工作的,但由於某種需求,Windows API
會反過來呼叫應用程式的函式,這種函式稱之為 callback function
callback function 對API來說只有該傳入那些參數和返回值型態,沒有函式名稱而用函式
指標來呼叫(事實上Windows也不可能用程式的函式名稱來呼叫)。這時使用函式型態的別名
來宣告函式指標就特別好用了。
舉個例子吧!建立一個新的行程(Thread)的函式:
CWinThread* AfxBeginThread( AFX_THREADPROC pfnThreadProc,
LPVOID pParam, int nPriority = THREAD_PRIORITY_NORMAL, UINT
nStackSize = 0, DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );

其中AFX_THREADPROC就是一個函式型態的別名
它的定義是
typedef UINT (AFX_CDECL *AFX_THREADPROC)(LPVOID);
//AFX_THREADPROC 是一個傳入一個指標參數返回UINT型態值的函式
//指標的名稱(AFX_CDEL是標明函式呼叫為 __cdecl(C style calling convention))

用這個宣告,不論API或應用程式本身都很方便,如應用程式可以這樣來
開啟行程:
CWinThread* pMyThread=AfxBeginThread(
(AFX_THREADPROC)MyThreadFunc,............
是不是很簡潔明瞭?嗯...MyThreadFunc算不算 callback function 有點疑義,但做為 typedef 的使用例子應沒問題的

typedef :

將資料型態定義成自己希望的識別字,方便撰寫程式.

比方說

typedef int number; // 表示number識別字和int相同.
int n; // 宣告一個int變數n.
number n; // 宣告一個number變數n,而number其實就是int.

又比方說有一個結構叫做record

struct record
{
int number;
struct record *next;
}

typedef struct record Node; // 表示Node識別字和struct record相同.

struct record record1; // 宣告一個record結構名為record1.

Node record1; // 宣告一個Node 結構名為record1,而Node 其實就是 struct record的意思.

除了省下了打字的力氣以外,由於不同的機器使用的資料型態都不太一樣,換機器跑程式時,只要修改typedef就好了,增加了C的可攜性.

[ 參考 ] http://home.educities.edu.tw/peterhuang1/Clan/CLanTypedef.htm

2.
struct t_Point
{
int x; int y;
}; // 注意,這裡最後一個分號不能省略

int main(int argc, char* argv[])
{
struct t_Point a, b;
// . . .
return 0;
}

顯然,這種方法沒有typedef更加直觀(在C++中,main函數第一行的struct關鍵字可以省略,但在標準C中,省略該關鍵字會出現編譯錯誤)。

此外,對於定義鏈接隊列中的結點,我們可以這樣實現:

typedef struct t_node
{
int Value;
struct t_node *next;
} Node;

當然也可以這樣定義:

typedef strcut t_node Node;
struct t_node
{
int Value;
Node *next;
};

結構中的冒號; 位域 :

位域
  有些信息在存儲時,並不需要佔用一個完整的字節, 而只需占幾個或一個二進制位。例如在存放一個開關量時,只有0和1 兩種狀態, 用一位二進位即可。為了節省存儲空間,並使處理簡便,C語言又提供了一種數據結構,稱為「位域」或「位段」。所謂「位域」是把一個字節中的二進位劃分為幾個不同的區域, 並說明每個區域的位數。每個域有一個域名,允許在程序中按域名進行操作。 這樣就可以把幾個不同的對象用一個字節的二進制位域來表示。一、位域的定義和位域變量的說明位域定義與結構定義相仿,其形式為:

  struct 位域結構名

  { 位域列表 };

  其中位域列表的形式為: 類型說明符 位域名:位域長度

  例如:

struct bs
{
 int a:8;
 int b:2;
 int c:6;
};


  位域變量的說明與結構變量說明的方式相同。 可採用先定義後說明,同時定義說明或者直接說明這三種方式。例如:

struct bs
{
 int a:8;
 int b:2;
 int c:6;
}data;


  說明data為bs變量,共佔兩個字節。其中位域a占8位,位域b占2位,位域c占6位。對於位域的定義尚有以下幾點說明:

  1. 一個位域必須存儲在同一個字節中,不能跨兩個字節。如一個字節所剩空間不夠存放另一位域時,應從下一單元起存放該位域。也可以有意使某位域從下一單元開始。例如:

struct bs
{
 unsigned a:4
 unsigned :0
/*空域*/ unsigned b:4 /*從下一單元開始存放*/
 unsigned c:4
}


  在這個位域定義中,a佔第一字節的4位,後4位填0表示不使用,b從第二字節開始,佔用4位,c佔用4位。

  2. 由於位域不允許跨兩個字節,因此位域的長度不能大於一個字節的長度,也就是說不能超過8位二進位。
  3. 位域可以無位域名,這時它只用來作填充或調整位置。無名的位域是不能使用的。例如:
struct k
{
 int a:1
 int :2 /*該2位不能使用*/ int b:3
 int c:2
};


  從以上分析可以看出,位域在本質上就是一種結構類型, 不過其成員是按二進位分配的。

  二、位域的使用

  位域的使用和結構成員的使用相同,其一般形式為: 位域變量名·位域名 位域允許用各種格式輸出。

main(){
 struct bs
 {
  unsigned a:1;
  unsigned b:3;
  unsigned c:4;
 } bit,*PBit;
 bit.a=1;
 bit.b=7;
 bit.c=15;
 printf("%d,%d,%d\n",bit.a,bit.b,bit.c);
 PBit=&bit;
 PBit->a=0;
 PBit->b&=3;
 PBit->c=1;
 printf("%d,%d,%d\n",PBit->a,PBit->b,PBit->c);
}

  上例程序中定義了位域結構bs,三個位域為a,b,c。說明了bs類型的變量bit和指向bs類型的指針變量PBit。這表示位域也是可以使用指標的。

  程序的9、10、11三行分別給三個位域賦值。( 應注意賦值不能超過該位域的允許範圍)程序第12行以整型量格式輸出三個域的內容。第13行把位域變量bit的地址送給指針變量PBit。第14行用指針方式給位域a重新賦值,賦為0。第15行使用了復合的位運算符"&=", 該行相當於: PBit->b=PBit->b&3位域b中原有值為7,與3作按位與運算的結果為3(111&011=011,十進制值為3)。同樣,程序第16行中使用了復合位運算"=", 相當於: PBit->c=PBit->c1其結果為15。程序第17行用指針方式輸出了這三個域的值。

Camera相關知識

AE锁
    AE是automatic exposure自动曝光控制装置的缩写,AE锁就是锁定于某一AE设置,用于自动曝光时人为控制曝光量,保证主体曝光正常。
    使用AE锁有几点需要注意:1、手动方式或自拍时不能使用自动曝光(AE)锁。 2、按下自动曝光(AE)锁之后不要再调节光圈大小。 3、用闪光灯摄影时不要使用(AE)锁。
    CCD
    中文译为:电子耦合组件(charged coupled device),它就像传统相机的底片一样,是感应光线的电路装置,你可以将它想象成一颗颗微小的感应粒子,铺满在光学镜头后方,当光线与图像从镜头透过、投射到CCD表面时,CCD就会产生电流,将感应到的内容转换成数码资料储存起来。CCD像素数目越多、单一像素尺寸越大,收集到的图像就会越清晰。因此,尽管CCD数目并不是决定图像品质的唯一重点,我们仍然可以把它当成相机等级的重要判准之一。
CMOS
    comple-mentary metal-oxicle-semiconductor,中文译为:互补金属氧化物半导体
    DPOF
    DPOF指的是数码打印顺序指令,用于在存储介质(影像记忆卡等)上记录信息。在此格式下,你可以设定将数码相机拍摄的那些影像进行打印以及进行打印多少张。
    EXIF
    所谓EXIF (exchangerable image file format for digital still cameras) ,就是由jeita(电子信息技术产业协会)制定的、决定记录jpeg 图像和声音的文件上的附加信息的方式的规格。     
   EXIF 2.2
    EXIF 2.2 版是一种新改版的数码相机文件格式,其中包含实现最佳打印所必需的各种拍摄信息。
    PTP
    PTP是英语“图片传输协议(picture transfer protocol)”的缩写。
    PTP是最早由柯达公司与微软协商制定的一种标准,符合这种标准的图像设备在接入Windows XP系统之后可以更好地被系统和应用程序所共享,尤其在网络传输方面,系统可以直接访问这些设备用于建立网络相册时图片的上传、网上聊天时图片的传送等。
    当然,这主要是为方便计算机知识不多的普通用户的,使相机、应用软件、网站....结合在一起更容易地完成一些傻瓜式功能。
CMOS
    comple-mentary metal-oxicle-semiconductor,中文译为:互补金属氧化物半导体
    DPOF
    DPOF指的是数码打印顺序指令,用于在存储介质(影像记忆卡等)上记录信息。在此格式下,你可以设定将数码相机拍摄的那些影像进行打印以及进行打印多少张。
    EXIF
    所谓EXIF (exchangerable image file format for digital still cameras) ,就是由jeita(电子信息技术产业协会)制定的、决定记录jpeg 图像和声音的文件上的附加信息的方式的规格。     
   EXIF 2.2
    EXIF 2.2 版是一种新改版的数码相机文件格式,其中包含实现最佳打印所必需的各种拍摄信息。
    PTP
    PTP是英语“图片传输协议(picture transfer protocol)”的缩写。
    PTP是最早由柯达公司与微软协商制定的一种标准,符合这种标准的图像设备在接入Windows XP系统之后可以更好地被系统和应用程序所共享,尤其在网络传输方面,系统可以直接访问这些设备用于建立网络相册时图片的上传、网上聊天时图片的传送等。
    当然,这主要是为方便计算机知识不多的普通用户的,使相机、应用软件、网站....结合在一起更容易地完成一些傻瓜式功能。
图片传输协议
    图片传输协议英文全称为:picture transfer protocol,缩写为PTP。 PTP是由柯达与微软协商制定的一种标准,符合这种标准的图像设备在接入windows XP系统之后可以更好地被系统和应用程序所共享,尤其在网络传输方面,系统可以直接访问这些设备用于建立网络相册时图片的上传、网上聊天时图片的传送等。当然,这主要是为方便计算机知识不多的普通用户的,使相机、应用软件、网站等结合在一起更容易地完成一些傻瓜式功能。    
    图像储存格式
    由于数码相机拍下的图像文件很大,储存容量却有限,因此图像通常都会经过压缩再储存。最常见的图像储存格式就是jpeg和TIFF档,jpeg经过高度压缩,能使档案变为原先的1/4、1/8或1/16大小左右,因此可以省下不少储存空间,不过相对也会让原始图像资料有所损失,许多相机都会提供特定的压缩比例供使用者自己选择。
TIFF文件几乎未经压缩,所以图像会比Jpeg保持地更完整。不过因为图像分辨率越高、压缩越小就越占记忆空间,所以拍照时必须兼顾对图像的品质要求与记忆卡容量。举例来说,一张8MB的内存卡存640×480分辨率、高压缩格式的照片可能可以存80张,可是如果存1024×768、未压缩格式的照片就只能存3张,差异其实非常大,因此拍摄前必须先预设储存模式或干脆准备好足够的内存卡。
    无损和有损压缩
    无损压缩和有损压缩是数码图像文件压缩的两种类型。 无损压缩是对文件本身的压缩,和其它数据文件的压缩一样,是对文件的数据存储方式进行优化,采用某种算法表示重复的数据信息,文件可以完全还原,不会影响文件内容,对于数码图像而言,也就不会使图像细节有任何损失。而有损压缩是对图像本身的改变,在保存图像时保留了较多的亮度信息,而将色相和色纯度的信息和周围的像素进行合并,合并的比例不同,压缩的比例也不同,由于信息量减少了,所以压缩比可以很高,图像质量也会相应的下降。
GT镜头
    GT镜头是指美能达独特设计的多片多组配合巧妙的镜头组件,镜头镜片使用高档低色散光学玻璃,其中包含多枚模铸成型非球面镜片等等。也就是说美能达的 G 系列高档专业传统相机(银盐相机)使用的镜头称为AF镜头,而美能达将生产 G 系列镜头的工艺技术应用于数码相机的设计生产中,所生产出的产品就称为 GT 镜头。     
    蔡司镜头
    即zeiss。蔡司是一家致力於应用研究,对於光学、玻璃技术、精密技术以及电子等高品质的产品开发、制造、销售有贡献的德国企业,从 1846 年开始,carl zeiss 已开设生产显微镜的工作坊。zeiss镜头,专业的摄像,摄影镜头     
  广角镜
    即wide angle,又叫短焦镜头。广角镜因焦距非常短,所以投射到底片上的景物就变小了扩阔镜头拍摄角度,除可拍摄更多景物,更能在狭窄的环境下拍摄出宽阔角度的影像。
    IESP自动聚焦
    IESP英语intelligent electro selective pattern(智能电子选择模式)的缩写。IESP自动聚焦是数码相机在对焦范围内做多重区块分割(有资料称分割方式为扇形分割),再将分割区块所测得焦点位置综合运算,根据主体的不同状态,确定最佳焦距位。IESP自动聚焦在奥林巴斯数码相机的介绍中经常看。
变焦
    镜头的另一个重点在变焦能力,所谓的变焦能力包括光学变焦(optical zoom)与数码变焦(digital zoom)两种。两者虽然都有有助于望远拍摄时放大远方物体,但是只有光学变焦可以支持图像主体成像后,增加更多的像素,让主体不但变大,同时也相对更清晰。通常变焦倍数大者越适合用于望远拍摄。光学变焦同传统相机设计一样,取决于镜头的焦距,所以分辨率及画质不会改变。数码变焦只能将原先的图像尺寸裁小,让图像在lcd屏幕上变得比较大,但并不会有助于使细节更清晰。因此购买数码相机时,我们往往建议大家留意光学变焦的倍数。目前中端相机普遍都有3倍左右的光学变焦,不过也有具超长变焦功能的产品,例如10倍光学变焦的机种。
    光学变焦
    是依靠光学镜头结构来实现变焦,变焦方式与35mm相机差不多,就是通过摄像头的镜片移动来放大与缩小需要拍摄的景物,光学变焦倍数越大,能拍摄的景物就越远。如今的数码相机的光学变焦倍数大多在2倍-5倍之间,也有一些码相机拥有10倍的光学变焦效果。家用摄录机的光学变焦倍数在10倍~22倍,能比较清楚的拍到70米外的东西。使用增倍镜能够增大摄录机的光学变焦倍数。
    数字变焦
    即digital zoom,实际上是画面的电子放大,把原来CCD影像感应器上的一部份像素使用“插值”处理手段做放大,将CCD影像感应器上的像素用插值算法将画面放大到整个画面。通过数码变焦,拍摄的景物放大了,但它的清晰度会有一定程度的下降,有点像VCD或DVD中的zoom功能,所以数码变焦并没有太大的实际意义。目前数码相机的数码变焦一般在6倍左右,摄像机的数码变焦在44倍-600倍左右,实际使用中有40倍就足够了。如果变焦倍数不够,我们可以在镜头前加一增倍镜。如果拍摄的视角小,可以相应的加一广角镜。     
    智能变焦
    全新独有的sony智能变焦功能.可放大变焦拍摄,不会将微粒放大,令放大的影像也能保持原有的细致质素.智能变焦因应不同影像尺寸的选择,提供不同程度的强化变焦功能.有别于数码变焦,智能变焦能保持画质与原本影像相同。
    程序式自动曝光
    程序式自动曝光是电子技术与人工智能相结合的产物,采用这种方式曝光时,相机不但能根据光线条件算出合适的曝光量,还能自动选择合适的曝光组合。
    超焦距
    由于镜头的后景深比较大,人们称对焦点以后的能清晰成像的距离为超焦距。傻瓜相机一般就利用了超焦距,利用短焦镜头在一定距离之后的景物都能比较清晰成像的特点,省去对焦功能,所以,一般低档的傻瓜相机并不能自动对焦,只是利用了超焦距而已。正如前面所说的,“清晰”不是一个绝对的概念,超焦距范围内的景物并非真正的清晰成像,由于不在对焦点上,肯定是模糊的,只是模糊的程度一般人能够接受而已,这就是傻瓜相机拍摄的底片不能放大得太大的原因。

單晶片C語言,Volatile使用

轉貼  http://ethanjob.blogspot.com/2007/02/volatile.html

volatile宣告 在C裡面有volatile這個宣告,通常是說這個變數會被外在routine改變, 在kernel裡面通常是指會被interrupt handler(有時就是硬體中斷的routine) 改變值,也就是被非同步的改變的變數。例如 unsigned long vloatile jiffies; jiffies在kernel是時間每次hardware的中斷會來改這個值 在asm裡面是說這個東西compiler時,gcc不要雞婆作optimized,因為 最佳化的結果,compiler會把code按照他想的方法放到記憶體裡, 但是有的code我們需要特定指定他一定要在某個記憶體上, 在kernel裡常有這樣情形發生,我們可以用 __asm__ __volatile__宣告一段assembly的code是不要做最佳化的。 例如cli sti #define disable() __asm__ __volatile__ ("cli"); #define enable() __asm__ __volatile__ ("sti");

[ 例1 ]

Volatile這玩意兒用在單晶片的C語言較多

例如:
Volatile char wait;
void xxx(void)
{
wait=1;
while (wait!=0);
.....
.....
}
void timer0(void) interrupt 1
{
wait=0;
.......
}

xxx()中就是等一個timer中斷才執底下工作.
如果不寫Volatile會被編譯器省略掉.
因為wait=1;何來wait會等於0

[ 例2 ]

volatile sig_atomic_t read_flag = 1;

volatile是一個關鍵字(keyword),用來修飾詞資料型態,與const有對應的關係。
是語言關鍵字的話,就不會出現在標頭檔內的定義。
volatile sig_atomic_t read_flag = 1;
read_flag是一個為sig_atomic_t的資料型態,透過volatile的修飾,說明sig_atomic_t在程式中,可以在任何的時間下被修改 ,
也就是說,你的程式可能同一時間不止一個程序在使用。
可能主程式main在使用的同時,I/O Device或另一個thread也在利用或指定這個read_flag
來透過溝通的作用。

[ 例3 ]

http://www.programmersheaven.com/articles/pathak/article1.htm

[ 參考 ]

http://www.programmersheaven.com/articles/pathak/article1.htm

http://www.blueshop.com.tw/board/show.asp?subcde=BRD20060329085552QSX&fumcde=FUM20050124191259IGD&rplcnt=5