Lcd幀緩衝設備

緩衝(framebuffer)是Linux爲顯示設備提供的一個接口,是把顯存抽象後的一種設備,它允許上層應用程序在圖形模式下直接對顯示緩衝區進行讀寫操作,這種操作是抽象的,統一的。用戶不必關心物理顯存的位置,換頁機制等等具體細節。這些都由Framebuffer設備驅動程序完成的。緩衝驅動應用廣泛,在linux的桌面系統中,Xwindow服務器就是利用幀緩衝進行窗口繪製的。尤其是通過幀緩衝設備可顯示漢字點陣,成爲linux漢化的唯一可行方案。
    緩衝設備對應的設備文件爲/dev/fb*,如果系統有多個顯卡,Linux下還可支持多個緩衝設備,最多可達32個,分別爲/dev/fb0~/dev/fb31,而/dev/fb則爲當前缺省的緩衝設備,通常指向/dev/fb0。當然在嵌入式系統中支持一個顯示設備就夠了。緩衝設備爲標準字符設備,主設備號爲29,次設備號爲0到31,分別對應/dev/fb0~/dev/fb31

通過/dev/fb,應用程序的操作主要有一下幾種:
    1.讀/寫(read/write)/dev/fb
      相當於讀/寫屏幕緩衝區。
      cp /dev/fb0 tmp 將當前屏幕的內容拷貝到一個文件中
      cp tmp > /dev/fb0 則將圖形文件tmp顯示在屏幕上
    2.映射(map)操作
      由於Linux工作在保護模式,每個應用程序都有自己的虛擬地址空間,在應用程序不能直接訪問物理緩衝區地址的。爲此,linux在文件操作file_operations結構中提供了mmap函數,可將文件的內容應身到用戶空間。對於緩衝設備,則可通過映射操作,可將屏幕緩衝區的物理地址映射到用戶空間的一段虛擬地址中,之後用戶就可以通過讀寫這段虛擬地址訪問屏幕緩衝區,在屏幕上繪圖了。而且若干個進程可以映射到同一顯示緩衝區。實際上,使用緩衝設備的應用程序都是通過映射操作來顯示圖形的。
    3.I/O控制
     對於緩衝設備,對設備文件的ioctl操作可讀取/設置顯示設備及屏幕參數,如分辨率,顯示顏色數,屏幕大小等等。ioctl的操作是有底層的驅動程序來完成的。

在應用程序中,操作/dev/fb的一般步驟如下:
    1.打開/dev/fb設備文件
    2.用ioctrl操作取得當前顯示屏幕參數,根據屏幕參數可計算屏幕緩衝區的大小。
    3.將屏幕緩衝區映射到用戶空間。
    4.映射後就可以直接讀寫屏幕緩衝區,進行繪圖和圖片顯示了

備註:memset:作用是在一段內存塊中填充某個給定的值,它對較大的結構體或數組進行清零操作的一種最快方法。
     memcpy:作用是把一塊內存中的字節,不管其中的內容是什麼,從內存的一個區域複製到另一個區域。

  12月9日晚22:40於實驗室

____________________________________________________________________

典型程序段分析:

   #include
int main(){
        int fbfd = 0;
        struct fb_var_screeninfo vimnfo; 
        struct fb_var_screeninfo finfo;
        long int screensize = 0; 
      
        /*open the device*/ 
        fbfd = open ("/dev/fb0",O_RDWR);
 
        ioctl(fbfd,FBIOGET_FSCREENINFO,&finfo);
        ioctl(fbfd,FBIOGET_FSCREENINFO,&vimnfo);
       
        screensize = vimnfo.xres * vimnifo.yres * vimnfo.bit_per_pixel /8 ;
       
        fbp=(char*)mmap(0,screensize,PROT_READ|PROT_WRITE,MAP_SHARED,fbfd,0);
......
}
幀緩衝驅動的編寫

    幀緩衝設備屬於字符設備,其目的就是通過配置MX1寄存器,在一段制定的內存與LCD之間建立一個自動傳輸的通道。這樣,任何程序只要修改這段內存中的數據,就可以改變LCD上的顯示內容。幀緩衝設備驅動也採用“文件層-驅動層”的接口方式。在文件層次上,Linux爲其定義了:

     static struct file_operation fb_fops={

         owner:THIS_MODULE
         read:fb_read, /*讀操作*/
         write:fb_write, /*寫操作*/
         ioctl:fb_ioctl, /*控制操作*/
         mmap:fb_mmap, /*映射操作*/
         open:fb_open, /*打開操作*/
         release:fb_release, /*關閉操作*/

  }

    其中的成員函數都在文件linux/dev/vimdeo/fbmem.c中定義。

    由於顯示設備的特殊性,在驅動層的接口中不但要定義底層函數,還要有一些紀錄設備狀態的函數。Linux爲幀緩衝設備定義的驅動測藉口爲struct fb_info結構, 在include/linux/fb.h中定義。

                                 12月10日上午於實驗室

____________________________________________________________________

 
對驅動程序中要用到的幾個關鍵成員的說明
     fb_info:紀錄了幀緩衝設備的全部信息,包括設備的參數,狀態以及操作函數指針。每一個幀緩衝設備都必須對應一個fb_info結構。其中成員變量modename爲設備名稱,fontname爲顯示字體,fboops爲指向底層操作的函數的指針,這些函數是需要驅動程序人員編寫的。成員fb_var_screeninfo和fb_var_screeninfo也是結構體。其中var_screeninfo紀錄用戶可修改的顯示控制器參數,包括屏幕分辨率和每個象素的比特數。fb_var_screeninfo中的xres定義屏幕一行有多少個點,yres定義屏幕一列有多少個點,bits_per_pixel定義每個點用多少個字節表示。而fb_fix_screeninfo中紀錄用戶不能修改的顯示控制器的參數,如屏幕緩衝區的物理地址,長度。當對緩衝區設備進行映射操作時,就是從fb_fix_screeninfo中取得緩衝區相應的物理地址的。上面所說的數據成員都是需要在驅動程序中初始化和設置的。
     
編寫幀緩衝驅動程序的步驟爲:
     1.編寫初始化函數:初始化函數首先初始化LCD控制器,通過寫寄存器設置的顯示模式和顯示顏色數,然後分配LCD顯示緩衝區。在Linux可通過kmalloc函數分配一片連續空間。
      例如LCD顯示方式爲320*240,16位彩色,需要分配的顯示緩衝區位320*240*2=150K字節,緩衝區通常分配在大容量的片外SDRAM中,起始地址保存在LCD控制寄存器中。
      最後是初始化一個fb_info結構,填充其中的成員變量,並調用register_framebuffer(&fb_info),將fb_info登記入內核。
      2.編寫結構fb_info中函數指針fb_ops對應的成員函數:對於嵌入式系統的簡單實現,只需要下列三個函數就可以了:
       struct fb_ops{
       ......
       int(*fb_get_fix)(struct fb_fix_screeninfo *fix,int con,struct fb_info *info);  
       int(*fb_get_var)(struct fb_var_screeninfo *fix,int con,struct fb_info *info);   
       int(*fb_set_fix)(struct fb_fix_screeninfo *fix,int con,struct fb_info *info); 
       ......   
}
       struct fb_ops在include/linux/fb.h中定義。這些函數都是用來設置/獲取fb_info結構中的成員變量的。當應用程序對設備文件進行Ioctl操作時會調用它們,例如,對於fb_get_fix(),應用程序傳入的是fb_fix_screeninfo結構,在函數中對其成員變量賦值,主要是smem_start(緩衝區其實地址)和smem_len(緩衝區長度),最終返回給應用程序。而fb_set_var函數的傳入參數是fb_var_screeninfo,函數中,需要對xres,yres和bits_per_pixel賦值。驅動程序編寫完成後,開發者可以選擇將其編譯位動態加載模塊,或者靜態地編譯入內核中。
 
LCD API
     LCD API是一套應用層編程入口,它將屏幕緩衝區的物理地址映射到用戶空間的一段虛擬地址中,之後用戶就可以通過這段虛擬地址訪問屏幕緩衝區,在屏幕上繪圖了。
     lcd_initalize完成屏幕緩衝區的物理地址映射到用戶空間的一段虛擬地址中,以後用戶就可以通過讀寫這段虛擬地址訪問屏幕緩衝區,在屏幕上繪圖了。
     lcd_putpixel是畫圖的基礎,直線,矩形,橢圓,圓都是在此繼承上的算法。
     lcd_textout在使用這個函數顯示字符的時候,需要將/usr/local/src/example//bin/hz16字符庫文件。
      
 
LCD顯示原理:
     LCD是基於液晶光電效應的顯示器件。液晶顯示器的工作原理就是利用液晶的物理特性,在通電時,液晶排列變得有次序,使光線容易通過;不通電時排列變得混亂,阻止光線的通過。即液晶工作時,使用的是外部的光線,自己本身並不發光,所以與CRT相比,液晶顯示器的耗電量較低。
    LCD中使用的位液晶照明的主要有兩種:傳送式和反射式。傳送式屏幕要使用外加光源照明,成爲背光(backlight),照明光源安裝在LCD背後。傳送式LCD在正常光線及暗光線下,顯示效果很好,但在戶外,尤其在日光下,很難辨清顯示內容。
    反射式屏幕,則不需要外加照明電源,使用周圍環境的光線,這樣,反射式屏幕就沒有背光,所以這種屏幕在戶外或光線充足的室內,纔會有出色的顯示效果,但在一般室內光線下,這種顯示屏的顯示效果不及背光傳送式的。
 
灰度顯示原理:
    實際上,LCD顯示屏並不是設置成不同的亮度去驅動每一個象素的,它對象素要麼顯示,要麼關閉。LCD顯示屏的一個常用指標就是它的反應時間,反應時間指得是一個象素從顯示到關閉所花費的時間,典型的是幾百ms。一種調試技術被用於驅動每個象素,即用整個固定時間週期的一部分驅動每個象素。
     LCD控制器內部有1個16週期計數器,用於產生16週期的間隔。當驅動象素時,它讀幀緩衝數據所指的,在調色寄存器中的半字節數據。該數據確定位16週期間隔裏象素顯示的次數。例如該值等於4,則該象素每個4個時鐘週期顯示1次,等於整個16週期間隔的4/16。即認爲該象素以最大亮度的1/4進行顯示。
 
彩色顯示原理:
    彩色顯示時,每個象素點有3個子色彩象素(RGB),灰度顯示的技術應用到彩色顯示中,每個子彩色象素有15個濃度的感覺效果。可用RGB三種顏色的15中濃度中的一種去驅動1個象素點。如LCD的控制器編程爲4bpp模式,可支持最高15*15*15=3 375種不同的顏色;2bpp模式時,可支持64種不同的顏色;1bpp模式時,可支持8種不同的顏色;對於一個1/4VGA顯示屏,實際象素數量等於320*400*4=921600位或115200字節,小於上面提到的最大幀緩衝限制(128K)
    另外一個顯示特性是刷新率,指的是整個數據幀被重新寫到顯示屏的頻率。如果數據寫的太慢,將影響到顯示質量;太快則顯示器的反應時間跟不上象素驅動狀態的改變。大部分顯示屏推薦的速率是70~80Hz
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章