您好,登錄后才能下訂單哦!
本篇內容介紹了“controller如何使用”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
首先, 我們來看下2440的 lcd controller 組成框圖:
REGBANK: LCD控制器的寄存器組, 含有17個寄存器及一塊256x16的調色板
LCDCDMA: LCD控制器的專用DMA通道, 可以自動從系統總線上獲取圖像數據, 顯示圖像時不需要cpu core的參與
TIMEGEN / LPC3600: 產生控制時序, 如: VSYNC, HSYNC, VCLK, VDEN, 而這些信號又與REGBANK中的LCDCON1/2/3/4的配置密切相關, 通過不同的配置產生不同的控制信號. 然后從VIDEO MUX中傳遞給液晶屏(LPC3600為STN屏專用)
VIDPRCS: 接收LCDCDMA 的數據, 然后轉換為合適的數據格式, 比如 4 bit單掃 / 8ibt單掃 /4bit雙掃, 然后由 VD[23:0]來顯示
其次, 我們來分析一下lcd controller的時序:
VSYNC/VFRAME/STV:垂直同步信號(TFT)/幀同步信號(STN)/SEC TFT信號 HSYNC/VLINE/CPV: 水平同步信號(TFT)/行同步脈沖信號(STN)/SEC TFT信號 VCLK/LCD_HCLK: 像素時鐘信號(TFT/STN)/SEC TFT信號 VD[23:0]: LCD像素數據輸出端口(TFT/STN/SEC TFT) VDEN/VM/TP: 數據使能信號(TFT)/LCD驅動交流偏置信號(STN)/SEC TFT 信號 LEND/STH: 行結束信號(TFT)/SEC TFT信號 LCD_LPCOE: SEC TFT OE信號 LCD_LPCREV: SEC TFT REV信號 LCD_LPCREVB: SEC TFT REVB信號
所有顯示器顯示圖像的原理都是從上到下,從左到右的。這是什么意思呢?這么說吧,一副圖像可以看做是一個矩形,由很多排列整齊的點一行一行組成,這些點稱之為像素。那么這幅圖在LCD上的顯示原理就是:
A:顯示指針從矩形左上角的第一行第一個點開始,一個點一個點的在LCD上顯示,在上面的時序圖上表示為VCLK,我們稱之為像素時鐘信號 B:當顯示指針一直顯示到矩形的右邊就結束這一行,那么這一行的動作在上面的時序圖中就稱之為1 Line C:接下來顯示指針又回到矩形的左邊從第二行開始顯示,注意,顯示指針在從第一行的右邊回到第二行的左邊是需要一定的時間的,我們稱之為行切換 D:如此類推,顯示指針就這樣一行一行的顯示至矩形的右下角才把一副圖顯示完成。行的顯示在時序圖上看就是HSYNC E:然而,LCD要顯示多個圖片就要一幅一幅的切換, 那么這每一幅圖像就稱之為幀,在時序圖上就表示為1 Frame,因此從時序圖上可以看出1 Line只是1 Frame中的一行 F:同樣的,在幀與幀切換之間也是需要一定的時間的,我們稱之為幀切換,那么LCD整個顯示的過程在時間線上看,就可表示為時序圖上的VSYNC
上面時序圖上各時鐘延時參數的含義如下:(這些參數的值,LCD產生廠商會提供相應的數據手冊)
VBPD(vertical back porch):表示在一幀圖像開始時,垂直同步信號以后的無效的行數,對應驅動中的upper_margin VFBD(vertical front porch):表示在一幀圖像結束后,垂直同步信號以前的無效的行數,對應驅動中的lower_margin VSPW(vertical sync pulse width):表示垂直同步脈沖的寬度,用行數計算,對應驅動中的vsync_len HBPD(horizontal back porch):表示從水平同步信號開始到一行的有效數據開始之間的VCLK的個數,對應驅動中的left_margin HFPD(horizontal front porth):表示一行的有效數據結束到下一個水平同步信號開始之間的VCLK的個數,對應驅動中的right_margin HSPW(horizontal sync pulse width):表示水平同步信號的寬度,用VCLK計算,對應驅動中的hsync_len
使用LCD的步驟:
Lcd_Port_Init(); // 設置LCD引腳 Tft_Lcd_Init(MODE_TFT_16BIT_240320); // 初始化LCD控制器, 這里配置了液晶的顯示模式, 如: 分辨率 240x320 顏色深度 16bit Lcd_PowerEnable(0, 1); // 設置LCD_PWREN有效,它用于打開LCD的電源 Lcd_EnvidOnOff(1); // 使能LCD控制器輸出信號 ClearScr(0x0); // 清屏,黑色
GPCUP = 0xffffffff; // 禁止內部上拉 GPCCON = 0xaaaaaaaa; // GPIO管腳用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND GPDUP = 0xffffffff; // 禁止內部上拉 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); /* 設置VCLK的頻率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2] 選擇LCD類型: TFT LCD 設置顯示模式: 16BPP 先禁止LCD信號輸出 */
#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 設置HSYNC、VSYNC脈沖的極性(這需要參考具體LCD的接口信號): 反轉 半字(2字節)交換使能 */
#define LCDFRAMEBUFFER 0x30400000 #define LOWER21BITS(n) ((n) & 0x1fffff) LCDSADDR1 = ((LCDFRAMEBUFFER>>22)<<21) | LOWER21BITS(LCDFRAMEBUFFER>>1); /* 0x30400000的[30:22]值為LCDSADDR1[29:21]的值, 所以0x30400000>>22之后再左移21位 0x30400000的[21:1]值為LCDSADDR1[20:0]的值, 所以0x30400000>>1 為應該配置的值, 這個值只保留低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); /* 這里是計算幀緩沖的結束地址, 本例中占用緩沖區大小為: (LINEVAL_TFT_640480+1) * 640 * 480 * 2, 這里 *2 是因為16bpp, 如果是8bpp則應 *1. 這個大小再加上起始地址LCDFRAMEBUFFER就得到了結束地址 */
#define LCD_XSIZE_TFT_640480 (640) #define LCD_YSIZE_TFT_640480 (480) LCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_640480*2/2);
如果需要禁止調色板:
/* 禁止臨時調色板寄存器 */ 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;
* 設置是否輸出LCD電源開關信號LCD_PWREN * 輸入參數: * invpwren: 0 - LCD_PWREN有效時為正常極性 * 1 - LCD_PWREN有效時為反轉極性 * pwren: 0 - LCD_PWREN輸出有效 * 1 - LCD_PWREN輸出無效 */ void Lcd_PowerEnable(int invpwren, int pwren) { GPGCON = (GPGCON & (~(3<<8))) | (3<<8); // GPG4用作LCD_PWREN GPGUP = (GPGUP & (~(1<<4))) | (1<<4); // 禁止內部上拉 LCDCON5 = (LCDCON5 & (~(1<<5))) | (invpwren<<5); // 設置LCD_PWREN的極性: 正常/反轉 LCDCON5 = (LCDCON5 & (~(1<<3))) | (pwren<<3); // 設置是否輸出LCD_PWREN }
/* * 設置LCD控制器是否輸出信號 * 輸入參數: * onoff: * 0 : 關閉 * 1 : 打開 */ 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 背光 } }
屏幕上任何寫操作都是由寫一個個的點來組合完成的, 寫點函數如下:
/* * 畫點 * 輸入參數: * x、y : 象素坐標 * color: 顏色值 * 對于16BPP: color的格式為0xAARRGGBB (AA = 透明度), * 需要轉換為5:6:5格式 * 對于8BPP: color為調色板中的索引值, * 其顏色取決于調色板中的數值 */ 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已經指向了幀內存首地址, 還有幀內存與視圖雖然類比為窗口一樣的形狀, 但是在內存里只有線性結構, 就如同二維數組照樣是線性存儲的. 所以這里可以這樣尋址每個點的內存中的位置 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如何使用”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。