本篇內(nèi)容介紹了“controller如何使用”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
創(chuàng)新互聯(lián)公司專注于網(wǎng)站建設(shè),為客戶提供網(wǎng)站設(shè)計(jì)制作、網(wǎng)站設(shè)計(jì)、網(wǎng)頁(yè)設(shè)計(jì)開(kāi)發(fā)服務(wù),多年建網(wǎng)站服務(wù)經(jīng)驗(yàn),各類網(wǎng)站都可以開(kāi)發(fā),品牌網(wǎng)站建設(shè),公司官網(wǎng),公司展示網(wǎng)站,網(wǎng)站設(shè)計(jì),建網(wǎng)站費(fèi)用,建網(wǎng)站多少錢(qián),價(jià)格優(yōu)惠,收費(fèi)合理。
首先, 我們來(lái)看下2440的 lcd controller 組成框圖:
REGBANK: LCD控制器的寄存器組, 含有17個(gè)寄存器及一塊256x16的調(diào)色板
LCDCDMA: LCD控制器的專用DMA通道, 可以自動(dòng)從系統(tǒng)總線上獲取圖像數(shù)據(jù), 顯示圖像時(shí)不需要cpu core的參與
TIMEGEN / LPC3600: 產(chǎn)生控制時(shí)序, 如: VSYNC, HSYNC, VCLK, VDEN, 而這些信號(hào)又與REGBANK中的LCDCON1/2/3/4的配置密切相關(guān), 通過(guò)不同的配置產(chǎn)生不同的控制信號(hào). 然后從VIDEO MUX中傳遞給液晶屏(LPC3600為STN屏專用)
VIDPRCS: 接收LCDCDMA 的數(shù)據(jù), 然后轉(zhuǎn)換為合適的數(shù)據(jù)格式, 比如 4 bit單掃 / 8ibt單掃 /4bit雙掃, 然后由 VD[23:0]來(lái)顯示
其次, 我們來(lái)分析一下lcd controller的時(shí)序:
VSYNC/VFRAME/STV:垂直同步信號(hào)(TFT)/幀同步信號(hào)(STN)/SEC TFT信號(hào) HSYNC/VLINE/CPV: 水平同步信號(hào)(TFT)/行同步脈沖信號(hào)(STN)/SEC TFT信號(hào) VCLK/LCD_HCLK: 像素時(shí)鐘信號(hào)(TFT/STN)/SEC TFT信號(hào) VD[23:0]: LCD像素?cái)?shù)據(jù)輸出端口(TFT/STN/SEC TFT) VDEN/VM/TP: 數(shù)據(jù)使能信號(hào)(TFT)/LCD驅(qū)動(dòng)交流偏置信號(hào)(STN)/SEC TFT 信號(hào) LEND/STH: 行結(jié)束信號(hào)(TFT)/SEC TFT信號(hào) LCD_LPCOE: SEC TFT OE信號(hào) LCD_LPCREV: SEC TFT REV信號(hào) LCD_LPCREVB: SEC TFT REVB信號(hào)
所有顯示器顯示圖像的原理都是從上到下,從左到右的。這是什么意思呢?這么說(shuō)吧,一副圖像可以看做是一個(gè)矩形,由很多排列整齊的點(diǎn)一行一行組成,這些點(diǎn)稱之為像素。那么這幅圖在LCD上的顯示原理就是:
A:顯示指針從矩形左上角的第一行第一個(gè)點(diǎn)開(kāi)始,一個(gè)點(diǎn)一個(gè)點(diǎn)的在LCD上顯示,在上面的時(shí)序圖上表示為VCLK,我們稱之為像素時(shí)鐘信號(hào) B:當(dāng)顯示指針一直顯示到矩形的右邊就結(jié)束這一行,那么這一行的動(dòng)作在上面的時(shí)序圖中就稱之為1 Line C:接下來(lái)顯示指針又回到矩形的左邊從第二行開(kāi)始顯示,注意,顯示指針在從第一行的右邊回到第二行的左邊是需要一定的時(shí)間的,我們稱之為行切換 D:如此類推,顯示指針就這樣一行一行的顯示至矩形的右下角才把一副圖顯示完成。行的顯示在時(shí)序圖上看就是HSYNC E:然而,LCD要顯示多個(gè)圖片就要一幅一幅的切換, 那么這每一幅圖像就稱之為幀,在時(shí)序圖上就表示為1 Frame,因此從時(shí)序圖上可以看出1 Line只是1 Frame中的一行 F:同樣的,在幀與幀切換之間也是需要一定的時(shí)間的,我們稱之為幀切換,那么LCD整個(gè)顯示的過(guò)程在時(shí)間線上看,就可表示為時(shí)序圖上的VSYNC
上面時(shí)序圖上各時(shí)鐘延時(shí)參數(shù)的含義如下:(這些參數(shù)的值,LCD產(chǎn)生廠商會(huì)提供相應(yīng)的數(shù)據(jù)手冊(cè))
VBPD(vertical back porch):表示在一幀圖像開(kāi)始時(shí),垂直同步信號(hào)以后的無(wú)效的行數(shù),對(duì)應(yīng)驅(qū)動(dòng)中的upper_margin VFBD(vertical front porch):表示在一幀圖像結(jié)束后,垂直同步信號(hào)以前的無(wú)效的行數(shù),對(duì)應(yīng)驅(qū)動(dòng)中的lower_margin VSPW(vertical sync pulse width):表示垂直同步脈沖的寬度,用行數(shù)計(jì)算,對(duì)應(yīng)驅(qū)動(dòng)中的vsync_len HBPD(horizontal back porch):表示從水平同步信號(hào)開(kāi)始到一行的有效數(shù)據(jù)開(kāi)始之間的VCLK的個(gè)數(shù),對(duì)應(yīng)驅(qū)動(dòng)中的left_margin HFPD(horizontal front porth):表示一行的有效數(shù)據(jù)結(jié)束到下一個(gè)水平同步信號(hào)開(kāi)始之間的VCLK的個(gè)數(shù),對(duì)應(yīng)驅(qū)動(dòng)中的right_margin HSPW(horizontal sync pulse width):表示水平同步信號(hào)的寬度,用VCLK計(jì)算,對(duì)應(yīng)驅(qū)動(dòng)中的hsync_len
使用LCD的步驟:
Lcd_Port_Init(); // 設(shè)置LCD引腳 Tft_Lcd_Init(MODE_TFT_16BIT_240320); // 初始化LCD控制器, 這里配置了液晶的顯示模式, 如: 分辨率 240x320 顏色深度 16bit Lcd_PowerEnable(0, 1); // 設(shè)置LCD_PWREN有效,它用于打開(kāi)LCD的電源 Lcd_EnvidOnOff(1); // 使能LCD控制器輸出信號(hào) ClearScr(0x0); // 清屏,黑色
GPCUP = 0xffffffff; // 禁止內(nèi)部上拉 GPCCON = 0xaaaaaaaa; // GPIO管腳用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND GPDUP = 0xffffffff; // 禁止內(nèi)部上拉 GPDCON = 0xaaaaaaaa; // GPIO管腳用于VD[23:8] GPBCON &= ~(GPB0_MSK); // Power enable pin GPBCON |= GPB0_out; // GPB0控制液晶的背光ic輸出使能 GPBDAT &= ~(1<<0); // Power off printf("Initializing GPIO ports..........\n");
#define CLKVAL_TFT_640480 (1) #define LCDTYPE_TFT 0x3 #define BPPMODE_16BPP 0xC #define ENVID_DISABLE 0 LCDCON1 = (CLKVAL_TFT_640480<<8) | (LCDTYPE_TFT<<5) | (BPPMODE_16BPP<<1) | (ENVID_DISABLE<<0); /* 設(shè)置VCLK的頻率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2] 選擇LCD類型: TFT LCD 設(shè)置顯示模式: 16BPP 先禁止LCD信號(hào)輸出 */
#define VBPD_640480 ((33-1)&0xff) #define LINEVAL_TFT_640480 (LCD_YSIZE_TFT_640480-1) #define VFPD_640480 ((10-1)&0xff) #define VSPW_640480 ((2-1) &0x3f) LCDCON2 = (VBPD_640480<<24) | (LINEVAL_TFT_640480<<14) | (VFPD_640480<<6) | (VSPW_640480);
#define HBPD_640480 ((48-1)&0x7f) #define HOZVAL_TFT_640480 (LCD_XSIZE_TFT_640480-1) #define HFPD_640480 ((16-1)&0xff) LCDCON3 = (HBPD_640480<<19) | (HOZVAL_TFT_640480<<8) | (HFPD_640480);
#define HSPW_640480 ((96-1)&0xff) LCDCON4 = HSPW_640480;
#define FORMAT8BPP_565 1 #define HSYNC_INV 1 #define VSYNC_INV 1 #define HWSWP 1 LCDCON5 = (FORMAT8BPP_565<<11) | (HSYNC_INV<<9) | (VSYNC_INV<<8) | (HWSWP<<1); /* 16bpp 565 設(shè)置HSYNC、VSYNC脈沖的極性(這需要參考具體LCD的接口信號(hào)): 反轉(zhuǎn) 半字(2字節(jié))交換使能 */
#define LCDFRAMEBUFFER 0x30400000 #define LOWER21BITS(n) ((n) & 0x1fffff) LCDSADDR1 = ((LCDFRAMEBUFFER>>22)<<21) | LOWER21BITS(LCDFRAMEBUFFER>>1); /* 0x30400000的[30:22]值為L(zhǎng)CDSADDR1[29:21]的值, 所以0x30400000>>22之后再左移21位 0x30400000的[21:1]值為L(zhǎng)CDSADDR1[20:0]的值, 所以0x30400000>>1 為應(yīng)該配置的值, 這個(gè)值只保留低21位, 所以 又與 0x1fffff相與 */
#define HOZVAL_TFT_640480 (LCD_XSIZE_TFT_640480-1) #define LINEVAL_TFT_640480 (LCD_YSIZE_TFT_640480-1) LCDSADDR2 = LOWER21BITS((LCDFRAMEBUFFER+(LINEVAL_TFT_640480+1)*(HOZVAL_TFT_640480+1)*2)>>1); /* 這里是計(jì)算幀緩沖的結(jié)束地址, 本例中占用緩沖區(qū)大小為: (LINEVAL_TFT_640480+1) * 640 * 480 * 2, 這里 *2 是因?yàn)?6bpp, 如果是8bpp則應(yīng) *1. 這個(gè)大小再加上起始地址LCDFRAMEBUFFER就得到了結(jié)束地址 */
#define LCD_XSIZE_TFT_640480 (640) #define LCD_YSIZE_TFT_640480 (480) LCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_640480*2/2);
如果需要禁止調(diào)色板:
/* 禁止臨時(shí)調(diào)色板寄存器 */ TPAL = 0;
幀地址:
unsigned int fb_base_addr; unsigned int bpp; unsigned int xsize; unsigned int ysize; fb_base_addr = LCDFRAMEBUFFER; bpp = 16; xsize = 640; ysize = 480;
* 設(shè)置是否輸出LCD電源開(kāi)關(guān)信號(hào)LCD_PWREN * 輸入?yún)?shù): * invpwren: 0 - LCD_PWREN有效時(shí)為正常極性 * 1 - LCD_PWREN有效時(shí)為反轉(zhuǎn)極性 * pwren: 0 - LCD_PWREN輸出有效 * 1 - LCD_PWREN輸出無(wú)效 */ void Lcd_PowerEnable(int invpwren, int pwren) { GPGCON = (GPGCON & (~(3<<8))) | (3<<8); // GPG4用作LCD_PWREN GPGUP = (GPGUP & (~(1<<4))) | (1<<4); // 禁止內(nèi)部上拉 LCDCON5 = (LCDCON5 & (~(1<<5))) | (invpwren<<5); // 設(shè)置LCD_PWREN的極性: 正常/反轉(zhuǎn) LCDCON5 = (LCDCON5 & (~(1<<3))) | (pwren<<3); // 設(shè)置是否輸出LCD_PWREN }
/* * 設(shè)置LCD控制器是否輸出信號(hào) * 輸入?yún)?shù): * onoff: * 0 : 關(guān)閉 * 1 : 打開(kāi) */ void Lcd_EnvidOnOff(int onoff) { if (onoff == 1) { LCDCON1 |= 1; // ENVID ON GPBDAT |= (1<<0); // Power on 背光 } else { LCDCON1 &= 0x3fffe; // ENVID Off GPBDAT &= ~(1<<0); // Power off 背光 } }
屏幕上任何寫(xiě)操作都是由寫(xiě)一個(gè)個(gè)的點(diǎn)來(lái)組合完成的, 寫(xiě)點(diǎn)函數(shù)如下:
/* * 畫(huà)點(diǎn) * 輸入?yún)?shù): * x、y : 象素坐標(biāo) * color: 顏色值 * 對(duì)于16BPP: color的格式為0xAARRGGBB (AA = 透明度), * 需要轉(zhuǎn)換為5:6:5格式 * 對(duì)于8BPP: color為調(diào)色板中的索引值, * 其顏色取決于調(diào)色板中的數(shù)值 */ void PutPixel(UINT32 x, UINT32 y, UINT32 color) { UINT8 red,green,blue; switch (bpp){ case 16: { UINT16 *addr = (UINT16 *)fb_base_addr + (y * xsize + x); //這里fb_base_addr已經(jīng)指向了幀內(nèi)存首地址, 還有幀內(nèi)存與視圖雖然類比為窗口一樣的形狀, 但是在內(nèi)存里只有線性結(jié)構(gòu), 就如同二維數(shù)組照樣是線性存儲(chǔ)的. 所以這里可以這樣尋址每個(gè)點(diǎn)的內(nèi)存中的位置 red = (color >> 19) & 0x1f; green = (color >> 10) & 0x3f; blue = (color >> 3) & 0x1f; color = (red << 11) | (green << 5) | blue; // 格式5:6:5 *addr = (UINT16) color; break; } case 8: { UINT8 *addr = (UINT8 *)fb_base_addr + (y * xsize + x); *addr = (UINT8) color; break; } default: break; } }
“controller如何使用”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!