標(biāo)題: PXA270驅(qū)動(dòng)LCD 嵌入式試驗(yàn)報(bào)告 [打印本頁(yè)]

作者: 51hei單片    時(shí)間: 2016-3-14 16:50
標(biāo)題: PXA270驅(qū)動(dòng)LCD 嵌入式試驗(yàn)報(bào)告
實(shí)驗(yàn)?zāi)康?/font>
①了解LCD控制器的基本原理
②了解LCD控制器的配置方法
③掌握字符和圖像的顯示方法和編程實(shí)現(xiàn)過程

實(shí)驗(yàn)內(nèi)容
①根據(jù)參考代碼,分析和完成LCD顯示實(shí)驗(yàn)程序代碼
②程序的編譯
③通過AXD下載編譯后的文件到實(shí)驗(yàn)板上
④調(diào)試程序,并觀察程序運(yùn)行情況
⑤引導(dǎo)程序?qū)⑻囟ǖ臐h字和符號(hào)顯示在液晶顯示屏上
⑥顯示一個(gè)或多個(gè)圖標(biāo)、背景圖像等

實(shí)驗(yàn)原理
①幀緩沖
顯示屏的顯示區(qū)域,在系統(tǒng)內(nèi)有一段存儲(chǔ)空間與之對(duì)應(yīng),通過改變存儲(chǔ)空間的內(nèi)容,便可改變顯示的內(nèi)容,該存儲(chǔ)空間成為幀緩沖或顯存。顯示屏上得每一點(diǎn)都必然與幀緩沖里的莫一位置相對(duì)應(yīng),要解決顯示屏的顯示問題,首先需要解決幀緩沖的大小以及屏上得每一像素與幀緩沖的映射關(guān)系。
②LCD控制器
PXA270內(nèi)部集成了LCD控制器LCDC,它提供了PXA270處理器與顯示屏的接口。LCDC的作用是將幀緩沖中的數(shù)據(jù)傳輸?shù)絃CDC的內(nèi)部,經(jīng)過處理后輸出到LCD的輸入引腳上。
③DMA控制器
LCDC內(nèi)部有七個(gè)完全獨(dú)立的DMA通道,分別用于從內(nèi)部或外部?jī)?nèi)存?zhèn)鬏斦{(diào)色板數(shù)據(jù)、幀數(shù)據(jù)、光標(biāo)數(shù)據(jù)、命令數(shù)據(jù)等到LCD控制器。在使用DMAC前,必須對(duì)其進(jìn)行初始化,DMAC被初始化完成后,它就會(huì)自動(dòng)從幀緩沖中提取數(shù)據(jù)。
④輸入FIFO
LCD控制器有七個(gè)輸入FIFO,一個(gè)16*64bit的顯示基層FIFO,一個(gè)16*64bit的顯示層FIFO,三個(gè)16*64bit顯示疊加層2FIFOs,一個(gè)16*64bit光標(biāo)FIFO,一個(gè)4*64bit命令解析FIFO。DMAC的每次操作都會(huì)從幀緩沖中數(shù)據(jù)傳輸?shù)狡渲械囊粋(gè)FIFO。
⑤輸出FIFO
像素?cái)?shù)據(jù)被發(fā)送到輸出引腳之前會(huì)被鎖存到輸出FIFO。
⑥各個(gè)寄存器配置
LCD控制寄存器包括16個(gè)控制寄存器,35個(gè)DMA寄存器,2個(gè)狀態(tài)寄存器和256*3字節(jié)的內(nèi)部調(diào)色板。部分寄存器的描述及物理地址如下表所示
  地址
  
  名稱
  
  描述
  
  0x4400_0000
  
  LCCR0
  
  LCD控制寄存器0
  
  0x4400_0004
  
  LCCR1
  
  LCD控制寄存器1
  
  0x4400_0008
  
  LCCR2
  
  LCD控制寄存器2
  
  0x4400_000C
  
  LCCR3
  
  LCD控制寄存器3
  
  0x4400_0020
  
  FBR0
  
   
  
  0x4400_0024
  
  FBR1
  
   
  
  0x4400_0038
  
  LCSR
  
  LCD控制器狀態(tài)寄存器
  
  0x4400_003C
  
  LIIDR
  
  LCD控制器中斷ID寄存器
  
  0x4400_0040
  
  TRGBR
  
   
  
  0x4400_0044
  
  TCR
  
   
  
  0x4400_0200
  
  FDADR0
  
  DMA通道0幀描述符地址寄存器
  
  0x4400_0204
  
  FSADR0
  
  DMA通道0幀源地址寄存器
  
  0x4400_0208
  
  FIDR0
  
  DMA通道0幀ID寄存器
  
  0x4400_020C
  
  LDCMD0
  
  DMA通道0命令寄存器
  
  0x4400_0210
  
  FDADR1
  
  DMA通道1幀描述符地址寄存器
  
  0x4400_0214
  
  FSADR1
  
  DMA通道1幀源地址寄存器
  
  0x4400_0218
  
  FIDR1
  
  DMA通道1幀ID寄存器
  
  0x4400_021C
  
  LDCMD1
  
  DMA通道1命令寄存器
  

LCDC內(nèi)的DMAC需要初始化才可以工作,因?yàn)樵贒MAC工作之前需要提供DMAC一些相關(guān)信息:下一個(gè)幀描述符的位置、幀緩沖的位置、當(dāng)前傳送的是調(diào)色板數(shù)據(jù)還是圖像數(shù)據(jù)、幀開始/結(jié)束時(shí)是否需要產(chǎn)生中斷,以及所傳送的數(shù)據(jù)的總大小。
LCDC有四個(gè)關(guān)于幀描述符的寄存器,分別是:FDADRx,F(xiàn)SADRx,F(xiàn)IDRx,LDCMDx(x取0-6,與DMAC的相應(yīng)通道相對(duì)應(yīng)),這四個(gè)寄存器的初始化方式并不是通過程序賦值,而是通過DMAC自動(dòng)提取預(yù)先在內(nèi)存里寫好的數(shù)值,然后自動(dòng)為這些寄存器賦值。為了讓DMAC能夠找到這些預(yù)先寫好的數(shù)值,第一次使用DMAC或停用LCDC后又重新使用時(shí),需要通過軟件來初始化FDADRx(因?yàn)镕DADRx的數(shù)值就是表示下一個(gè)幀描述符的位置)。當(dāng)DMAC獲得描述符的位置后,它便從該位置獲取相應(yīng)的數(shù)值,然后將另外三個(gè)寄存器初始化,再讀取寫在內(nèi)存的為FDADRx預(yù)先準(zhǔn)備好的數(shù)值,根據(jù)該數(shù)值跳轉(zhuǎn)到指定的位置讀取其他的幀描述符。
幀描述符需要在啟動(dòng)LCDC前定義,必須定義在內(nèi)存空間,而且必須是連續(xù)的4*4字節(jié)的空間,這個(gè)空間劃分為4個(gè)單元,每個(gè)單元都是32位,并且?guī)枋龇拈_始抵制能夠被8整出,即二進(jìn)制表示的開始地址的最低3位必須為0。
LCD控制寄存器的配置在啟動(dòng)代碼中已經(jīng)用匯編代碼給出,在啟動(dòng)代碼跳轉(zhuǎn)到main函數(shù)之間已經(jīng)初始化完成,所以實(shí)驗(yàn)重點(diǎn)在于字符的顯示和圖片的顯示部分。其中圖片顯示可以直接使用Debug調(diào)試工具將二進(jìn)制的圖片文件下載到PXA270指定的顯存中來顯示。字符的顯示需要寫函數(shù)來實(shí)現(xiàn)。在裸機(jī)編程中,一般字符都以點(diǎn)陣的形式存儲(chǔ)。在顯示的時(shí)候通過讀取點(diǎn)陣數(shù)組的每一位來決定是否顯示從而完成對(duì)整個(gè)字符的顯示。

實(shí)驗(yàn)步驟
第一步 分析代碼
結(jié)合以上說明,對(duì)本實(shí)驗(yàn)提供的示例代碼分析,深入理解針對(duì)具體的硬件實(shí)現(xiàn),軟件是如何配合工作的。
第二步 程序的編譯和下載
利用ADS打開示例工程文件,執(zhí)行Project→Make,編譯、鏈接生成可執(zhí)行映像文件
第三步 觀察系統(tǒng)運(yùn)行情況,對(duì)系統(tǒng)進(jìn)行源碼調(diào)試
通過調(diào)試工具的“從文件導(dǎo)入到內(nèi)存”功能,將bmp文件導(dǎo)入到PXA270指定的顯存中,先前需要將bmp文件的前70個(gè)字節(jié)的文件頭去掉。在導(dǎo)入過程中就可以看到LCD上顯示在一行一行地刷新。

程序說明
①LCD初始化
LCD初始化部分本次實(shí)驗(yàn)的示例程序使用的是匯編代碼來寫的,主要完成對(duì)幀描述符的初始化和對(duì)LCD控制器的第0、1、2、3號(hào)控制寄存器的初始化,包括外接LCD的分辨率、顏色、接口、時(shí)序等信息的初始化。
②LCD底層驅(qū)動(dòng)
LCD底層驅(qū)動(dòng)采用C語(yǔ)言來寫,主要完成功能包括用制定顏色填充顯示屏,在LCD指定位置顯示字符,在LCD上顯示指定大小的圖片。

程序源代碼、注釋
①LCD初始化
  ldr r11, =desc_word_0  ldr r1,  =init_word_0  str r1, [r11]   nop
  nop  ldr r11, =desc_word_1  ldr r1,  =init_word_1  str r1, [r11]  nop  nop  ldr r11, =desc_word_2  ldr r1,  =init_word_2  str r1, [r11]  nop  nop  ldr r11, =desc_word_3  ldr r1,  =init_word_3  str r1, [r11]上面一段匯編代碼在內(nèi)存的指定地址(寄存器間接尋址)設(shè)定初始化幀描述符。
ldr r11, =LCCR1
  ldr r1, =init_LCCR1  str r1, [r11]  nop  nop  ldr r11, =LCCR2  ldr r1, =init_LCCR2  str r1, [r11]  nop  nop  ldr r11, =LCCR3  ldr r1, =init_LCCR3  str r1, [r11]上面一段匯編代碼設(shè)置LCD的控制寄存器1、2、3。
  ldr r11,=FDADR0  ldr r1, =init_FDADR0  str r1, [r11]  nop  nop  ldr r11, =LCCR0  ldr r1, =init_LCCR0  str r1, [r11]上面一段匯編代碼將LCD的幀描述符地址寄存器中的值設(shè)定為已經(jīng)定義好的幀描述符的地址,并且設(shè)定LCD的控制寄存器0
  ldr r11,=LCCR0  ldr r1, [r11]  orr r1,r1,#0x01  str r1,[r11]  mov pc,r14上面一段匯編代碼打開LCD控制器并且返回調(diào)用函數(shù)

②LCD底層驅(qū)動(dòng)
1)LCD.h文件
#ifndef __LCD_H__
#define __LCD_H__

#define FB0_ADDR      (0xA0500000)              //基層FramBuffer地址
#define LCD_XSIZE     (800u)                   //LCD尺寸定義
#define LCD_YSIZE     (480u)
#define CHAR_XSIZE  (16u)                    //顯示字符大小定義
#define CHAR_YSIZE  (16u)

//系統(tǒng)顏色宏定義
#define COLOR_RED          (0xF800)
#define COLOR_GREEN      (0x07E0)
#define COLOR_BLUE        (0x001F)
#define COLOR_BLACK      (0x0000)
#define COLOR_WHITE      (0xFFFF)

//字符覆蓋性顯示宏定義開關(guān)
#define CHAR_COVER

//點(diǎn)陣字庫(kù)數(shù)組申明
extern unsigned char charNum[32 * 32 * 10];

extern signed char LCD_FillColor(unsignedshort);extern signed char LCD_DrawChar(unsignedchar *, unsigned short, unsigned short, unsigned short);extern signed char LCD_DrawGraph(unsignedshort *, unsigned short, unsigned short);
#endif

2)LCD.c文件
#include "LCD.h"

/*
       名   稱:LCD_FillColor()       功   能:將整個(gè)LCD屏幕用制定的顏色填充       入口參數(shù):color:指定的顏色,推薦使用宏定義中的顏色,當(dāng)然使用R:G:B=5:6:5的半字填充也可以
       出口參數(shù):始終為0
       說   明:無       使用范例:LCD_FillColor(COLOR_GREEN);將整個(gè)屏幕填充成綠色
*/
signed char LCD_FillColor(unsigned shortcolor){
       inti;      
       for(i= 0; i < LCD_XSIZE * LCD_YSIZE; i++)              (*(volatile unsigned short *)(FB0_ADDR +i)) = color;      
       return0;}

/*
       名   稱:LCD_DrawChar()       功   能:在LCD的指定位置上顯示制定顏色的字符       入口參數(shù):*pChar:字符點(diǎn)陣數(shù)據(jù)的數(shù)組,存儲(chǔ)字符點(diǎn)陣信息,通過字符取模工具獲得
                       color:指定的顏色,推薦使用宏定義中的顏色,當(dāng)然使用R:G:B=5:6:5的半字填充也可以
                       x,y:指定的坐標(biāo),取值范圍和字符的大小有關(guān)系,0 <= x + CHAR_XSIZE <= LCD_XSIZE,y同理
       出口參數(shù):正確返回0,否則返回-1
       說   明:確保字符整個(gè)都在屏幕范圍內(nèi),否則會(huì)返回錯(cuò)誤信息       使用范例:LCD_DrawChar(ch0, COLOR_GREEN,10, 20);在LCD的(10,20)坐標(biāo)處顯示綠色的字符ch0 */
signed char LCD_DrawChar(unsigned char*pChar, unsigned short color, unsigned short x, unsigned short y){
       unsignedshort i, j;       unsignedchar k = 0;      
       //參數(shù)合理性檢查,確保字符能夠完整的在LCD上顯示
       if((x+ CHAR_XSIZE > LCD_XSIZE) || (y + CHAR_YSIZE > LCD_YSIZE))              return -1;
      
       for(j= y; j < y + CHAR_YSIZE; j++)  //列              for(i = x; i < x + CHAR_XSIZE <<1; i += 2)    //行              {
                     if(*pChar& 0x80) //檢查點(diǎn)陣數(shù)組中一個(gè)字節(jié)的每一位                            (*(volatile unsigned short *)(FB0_ADDR +j * LCD_XSIZE << 1 + i)) = color;                           
                     #ifdefCHAR_COVER   //如果定義了CHAR_COVER 將字符不顯示的部分填充黑色                            else
                                   (*(volatileunsigned short *)(FB0_ADDR + j * LCD_XSIZE << 1+ i)) = COLOR_BLACK;                     #endif
                                                
                     *pChar= *pChar << 1;                     k++;
                     
                     if(k>= 8)       //點(diǎn)陣數(shù)組中一個(gè)字節(jié)的數(shù)據(jù)檢查完成后指針指向下一個(gè)字節(jié)                     {
                            k = 0;
                            pChar++;
                     }
              }
              
       return0;}

/*
       名   稱:LCD_DrawGraph()       功   能:在LCD的指定位置上顯示一幅圖片       入口參數(shù):*pGraph:指向圖片數(shù)組的指針
                       width:圖片的寬度/pixel
                       height:圖片的高度/pixel
       出口參數(shù):正確返回0,否則返回-1
       說   明:圖片分辨率必須比LCD分辨率低,否則返回-1       使用范例:LCD_DrawGraph(*pGraph, 60, 60);在LCD上顯示一幅60x60的圖片,圖片源由pGraph指針指定
*/
signed char LCD_DrawGraph(unsigned short*pGraph, unsigned short width, unsigned short height){
       unsignedshort i, j;      
       if((width> LCD_XSIZE) || (height > LCD_YSIZE))              return -1;
              
       for(j= 0; j < height; j++)              for(i = 0; i < width << 1; i +=2)              {
                     (*(volatileunsigned short *)(FB0_ADDR + j * LCD_XSIZE << 1 + i)) = *pGraph;                     pGraph++;
              }
              
       return0;}

3)字庫(kù)文件
由于全是點(diǎn)陣數(shù)組,此處略


總結(jié)
實(shí)驗(yàn)中要求在LCD上顯示圖片,就以為需要寫函數(shù)來實(shí)現(xiàn),就寫了顯示圖片的函數(shù),后來發(fā)現(xiàn)在顯示中下半屏顯示有問題,本身加了800x480的圖片數(shù)組導(dǎo)致編譯出的調(diào)試文件體積非常大,用并口的JTAG下載非常耗時(shí),調(diào)了好長(zhǎng)時(shí)間。而實(shí)際實(shí)驗(yàn)中要求只需要將LCD初始化好,圖片的顯示可以通過在Debug方式下直接向LCD的顯示緩沖區(qū)中傳送相應(yīng)的圖片文件,這樣代碼中不需要存儲(chǔ)圖片數(shù)組,編譯生成的調(diào)試文件體積非常小,用并口JTAG下載速度非?,需要顯示圖片時(shí)用調(diào)試軟件的傳送文件到內(nèi)存即可。







歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1