當(dāng)前位置:首頁 > 嵌入式 > 嵌入式教程
[導(dǎo)讀]基于AT91RM9200的LCD驅(qū)動(dòng)程序設(shè)計(jì)

1 引言
嵌入式系統(tǒng)應(yīng)用于工控領(lǐng)域越來越普及,對(duì)于傳統(tǒng)工控產(chǎn)品升級(jí)換代發(fā)揮重要作用,隨著由此帶來的工控產(chǎn)品性能的大幅提高,與之對(duì)應(yīng)的較高檔次、友好的人機(jī)界面需求也不斷增大。為此,Linux也出現(xiàn)了許多圖形界面軟件包,在其開發(fā)和移植過程種都涉及到底層LCD的驅(qū)動(dòng)。本文針對(duì)一款基于AT91RM9200芯片的工業(yè)級(jí)嵌入式系統(tǒng)開發(fā)板,加上可擴(kuò)展外圍控制器SLD13506,在Linux2.4.19操作系統(tǒng)下,通過編寫其驅(qū)動(dòng)程序,再用arm-linux-gcc進(jìn)行編譯,使ARM9開發(fā)板添加12.1英寸TFT彩色LCD顯示功能。

2 硬件介紹
AT91RM9200是一款基于ARM920T內(nèi)核的高性價(jià)比、低功耗、32位的ARM 芯片,擁有獨(dú)立的16K指令和16K數(shù)據(jù)cache,寫緩存,全功能的MMU虛擬內(nèi)存管理單元,內(nèi)部的16KB SDRAM和128KB ROM,在180MHz工作頻率下運(yùn)行速度為200MIPS。AT91RM9200集成了EBI, PMC,I/O,Ethernet,USB,MCI,SSC,UASRT, SPI,RTC,TWI等接口及其控制器。卻沒有針對(duì)LCD顯示的控制器,所以本系統(tǒng)添加了SLD13506作為顯示控制器,來實(shí)現(xiàn)LCD的顯示。
SLD13506是EPSON公司一款用于LCD/CRT/TV的顯示控制芯片,其體系結(jié)構(gòu)應(yīng)低成本、低功耗的嵌入式市場的需求而設(shè)計(jì),多用于移動(dòng)通訊工具,手提電腦和辦公自動(dòng)化。它可支持4/8位單色或4/8/16位彩色的單板單顯示接口,直接支持9/12位TFT/D-TFD彩色顯示,在18位TFT/D-TFD下可顯示65536種顏色,最大分辨率可為18bpp800×600。通過編寫SLD13506的設(shè)備驅(qū)動(dòng)程序,讀寫一系列的寄存器來產(chǎn)生驅(qū)動(dòng)信號(hào),就可以驅(qū)動(dòng)LCD的顯示。

3設(shè)備驅(qū)動(dòng)程序
Linux是Unix操作系統(tǒng)的一種變種,類似于大部分Unix系統(tǒng),Linux應(yīng)用程序獨(dú)立于底層硬件運(yùn)行,用戶無需關(guān)心硬件問題,但需要為每一款硬件編寫驅(qū)動(dòng)程序【²】,從而構(gòu)成完整的運(yùn)行系統(tǒng)。模塊化驅(qū)動(dòng)程序后,用戶操作只需要通過一組標(biāo)準(zhǔn)化的調(diào)用來完成。把這些調(diào)用映射到設(shè)備特定的操作上,則是設(shè)備驅(qū)動(dòng)程序的任務(wù)【2】。
系統(tǒng)調(diào)用是操作系統(tǒng)內(nèi)核和應(yīng)用程序之間的接口,設(shè)備驅(qū)動(dòng)程序是操作系統(tǒng)內(nèi)核和機(jī)器硬件之間的接口。設(shè)備驅(qū)動(dòng)程序?yàn)閼?yīng)用程序屏蔽了硬件的細(xì)節(jié),這樣在應(yīng)用程序看來,硬件設(shè)備只是一個(gè)設(shè)備文件,應(yīng)用程序可以象操作普通文件一樣對(duì)硬件設(shè)備進(jìn)行操作。這種機(jī)制可稱為“文件層-驅(qū)動(dòng)層”接口方式。
應(yīng)用程序是通過設(shè)備文件操作硬件,實(shí)際上是通過如 open,read,write,close系統(tǒng)調(diào)用來實(shí)現(xiàn)的。而file_operations這一關(guān)鍵的數(shù)據(jù)結(jié)構(gòu)就把系統(tǒng)調(diào)用和驅(qū)動(dòng)程序關(guān)聯(lián)起來,它的形式如下:
struct file_operations {
struct module *owner;
int (*read) (struct inode * ,struct file *, char ,int);
int (*write) (struct inode * ,struct file *, off_t ,int);
int (*ioctl) (struct inode * ,struct file *, unsined int ,unsigned long);
int (*mmap) (struct inode * ,struct file *, struct vm_area_struct *);
}
這個(gè)結(jié)構(gòu)的每一個(gè)成員的名字都對(duì)應(yīng)著一個(gè)系統(tǒng)調(diào)用,應(yīng)用程序利用系統(tǒng)調(diào)用在對(duì)設(shè)備文件進(jìn)行諸如read/write操作時(shí),系統(tǒng)調(diào)用通過設(shè)備文件的主設(shè)備號(hào)找到相應(yīng)的設(shè)備驅(qū)動(dòng)程序,然后讀取這個(gè)數(shù)據(jù)結(jié)構(gòu)相應(yīng)的函數(shù)指針,接著把控制權(quán)交給該函數(shù),這是linux的設(shè)備驅(qū)動(dòng)程序工作的基本原理。所以編寫LCD驅(qū)動(dòng)程序的主要工作就是編寫子函數(shù)來填充file_operations的各個(gè)域。[!--empirenews.page--]

4 linux下的幀緩沖區(qū)
Linux操作系統(tǒng)為LCD等顯示設(shè)備提供了幀緩沖區(qū),它是一種驅(qū)動(dòng)程序接口【3】。幀緩沖區(qū)為圖像硬件設(shè)備提供了一種抽象化處理,那么應(yīng)用軟件無需關(guān)心硬件設(shè)備的細(xì)節(jié),就可以通過定義明確的界面來訪問圖像硬件設(shè)備。所以為LCD硬件設(shè)備編寫驅(qū)動(dòng)程序,實(shí)際上就是為幀緩沖區(qū)編寫驅(qū)動(dòng)程序, 它們的關(guān)系如下圖1-1所示。

500)this.style.width=500;" border="0" />

把硬件設(shè)備抽象化為幀緩沖區(qū)設(shè)備,首先要指定LCD的幀緩沖區(qū),在fb.h文件中,其結(jié)構(gòu)體fb_info為幀緩沖設(shè)備定義了驅(qū)動(dòng)層接口,它不僅包含了底層函數(shù),而且還可以記錄設(shè)備狀態(tài)的數(shù)據(jù)。每個(gè)幀緩沖設(shè)備都與一個(gè)fb_info結(jié)構(gòu)相對(duì)應(yīng)。其中成員變量modename為設(shè)備名稱,fontname為顯示字體,node為指向底層操作的函數(shù)的指針:
struct fb_info {
char modename[40];  
   kdev_t node;   int open;                 
   struct fb_var_screeninfo var;      
   struct fb_fix_screeninfo fix;           
   struct fb_cmap cmap;
   struct fb_ops *fbops;   …};
??1)Struct fb_fix_screeninfo:定義了顯示輸出設(shè)備自身的屬性,如屏幕緩沖區(qū)的物理地址和長度。
??2)Struct fb_var_screeninfo:記錄了幀緩沖設(shè)備和指定顯示模式的可修改信息。它包括顯示屏幕的分辨率、每個(gè)像素的比特?cái)?shù)和一些時(shí)序變量。其中變量xres定義了屏幕一行所占的像素?cái)?shù),yres定義了屏幕一列所占的像素?cái)?shù),bits_per_pixel定義了每個(gè)像素用多少個(gè)位來表示。
幀緩沖設(shè)備也屬于字符設(shè)備(文件設(shè)備的一種,還有塊設(shè)備),要實(shí)現(xiàn)“文件層-驅(qū)動(dòng)層”的接口方式來對(duì)LCD進(jìn)行驅(qū)動(dòng)就必須定義一個(gè)類似于File_operationes可實(shí)現(xiàn)文件設(shè)備操作數(shù)據(jù)結(jié)構(gòu)fb_ops,然后編寫子函數(shù)對(duì)fb_ops的各個(gè)域進(jìn)行填充:
struct fb_ops {
    struct module *owner;
    int (*fb_get_fix)(struct fb_fix_screeninfo *fix, int con, struct fb_info *info);
    int (*fb_get_var)(struct fb_var_screeninfo *var, int con, struct fb_info *info); 
    int (*fb_set_var)(struct fb_var_screeninfo *var, int con, struct fb_info *info); 
    int (*fb_get_cmap)(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);
    int (*fb_set_cmap)(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);
    int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma); …};
這個(gè)結(jié)構(gòu)中的每一個(gè)字段都必須指向驅(qū)動(dòng)程序中實(shí)現(xiàn)特定操作的函數(shù),對(duì)于不支持的操作,對(duì)應(yīng)的字段可以被置為NULL,或留到后續(xù)開發(fā)時(shí)載添加。

5 幀緩沖區(qū)驅(qū)動(dòng)程序的編寫
    為LCD顯示設(shè)備指定了幀緩沖區(qū)后,要實(shí)現(xiàn)LCD驅(qū)動(dòng)實(shí)際上就是編寫幀緩沖區(qū)的驅(qū)動(dòng)程序。在編寫幀緩沖區(qū)的驅(qū)動(dòng)程序時(shí),首先要對(duì)指出與fb_info中fb_ops結(jié)構(gòu)相對(duì)應(yīng)的成員函數(shù),然后分別實(shí)現(xiàn)它們,再對(duì)LCD的顯示進(jìn)行初始化。只有實(shí)現(xiàn)了這些成員子函數(shù)才能在“文件層-驅(qū)動(dòng)層”實(shí)現(xiàn)系統(tǒng)調(diào)用【4】,從而使應(yīng)用程序可直接操作顯示硬件?,F(xiàn)分述如下:
5.1 編寫結(jié)構(gòu)體fb_info中fb_ops及其對(duì)應(yīng)的成員函數(shù)
本系統(tǒng)中定義了特定操作所對(duì)應(yīng)的成員函數(shù),代碼如下:
static struct fb_ops s1d13xxxfb_ops = {
    owner:     THIS_MODULE,
    fb_get_fix:  s1d13xxxfb _get_fix,
    fb_get_var:  s1d13xxxfb _get_var,
    fb_set_var:  s1d13xxxfb _set_var,
    fb_get_cmap: s1d13xxxfb _get_cmap,
    fb_set_cmap: s1d13xxxfb _set_cmap,
    fb_mmap:  s1d13xxx_mmap,    …};[!--empirenews.page--]
這些函數(shù)都是用來設(shè)置和獲取驅(qū)動(dòng)層接口fb_info結(jié)構(gòu)體中的成員變量的,在第4小節(jié)中已提到,當(dāng)應(yīng)用程序?qū)υO(shè)備文件進(jìn)行操作或讀取設(shè)備文件狀態(tài)時(shí)會(huì)調(diào)用這些函數(shù)。如fb_get_fix和fb_get_var函數(shù)得到的是fb_info中變量fix和var,fb_set_var則是對(duì)var變量進(jìn)行設(shè)置。這些函數(shù)都要根據(jù)實(shí)際的操作來進(jìn)行實(shí)現(xiàn),下面以s1d13xxxfb_set_var函數(shù)為例來說明這些子函數(shù)都是如何實(shí)現(xiàn)的。它的作用是設(shè)置fb_info里的結(jié)構(gòu)體fb_var_screeninfo變量var的值:
static int s1d13xxxfb_set_var(struct fb_var_screeninfo *var,){
memset(var, 0, sizeof(struct fb_var_screeninfo));
    var->xres =  800;     //顯示800×600分辨率
    var->yres =  600;
    var->bits_per_pixel = 16;  //定義16位顏色數(shù)
    …  //其他與LCD硬件有關(guān)的參數(shù)}

5.2 LCD初始化
LCD控制器是通過產(chǎn)生顯示驅(qū)動(dòng)信號(hào)來驅(qū)動(dòng)LCD的。在驅(qū)動(dòng)程序里,用戶只需要通過讀寫一系列的寄存器,就可以完成配置和顯示控制。而Linux下驅(qū)動(dòng)程序總是先調(diào)用module_init()函數(shù),括號(hào)里的參數(shù)是所要初始化的文件設(shè)備的初始化函數(shù)。因此在本系統(tǒng)中,通過調(diào)用module_init(s1d13xxxfb_init)初始化函數(shù)來實(shí)現(xiàn)對(duì)一系列寄存器的設(shè)置。s1d13xxxfb_init初始化函數(shù)部分代碼如下:
int __init s1d13xxxfb_init(char *dummy){
  S1D_INDEX  s1dReg;  //定義寄存器數(shù)組
  S1D_VALUE  s1dValue;  //設(shè)置所對(duì)應(yīng)寄存器的值
  plateform_init_video();    //LCD顯示電壓寄存器的初始化
  for (i = 0; i < sizeof(aS1DRegs)/sizeof(aS1DRegs[0]); i++) {
      s1dReg = aS1DRegs[i].Index;  //把設(shè)定的值寫入寄存器
      s1dValue = aS1DRegs[i].Value;…  }  
local_s1d13xxxfb_open();   //打開sld13506控制器
  strcpy(fb_info.modename, "s1d13xxx"); //復(fù)制modename
  fb_info.node = -1; //指向底層函數(shù)指針賦初值為-1
  fb_info.fbops = &s1d13xxxfb_ops; //對(duì)結(jié)構(gòu)體fb_info.fbops初始化 
  fbgen_get_var(&disp.var, -1, &fb_info.gen.info); //獲取當(dāng)前的顯示參數(shù)
  fbgen_do_set_var(&disp.var, 1, &fb_info.gen); //設(shè)置顯示控制器參數(shù)
  fbgen_install_cmap(0, &fb_info.gen); //根據(jù)LCD硬件參數(shù)開辟顯存空間
 
  if (register_framebuffer(&fb_info.gen.info) < 0) {//注冊(cè)顯示驅(qū)動(dòng)程序,不成功則報(bào)錯(cuò)
    return -EINVAL;  }
  printk("Installed sld31506 frame buffer n”);   };
首先對(duì)LCD的背光燈進(jìn)行點(diǎn)亮,LCD顯示是一種被動(dòng)的顯示模式,它不能發(fā)光,只能依靠控制透射或反射周圍環(huán)境的光來達(dá)到顯示的目的,因此,必須通過寫電壓寄存器,用高電平對(duì)LCD顯示器加3.2伏電壓來實(shí)現(xiàn)背光燈的點(diǎn)亮。其函數(shù)的部分代碼如下:[!--empirenews.page--]
void plateform_init_video(void) {
       AT91_SYS->PIOC_PER |= 0x00004000; //對(duì)LCD加3.2伏的背光電壓[5]
    AT91_SYS->PIOC_OER |= 0x00004000;
    AT91_SYS->PIOC_SODR |= 0x00004000; …}
本文系統(tǒng)采用的12.1寸TFT彩色LCD最佳分辨率是800×600,但通過前面對(duì)結(jié)構(gòu)Struct fb_var_screeninfo的賦值并不能真正設(shè)定其分辨率,因?yàn)榻Y(jié)構(gòu)Struct fb_var_screeninfo的值只是作為一個(gè)顯示記錄來用,必須通過設(shè)定寄存器的值,才能達(dá)到需要的分辨率。其中最主要的幾個(gè)寄存器及其代表意義如圖1-2所示:

500)this.style.width=500;" border="0" />

本系統(tǒng)通過一個(gè)數(shù)組對(duì)寄存器進(jìn)行賦值,在初始化函數(shù)中利用s1dReg和s1dValue這兩個(gè)實(shí)參寫入:
static S1D_REGS aS1DRegs[] = {
…//前一個(gè)值為寄存器標(biāo)識(shí),后一個(gè)為寫入寄存器的值[6]
{0x0032,0x63},   // 分辨率水平象素 =) ((032h)bit6-0)+ 1) × 8為800
{0x0038,0x57},   // 分辨率垂直象素0 = (038h)bit7-0 +分辨率垂直象素1為600
{0x0039,0x02},   // 分辨率垂直象素1 = ((039h)bit1-0) + 1
{0x0042,0x00},   // (042h)bit7-0幀緩沖區(qū)開始地址
{0x0043,0x00},   // (043h)bit7-0
{0x0044,0x00},   // (044h)bit3-0
{0x0046,0x20},   // (046h)bit7-0幀緩沖區(qū)寬度偏移量  
{0x0047,0x03},   // (047h)bit2-0
{0x0048,0x00},   // lcd顯示圖像的起始位置地址0x00
}
至此,彩色LCD的驅(qū)動(dòng)程序框架基本上已經(jīng)完成了,通過5.1小節(jié)中已實(shí)現(xiàn)的成員函數(shù)調(diào)用就可以對(duì)幀緩沖區(qū)的顯示內(nèi)容進(jìn)行控制調(diào)試,步驟是把編寫好驅(qū)動(dòng)程序用arm-linux-gcc進(jìn)行交叉編譯,然后通過串口在目標(biāo)板上運(yùn)行insmod/remod命令動(dòng)態(tài)加載/卸載來調(diào)試。若程序已調(diào)試好就可以把它編譯到Linux內(nèi)核,燒錄進(jìn)目標(biāo)板的flash就可以完成LCD的顯示了。

6 結(jié)束語
文中介紹了Linux操作系統(tǒng)下的LCD驅(qū)動(dòng)程序基本原理和框架,以及幀緩沖設(shè)備的作用。以基于AT91RM9200芯片的開發(fā)板和SLD13506控制器為例,編寫了一個(gè)典型的幀緩沖設(shè)備驅(qū)動(dòng)程序。LCD顯示器的型號(hào)雖然很多,但其驅(qū)動(dòng)的編寫基本上是類似的,可以通過本文介紹的步驟對(duì)其它彩色LCD進(jìn)行編寫。

本文作者創(chuàng)新點(diǎn):本文是介紹了基于ARM9技術(shù)的芯片的LCD顯示屏驅(qū)動(dòng)控制程序,給出實(shí)際項(xiàng)目中已實(shí)現(xiàn)了的操作,對(duì)同類芯片中的LCD驅(qū)動(dòng)或其他硬件驅(qū)動(dòng)有很好的參考價(jià)值。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動(dòng)力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉