日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

s5pv210——LCD的原理和实战

發(fā)布時間:2023/12/20 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 s5pv210——LCD的原理和实战 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

以下內(nèi)容源于朱友鵬《物聯(lián)網(wǎng)大講堂》課程的學(xué)習(xí),以及博客http://www.cnblogs.com/biaohc/p/6286946.html的學(xué)習(xí),如有侵權(quán),請告知刪除。




一、S5PV210的LCD控制器

1、FIMD結(jié)構(gòu)框圖(P1162)


  • 210的LCD控制器叫FIMD;
  • FIMD是210內(nèi)部和圖像處理相關(guān)的一些部件,在攝像頭等和圖像處理有關(guān)的部分都可以有關(guān)聯(lián)。
  • FIMD在內(nèi)部與AHB總線等相連接,在外部提供RGB接口、I80接口、YUV接口與外部相連接,我們實(shí)際使用的是RGB接口。

2、虛擬屏幕疊加(數(shù)據(jù)手冊P1194)

(1)虛擬屏幕

  • 屏幕顯示的場景,實(shí)際是很多個屏幕顯示疊加在一起的效果(譬如新聞圖像、電視臺臺標(biāo)、下方飄動的字幕新聞);
  • S5PV210的LCD控制器中有5個虛擬屏幕Window0到Window4,虛擬屏幕不存在于真實(shí)而存在于內(nèi)存中。
  • LCD顯示時,顯示對應(yīng)的內(nèi)存中的顯存區(qū)域的數(shù)值。
  • 虛擬屏幕其實(shí)就是一個內(nèi)存中的顯存區(qū)域,有幾個顯存區(qū)域就有幾個虛擬屏幕。
  • 這些虛擬屏幕都被映射到一個真實(shí)的顯示屏上面,實(shí)際效果是這幾個虛擬屏幕的顯示內(nèi)容的疊加。
  • 疊加時,上面一層會覆蓋下面一層,因此要注意誰在前誰在后,通過相關(guān)寄存器進(jìn)行設(shè)置。
(2)使用虛擬屏幕,而非整個LCD只使用一個顯存

  • 第一,可以保證不污染源圖像,方便程序處理;
  • 第二,可以減少屏幕刷新,提高顯示效率,減少CPU工作量。

3、虛擬顯示(數(shù)據(jù)手冊P1206)



(1)解決如何實(shí)現(xiàn)在小分辨率的屏幕上(真實(shí)地,即不允許修改分辨路)顯示大分辨率的圖像?

(2)按照以前的思想,當(dāng)需要在屏幕上顯示不同圖像時,需要對整個顯存區(qū)域進(jìn)行刷新。

  • 即使是顯示同一幅圖像的不同區(qū)域(比如只需要屏幕顯示移動一點(diǎn)點(diǎn)),整個屏幕對應(yīng)的顯存空間也需要整個重新刷新,工作量和完全重新顯示一幅圖像是一樣的。
  • 這使得CPU刷新屏幕的工作量很大,效率很低。

(3)如何能夠在顯示一個大圖片的不同區(qū)域時,讓CPU刷新屏幕工作量減少?

  • 方法是,虛擬顯示。
  • 在內(nèi)存中建立顯示緩存時,建立一個很大的區(qū)域,直接將大圖像全部一次性加載入顯示緩存區(qū)(這樣就可以只加載一次);
  • LCD選擇其中的一部分區(qū)域作為有效的顯示區(qū)域;
  • 通過移動有效顯示區(qū)域就可以顯示大圖像的不同區(qū)域了。

4、主要寄存器簡介

(1)DISPAY_CONTROL寄存器:設(shè)置為10或11,即RGB模式可行。


(2)VIDCON0寄存器(Video Main Control 0 Register)




  • bit0,bit1:為使能控制信號都使能;
  • bit2:選擇時鐘源,選HCLK,連的是HCLC_DSYS 為166MHz;
  • bit4:開啟分頻;
  • bit13-6:設(shè)置時鐘大小,時鐘頻率要小于控制器的最大時鐘,也要小于LCD驅(qū)動器的最大時鐘。
  • bit18:設(shè)置RGB數(shù)據(jù)傳輸為并行還是串行,因?yàn)橛?4根數(shù)據(jù)線所以為并行;
  • bit28-26:選擇為RGB模式。
(3)VIDCON1寄存器(Video Main Control 1 Register)


  • bit5,bit6:設(shè)置HSYNC和VSYNC的極性,如果LCD的高低電平脈沖是相同的話,則Normal,如果極性相反則Invert。
(3)VIDTCONn(n=0,1,2,3)寄存器:設(shè)置時序,根據(jù)LCD數(shù)據(jù)手冊中的時序來設(shè)置。




(4)WINCONn(n=0~4)寄存器


  • bit0:使能window0 ;
  • bit5-2:選擇RGB888模式;
  • bit15:設(shè)置輸出順序?yàn)?red green blue還是 blue green red,設(shè)置為1時BGR,設(shè)置為0時RGB。
(5)VIDOSD0A、VIDOSD0B兩個寄存器


  • 用來設(shè)置內(nèi)存中window0的大小;
  • 比如設(shè)置為LCD屏幕的尺寸,即左上坐標(biāo)為(0,0),右下坐標(biāo)為(1023,767)。

(6)VIDOSD0A寄存器

  • 也是設(shè)置內(nèi)存中window0的大小,比如設(shè)置為LCD屏幕的尺寸=1024*768。
(7)VIDW0xADD0Bx寄存器、VIDW0xADD1Bx寄存器


  • VIDW0xADD0Bx寄存器,設(shè)置內(nèi)存中window0的起始地址;
  • VIDW0xADD1Bx寄存器,設(shè)置內(nèi)存中window0的結(jié)束地址。
(8)SHODOWCON寄存器:設(shè)置虛擬windows顯示,以下位可以分別設(shè)置哪個windows顯示

5、底板、核心板解讀




二、代碼實(shí)戰(zhàn)

#define GPF0CON (*(volatile unsigned long *)0xE0200120) #define GPF1CON (*(volatile unsigned long *)0xE0200140) #define GPF2CON (*(volatile unsigned long *)0xE0200160) #define GPF3CON (*(volatile unsigned long *)0xE0200180)#define GPD0CON (*(volatile unsigned long *)0xE02000A0) #define GPD0DAT (*(volatile unsigned long *)0xE02000A4)#define CLK_SRC1 (*(volatile unsigned long *)0xe0100204) #define CLK_DIV1 (*(volatile unsigned long *)0xe0100304) #define DISPLAY_CONTROL (*(volatile unsigned long *)0xe0107008)#define VIDCON0 (*(volatile unsigned long *)0xF8000000) #define VIDCON1 (*(volatile unsigned long *)0xF8000004) #define VIDTCON2 (*(volatile unsigned long *)0xF8000018) #define WINCON0 (*(volatile unsigned long *)0xF8000020) #define WINCON2 (*(volatile unsigned long *)0xF8000028) #define SHADOWCON (*(volatile unsigned long *)0xF8000034) #define VIDOSD0A (*(volatile unsigned long *)0xF8000040) #define VIDOSD0B (*(volatile unsigned long *)0xF8000044) #define VIDOSD0C (*(volatile unsigned long *)0xF8000048)#define VIDW00ADD0B0 (*(volatile unsigned long *)0xF80000A0) #define VIDW00ADD1B0 (*(volatile unsigned long *)0xF80000D0)#define VIDTCON0 (*(volatile unsigned long *)0xF8000010) #define VIDTCON1 (*(volatile unsigned long *)0xF8000014)#define HSPW (0) #define HBPD (40 - 1) #define HFPD (5 - 1) #define VSPW (0) #define VBPD (8 - 1) #define VFPD (8 - 1)// FB地址 #define FB_ADDR (0x23000000) //這個是任意的,只要對齊就好 #define ROW (480) #define COL (800) #define HOZVAL (COL-1) #define LINEVAL (ROW-1)// 初始化LCD void lcd_init(void) {// 配置引腳用于LCD功能/**LED、LCD、蜂鳴等,都是與gpio口有關(guān)的*因此,涉及這些器件的,都需要初始化gpio口*而初始化gpio,需要用到相關(guān)的配置寄存器,比如GPIOCON寄存器控制引腳的模式*而至于配置哪個GPIO,需要看原理圖。*這里從原理圖知LCD接到gpf0123,所以要到相應(yīng)的配置寄存器中進(jìn)行配置*/GPF0CON = 0x22222222;GPF1CON = 0x22222222;GPF2CON = 0x22222222;GPF3CON = 0x22222222;// 打開背光 GPD0_0(PWMTOUT0)/**由原理圖可知,當(dāng)PWMTOUT0接低電平時,正5V電壓加到背光上,也就打開了背光燈*而查閱PWMTOUT0可知,它就是GPD0_0這個引腳*把GPD0_0這個引腳配置為輸出模式,通過GPD0CON寄存器配置*然后配置GPD0_0這個引腳輸出值為0,通過GPD0DAT寄存器配置*/GPD0CON &= ~(0xf<<0);GPD0CON |= (1<<0); // output modeGPD0DAT &= ~(1<<0); // output 0 to enable backlight// 10: RGB=FIMD I80=FIMD ITU=FIMD//由上面寄存器的分析可知,這里可以設(shè)置為10DISPLAY_CONTROL = 2<<0;// bit[26~28]:使用RGB接口// bit[18]:RGB 并行// bit[2]:選擇時鐘源為HCLK_DSYS=166MHzVIDCON0 &= ~( (3<<26)|(1<<18)|(1<<2) );// bit[1]:使能lcd控制器// bit[0]:當(dāng)前幀結(jié)束后使能lcd控制器VIDCON0 |= ( (1<<0)|(1<<1) );// bit[4]:選擇需要分頻// bit[6~13]:分頻系數(shù)為15,即VCLK = 166M/(14+1) = 11M,那么bit[6~13]=14;VIDCON0 |= 14<<6 | 1<<4;//屏幕有的是高電平脈沖提示開始,有的是低脈沖提示開始// H43-HSD043I9W1.pdf(p13) 時序圖:VSYNC和HSYNC都是低脈沖提示開始// s5pv210芯片手冊(p1207) 時序圖:VSYNC和HSYNC都是高脈沖提示開始,所以需要反轉(zhuǎn)VIDCON1 |= 1<<5 | 1<<6;// 設(shè)置時序VIDTCON0 = VBPD<<16 | VFPD<<8 | VSPW<<0;VIDTCON1 = HBPD<<16 | HFPD<<8 | HSPW<<0;// 設(shè)置長寬(這里設(shè)置的是物理尺寸)VIDTCON2 = (LINEVAL << 11) | (HOZVAL << 0);// 設(shè)置windows0// bit[0]:使能// bit[2~5]:24bppWINCON0 |= 1<<0;WINCON0 &= ~(0xf << 2);//先清零WINCON0 |= (0xB<<2) | (1<<15);//再設(shè)置#define LeftTopX 0 #define LeftTopY 0 #define RightBotX 479 #define RightBotY 271// 設(shè)置windows1的上下左右//這里設(shè)置的是顯存空間的大小,可以比屏幕大。//這里設(shè)置和物理屏幕一樣大VIDOSD0A = (LeftTopX<<11) | (LeftTopY << 0);VIDOSD0B = (RightBotX<<11) | (RightBotY << 0);VIDOSD0C = (LINEVAL + 1) * (HOZVAL + 1);// 設(shè)置fb的地址VIDW00ADD0B0 = FB_ADDR;//這個可以任選的,但必須對齊(比如按照1M對齊)//每個像素點(diǎn)3個字節(jié)(24bit的bpp)就可以了的,但是為了對齊,用了4字節(jié)。VIDW00ADD1B0 = (((HOZVAL + 1)*4 + 0) * (LINEVAL + 1)) & (0xffffff);//上述兩句表明了一個屏幕占用的空間大小// 使能channel 0傳輸數(shù)據(jù)SHADOWCON = 0x1; }// 描點(diǎn) void lcd_draw_pixel(int row, int col, int color) {unsigned long * pixel = (unsigned long *)FB_ADDR;*(pixel + row * COL + col) = color;//假設(shè)像素點(diǎn)坐標(biāo)為(row,col),則該像素點(diǎn)在內(nèi)存中的位置計算方法如下//有一個基地址,pixel(這里是一個指針,注意它是指針,加1會加上4個字節(jié))//偏移量=每行多少個像素*有多少行*每個像素占用多少個字節(jié)+col個像素*每個像素多少字節(jié)// COL * row * 4 + col * 4//那么所處的位置應(yīng)該是(int)pixel+COL*row*4 + col * 4//或者簡單地寫成 pixel + row * COL + col }// 清屏 void lcd_clear_screen(int color) {int i, j;for (i = 0; i < ROW; i++)for (j = 0; j < COL; j++)lcd_draw_pixel(i, j, color);}// 劃橫線 void lcd_draw_hline(int row, int col1, int col2, int color) {int j;// 描第row行,第j列for (j = col1; j <= col2; j++)lcd_draw_pixel(row, j, color);}// 劃豎線 void lcd_draw_vline(int col, int row1, int row2, int color) {int i;// 描第i行,第col列for (i = row1; i <= row2; i++)lcd_draw_pixel(i, col, color);}// 劃十字 void lcd_draw_cross(int row, int col, int halflen, int color) {lcd_draw_hline(row, col-halflen, col+halflen, color);lcd_draw_vline(col, row-halflen, row+halflen, color); }

三、顯示內(nèi)容

1、首先必須清屏;

2、顯示點(diǎn)、線;

3、顯示英文字符;

(1)每個英文字符,占用16*8個像素,如果單色顯示,則每個像素占1bit,則每個英文字符是16Byte。 (2)字模。要想得到顯示,必須先取“模”(知道該字符的字模),然后填充即可。 (3)代碼示例 // 寫字 // 寫字的左上角坐標(biāo)(x, y),字的顏色是color,字的字模信息存儲在data中 static void show_8_16(unsigned int x, unsigned int y, unsigned int color, unsigned char *data) { // count記錄當(dāng)前正在繪制的像素的次序int i, j, count = 0; for (j=y; j<(y+16); j++) { for (i=x; i<(x+8); i++) { if (i<XSIZE && j<YSIZE) { // 在坐標(biāo)(i, j)這個像素處判斷是0還是1,如果是1寫color;如果是0直接跳過if (data[count/8]/*表示一個字模中(16行,每行8個像素)的第幾行(每行8bit)*/ & (1<<(count%8))/*表示該行的第幾bit*/) lcd_draw_pixel(i, j, color);} count++; } } } // 寫字符串 // 字符串起始坐標(biāo)左上角為(x, y),字符串文字顏色是color,字符串內(nèi)容為str void draw_ascii_ok(unsigned int x, unsigned int y, unsigned int color, unsigned char *str) {int i; unsigned char *ch;for (i=0; str[i]!='\0'; i++) { ch = (unsigned char *)ascii_8_16[(unsigned char)str[i]-0x20];show_8_16(x, y, color, ch); x += 8;if (x >= XSIZE){x -= XSIZE; // 回車y += 16; // 換行}} }

4、顯示中文字符;

5、顯示圖像

(1)之前都是單色的,每個像素點(diǎn)用一個bit(單色顯示時),像素點(diǎn)不是0就是1;而圖像是彩色的,每個像素點(diǎn)占用4字節(jié)(RGB888時),像素點(diǎn)情況很多。 (2)需要取模。使用軟件image2LCD。知道RGB順序的含義,知道生成的步驟即可(一般設(shè)置輸出的和屏幕實(shí)際大小一樣)。 (3)代碼
// 畫800×480的圖,圖像數(shù)據(jù)存儲在pData所指向的數(shù)組中 void lcd_draw_picture(const unsigned char *pData) {u32 x, y, color, p = 0;for (y=0; y<480; y++){for (x=0; x<800; x++){// 在這里將坐標(biāo)點(diǎn)(x, y)的那個像素填充上相應(yīng)的顏色值即可color = (pData[p+0] << 0) | (pData[p+1] << 8) | (pData[p+2] << 16);lcd_draw_pixel(x, y, color);p += 3;//注意這里的p不是指針,而是int數(shù)。由于RGB888,三個一組,所以下一個像素是p+3}} } (4)這樣處理得到的bin大于16KB,所以需要分成BL1,BL2部分。
  • 引用chapter10的分割方法,詳見chapter14\6.LCD目錄下的內(nèi)容。
  • 最后使用燒錄腳本(./write2sd),不能使用windows里的燒錄工具。
write2sd是一個腳本,內(nèi)容如下:
#!/bin/sh sudo dd iflag=dsync oflag=dsync if=./BL1/BL1.bin of=/dev/sdb seek=1 sudo dd iflag=dsync oflag=dsync if=./BL2/BL2.bin of=/dev/sdb seek=45
(5)補(bǔ)充
  • bmp格式是原始圖像,沒有經(jīng)過壓縮?因此可以直接使用image2LCD軟件解釋成數(shù)據(jù)。
  • jpg、png、gif等壓縮的不可以直接用image2LCD解釋。需要先用對應(yīng)的解壓縮庫對其解壓縮,才能使用image2LCD軟件?






總結(jié)

以上是生活随笔為你收集整理的s5pv210——LCD的原理和实战的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。