對于人機界面中的液晶屏的使用大家都不陌生。從簡單的電子表到手機、平板電腦,顯示器、液晶電視都能看到他們的身影。早其我們常用的液晶屏,比如段碼LCD,1602,12232,12864,等非黑即透明.,隨著技術的不斷進步,現在在手機和平板電腦等電子設備上用的主要是TFT液晶屏,本人一直也是對液晶的顯示十分好奇,按捺不住,就淘了幾個小尺寸TFT液晶屏(呵呵,囊中羞澀)搗鼓搗鼓。發現這東西其實還是很好玩的,除了涉及的知識面比較廣,需要閱讀不少手冊及資料外,只要你要一定的單片機開發的基礎,操作起來并不復雜,主要難點還是數據處理和字庫的制作上。下面就說道說道這個TFT液晶。
什么是TFT?
TFT液晶屏也就是thin film transistor 即薄膜晶體管顯示屏,它的每一個像素點都是由集成在其后的薄膜晶體管來驅動的。
常用TFT模塊尺寸:
對角線的尺寸:1.44、1.6、1.8、2.0、2.2、2.4、2.6、2.8、3.0、3.2、3.4、3.6、4.0、4.3、5.7、8.4、10.4、15、17、19、21英寸等。
本人使用過的,1.44、1.8、2.2
屏幕高寬比:4:3或16:9
分辨率:指水平像素和垂直像素的數量。
點距:相鄰兩個像素之間的距離。
刷新率:每秒更新的畫面數。
接口形式:并行接口和串行接口
顏色的表示:
對于黑白或單色像素的信息可以用1個位來表示和存儲,
對于一個彩色像素的信息可以用1個多位二進制數來表示和存儲。
用來表示彩色像素的二進制數的尾數,稱之為顏色的顏色深度或顏色質量
什么是真彩和偽彩
顏色深度在16為以上的稱為真彩色,顏色深度在16位以下的稱為偽彩色。
比如采用1個16位二進制數來表示一個彩色點:
紅色 綠色 藍色
5位 6位 5位
R4 R3 R2 R1 R0 G5 G4G3 G2 G1G0B4B3B2B1B0
高8位 低8位
這就是所謂的5-6-5格式。
字符或圖像到底是怎樣顯示出來的?
首先可將光看作是一種電磁波,以電場和磁場相互垂直而交互震蕩的方式向前傳播。電場在某個方向上震蕩,震蕩的幅度越大,光所具有的能量越大。某個方向上震蕩的光可以分解成兩個垂直方向上的分量。
偏光片:作用是讓某個方向上震蕩的光通過,而把垂直方向上震蕩的光擋住。
偏光片組:
第一偏光片僅讓在某個方向上震蕩的光通過,而第二偏光片再把所通過的光擋住,即可阻絕光的行進,達到關閉光的效果。
液晶具有雙折射系數的特性,并且在不同的電場下,會有不同的排列方式,因此當光通過液晶時,會受其影響而改變或保持其震蕩的方向,當液晶不改變光的震蕩方向時,光無法通過第二個偏光板而被關閉,而當液晶將光的震蕩方向改變時,光可以在分解成兩個分量,雖然一個分量無法通過第二個偏光片,但是仍還有一個分量可以通過第二個偏光片,而成為打開狀態。英雌,可用施加的電場來改變液晶的排列方式,來實現光的開關的來實現顯示功能。具體液晶是個什么東西,有那些種類,大家想了解就百度吧,這里就不再細談了。
電場是如何改變的?
首先了解一下TFT(thin-film transister )薄膜電晶體
主要結構是一個非晶矽半導體薄膜,TFT 就有一個門極gate;一個源極source;和一個漏極drain.看看這幾電極的名稱是不是很熟悉,對了場效應管也是這樣命名的,兩者類似,但又有不同之處。但是都可以理解成一個受控的開關。
這些開關以矩陣的方式進行排列。
彩色的TFT將水平方向的每個像素在次分成3個RGB像素,各個次像素的可以獨立的改變,故也分別對應一個TFT。這樣3個次像素組成一個像素。
呵呵,看了上面的圖,是不是就想到了單片機矩陣按鍵的動態掃描程序。呵呵不錯,逆向思維,矩陣鍵盤的掃描是讀狀態,這個是寫狀態。具體過程如下。
在水平方向上的同一條掃描線上,所有TFT的門極都連在一起,所以施加的電壓是一樣的,若在某一條掃面線上施加足夠大的正電壓,則這條掃描線上所有的TFT 都會被打開。此時該掃描線上的像素電極,會與垂直方向的資料線(漏極)連接,經由對應的資料線送入相應的視信號,將像素電極充電到適當的電壓。接著施加足夠大的負電壓,關閉TFT,直到下次再重新寫入信號。其間使得電荷保存在液晶電容上;在按照這種方式掃描下一行。再送入下一行的視信號,如此依次將整個畫面的視信號寫入,在重新自第一行開始寫入,(一般重復的頻率為60-70Hz)。
對每個像素中的液晶光閥而言,液晶上所施加的電壓和光的穿透度具有一定的關系,因此,只要依據所要顯示的畫面,控制施加在液晶上的電壓,即可將各個像素設定在適當的光穿透度,配合均勻的背光源就顯示出想要的畫面了。這就是主動式矩陣型液晶的顯示原理。
就幾款液晶屏的參數做一下總結說明
1、1.44寸液晶屏(以下數據來自液晶屏數據手冊)
LCD type : 1.45”active matrix TFT-LCD
Rsolution: 128(W)X128(H) Pixels
Display mode : transmissive type
Display color: 262Kcolor
driverIC: ILI9163C
Luminance: 120cd/m2
Contrast ratio: 400:1
Viewing direction: 6o’clock
Interface : 4 wire SPI interface
Back light: 1 white LED ,18ma ,3,15V
2、引腳說明:
VCC: 電源 +3,3V
GND: 電源地
CS: 片選 (低電平有效)
RST: 復位 (低電平有效)
AO: 寄存器選擇信號(低電平:選擇命令寄存器;高電平:選擇數據寄存器)
SDA: data input in SPI mode 在SPI模式下的數據輸入
SCL: 在SPI模式下的同步時鐘輸入
LED: 背光LED電源,
呵呵,從引腳定義上就可以看出是不是在SPI模式下只需要4條IO口線就可以和MCU構成一個顯示系統了。(其實還用一種模式只要3條IO口線就可以)。
再看1.8寸TFT的相關數據
顯示點陣數: 128W x 160H dots
模塊外形尺寸: 34W x 45.83H x 2.65T mm
可視區域: 28.03W x 35.04H mm
像素尺寸: 0.06W * 3 * 0.18H mm
像素中心距: 0.18W * 0.18H mm
占空比: 1/400
視角: 6點鐘
LCD模式: 260k color
IC: ST7735B
主要引腳定義:同1.44’
再看2.2英寸的屏
Size 2.2inch
Resolution: 240*320
Interface 4-wire SPI
Color depth 262k/65k
Technology a-Si
Pixel pitch(mm): 0.141*0.141
Viewing direction: 6o’clock
LED numbers 4 LEDs
Driver IC ILI9340C
主要引腳定義同1.44’英寸。
從上面不同尺寸液晶屏的引腳的定義看出,1.44英寸和1.8英寸及2.2英寸的TFT液晶屏,在和MCU構成顯示系統時操作方式是一樣的(因為都是4線 SPI),盡管他們使用的驅動IC型號不同。但是只要你翻看IC的數據手冊就會發現,他們的寄存器的定義基本是一樣的,操作原理相同。
如何構成一個顯示系統:
電源+MCU+TFT液晶屏
呵呵,是不是覺得少了點什么?驅動IC那里去了?
其實驅動IC我們是看不到的,它被集成在了液晶屏中,我們只要知道它的寄存器的定義,利用液晶屏的端口會進行讀寫即可。
電源:3.3V的直流電源,呵呵,這個不用細說,小功率的可以利用ASM1117-3;大功率的可以利用LM2596S-3.3(最高3A的輸出)來構成一個電源。
MCU:主要是3個要求。
工作電壓,3.3V
夠大,
夠快。
夠大才能存的下程序和數據,夠快才會圖像流暢。
本人手頭只有15L2K08S2這個單片機,8K程序存儲區,2K的SRAM,最高時鐘33.1776MHz,最高輸出8MHz的外部時鐘,比起60S2的60KB的FLASH,小了不少,但是對于普通的不太復雜的應用已經足夠了,主要是搞通應用的原理。
液晶屏:
以上列舉的液晶屏都是串口屏,所以屏的引出腳較少,除此之外還有引出管腳較多的并口屏,
當然串口屏的數據是一位一位的送出的,速度相對是比較慢的。
在操作上,串口和并口原理差不多。這里就先介紹串口屏的使用。
好了,你有了上面的3大件下面在準備點輔料。
1、數據線,USB轉串口數據線,用于燒寫MCU
2、字符LCD點陣提取軟件:百度一下吧,zimo221.exe
3、圖片點陣數據提取軟件:同樣百度,Image2Lcd.exe
4、編程軟件:KEIL
5、單片機燒寫軟件:這個不多說了,看你用的芯片而定。
好的,齊活了,準備開工。
用導線將單片機的電源接口和LCD的電源及LED端口同3.3V電源的輸出連接起來。供電的問題解決了。
用導線將自己選擇的單片機的端口和LCD的REST、CS、SCL、AO、SDA 一一對應的連接起來。數據輸出的問題解決。
硬件問題解決,開始代碼的編寫
TFT初始化函數:
也就是對液晶屏進行基本的配置。
這個基本直接套用就行。(除了個別地方需要修改,后面會說)
TFT驅動芯片的手冊還是有必要看看的,最好是看英文原版內容比較詳細。
也沒有必要全部看,但是下面初始化代碼中涉及到的指令及4wireSPI的時序圖,還是很有必要了解的,不然顯示的界面出了問題,就會感覺無從下手解決。
寫數據和寫命令
很明顯要想讓液晶屏顯示字符或圖像,必須要把要顯示的內容轉換成數據寫到液晶屏的控制器,想寫內容數據還要對液晶屏的控制寄存器進行設置,也就是寫命令數據。只有一條SDA串口數據線,怎么區分是內容數據還是命令數據呢,那就要靠 AO(RS): 寄存器選擇信號(低電平:選擇命令寄存器;高電平:選擇數據寄存器)。
寫命令
void write_command(uchar c)
{
cs=0; //片選有效
rs=0; //選擇命令寄存器
bitdata=c;//送數據
sda=bit7;scl=0;scl=1;
sda=bit6;scl=0;scl=1;
sda=bit5;scl=0;scl=1;
sda=bit4;scl=0;scl=1;
sda=bit3;scl=0;scl=1;
sda=bit2;scl=0;scl=1;
sda=bit1;scl=0;scl=1;
sda=bit0;scl=0;scl=1;
cs=1;//片選無效
}
寫數據
void write_data(uchar d)
{
cs=0;
rs=1;
bitdata=d;
sda=bit7;scl=0;scl=1;
sda=bit6;scl=0;scl=1;
sda=bit5;scl=0;scl=1;
sda=bit4;scl=0;scl=1;
sda=bit3;scl=0;scl=1;
sda=bit2;scl=0;scl=1;
sda=bit1;scl=0;scl=1;
sda=bit0;scl=0;scl=1;
cs=1;
}
初始化
/*****************TFT初始化函數***************/
void lcd_initial()
{
reset=0;
delay(100);
reset=1;
delay(100);
//------------------------------------------------------------------//
//-------------------Software Reset-------------------------------//
write_command(0x2A); //列地址設置
write_data(0x00); //列起始地址低8位
write_data(0x00); //列起始地址高8位
write_data(0x00); //列終止地址高8位
write_data(0x9F); //列終止地址低8位
//上面的列終止地址為什么設置成0x9f,0x9f=十進制的159,1.8寸的屏的分辨率是128*160.
//也就是說有0-159共160列。 下面的同樣的道理,只不過是說明行的起始和終止地址。
write_command(0x2B); //行地址設置
write_data(0x00);
write_data(0x00);
write_data(0x00);
write_data(0x7F);
write_command(0xCB); //功耗控制A
write_data(0x39);
write_data(0x2C);
write_data(0x00);
write_data(0x34);
write_data(0x02);
write_command(0xCF);//功耗控制B
write_data(0x00);
write_data(0XC1);
write_data(0X30);
write_command(0xE8);//驅動時序控制A
write_data(0x85);
write_data(0x00);
write_data(0x78);
write_command(0xEA);//驅動時序控制B
write_data(0x00);
write_data(0x00);
write_command(0xED);//電源序列控制
write_data(0x64);
write_data(0x03);
write_data(0X12);
write_data(0X81);
write_command(0xF7); //泵比控制
write_data(0x20);
write_command(0xC0); //Power control 功耗控制1
write_data(0x23); //VRH[5:0] `
write_command(0xC1); //Power control 功耗控制2
write_data(0x10); //SAP[2:0];BT[3:0]
write_command(0xC5); //VCM control
write_data(0x3e); //對比度調節
write_data(0x28);
write_command(0xC7); //VCM control2
write_data(0x86); //--
write_command(0x36); // Memory Access Control 存儲器訪問控制
write_data(0x68); //C8 //48 68豎屏//28 E8 橫屏
//cc同c8
write_command(0x3A); //像素格式設置
write_data(0x55);
write_command(0xB1);//幀速率控制
write_data(0x00);
write_data(0x18);
write_command(0xB6); // Display Function Control
write_data(0x08);
write_data(0x82);
write_data(0x27);
write_command(0xF2); // 3Gamma Function Disable
write_data(0x00);
write_command(0x26); //Gamma curve selected
write_data(0x01); //共4條曲線供選擇,分別是1248;這里選擇1,
write_command(0xE0); //Set Gamma
write_data(0x0F);
write_data(0x31);
write_data(0x2B);
write_data(0x0C);
write_data(0x0E);
write_data(0x08);
write_data(0x4E);
write_data(0xF1);
write_data(0x37);
write_data(0x07);
write_data(0x10);
write_data(0x03);
write_data(0x0E);
write_data(0x09);
write_data(0x00);
write_command(0XE1); //Set Gamma
write_data(0x00);
write_data(0x0E);
write_data(0x14);
write_data(0x03);
write_data(0x11);
write_data(0x07);
write_data(0x31);
write_data(0xC1);
write_data(0x48);
write_data(0x08);
write_data(0x0F);
write_data(0x0C);
write_data(0x31);
write_data(0x36);
write_data(0x0F);
write_command(0x11); //Exit Sleep
delay(120);
write_command(0x29); //Display on
write_command(0x2c);
}
在寫入數據時要先確定,圖像的起始坐標和終止坐標,可以用如下的代碼實現
static void LCD_SetPos(unsigned int x0,unsigned int x1,unsigned int y0,unsigned int y1)//設置位置
{
write_command(0x2A); //列地址設置
write_data(x0>>8); //列起始地址高8位
write_data(x0); //列起始地址低8位
write_data(x1>>8); //列終止地址高8位
write_data(x1); //列終止地址低8位
write_command(0x2B);//頁地址設置
write_data(y0>>8);
write_data(y0);
write_data(y1>>8);
write_data(y1);
write_command(0x2c);//寫存儲器
}
寫命令時,先將命令的地址寫入,然后在將設定的數據寫入寄存器。如
write_command(0x2A); //列地址設置
write_data(0x00);
write_data(0x00);
write_data(0x00);
write_data(0x9F);
至于這些寫入的數據的意義及數值大小,請查閱液晶屏對應的液晶屏的數據手冊。
了解一下顏色代碼:
幾種常用的顏色的代碼
#define White 0xFFFF //白
#define Black 0x0000 //黑
#define Red 0x001F //紅
#define Blue 0xF800 //藍
#define Magenta 0xF81F //紫
#define Green 0x07E0 //綠
#define Cyan 0x07FF //青
#define Yellow 0xFFE0 //黃
好了說了這么多,一個字暈。好吧,來點實際的簡單的,咱先啥字符也不顯示,
只是讓液晶屏顯示不同的顏色。
刷整個屏幕的顏色
可以用如下代碼實現
/*********顯示色彩******************/
void dsp_single_colour(DH,DL)//前景顏色,背景顏色
{
unsigned int i,j;
for (i=0;i<128;i++)
for (j=0;j<160;j++)
{
write_data(DH>>8);
write_data(DH);
write_data(DL>>8);
write_data(DL);
}
}
延時函數
/******延時函數************************/
void delay(uint time)
{
uint i,j;
for(i=0;i<time;i++)
for(j=0;j<500;j++);
}
好了,將上面的函數組合起來,準備刷屏。
main()
{
lcd_initial();//TFT初始化
while(1)
{
LCD_SetPos(0,159,0,10);//設置位置
dsp_single_colour(Blue,Black); //
delay(2000) ;
LCD_SetPos(0,159,10,20);//設置位置
dsp_single_colour(Blue,Blue); //
delay(2000) ;
LCD_SetPos(0,159,20,30);//設置位置
dsp_single_colour(Green,White); //
delay(2000) ;
LCD_SetPos(0,159,30,40);//設置位置
dsp_single_colour(Green,Green); //
delay(2000) ;
LCD_SetPos(0,159,40,50);//設置位置
dsp_single_colour(Yellow,White); //
delay(2000) ;
LCD_SetPos(0,159,50,60);//設置位置
dsp_single_colour(Yellow,Yellow); //
delay(2000) ;
LCD_SetPos(0,159,60,70);//設置位置
dsp_single_colour(Black,White); //
delay(2000) ;
LCD_SetPos(0,159,70,80);//設置位置
dsp_single_colour(Black,Black); //
delay(2000) ;
LCD_SetPos(0,159,80,90);//設置位置
dsp_single_colour(Red,White); //
delay(2000) ;
LCD_SetPos(0,159,90,100);//設置位置
dsp_single_colour(Red,Red); //
delay(2000) ;
LCD_SetPos(0,159,100,110);//設置位置
dsp_single_colour(Magenta ,Black); //
delay(2000) ;
LCD_SetPos(0,159,110,120);//設置位置
dsp_single_colour(Magenta ,Magenta ); //
delay(2000) ;
LCD_SetPos(0,159,0,120);//設置位置
dsp_single_colour(White,White ); //只刷到第121行留下了7行
delay(2000) ;
}
}
最終結果,滾動刷屏
感覺有點不對勁,不錯,最下面故意留了7行沒寫顏色數據。可以看到如果不寫任何數據,屏的狀態就是花屏。
通過上面的說明了解了:
TFT液晶屏的操作原理,就是寫數據和寫命令。
通過對寫數據或寫命令的代碼的分析,可以看到數據是怎樣輸送的。
TFT液晶屏的初始化工作的主要內容。
常用的顏色代碼。
如何讓液晶屏顯示不同的顏色。
最后仔細觀察圖片,可以了解
什么是隔行掃面,前景顏色,背景顏色。
以及,花屏是什么原因造成的。
至于如何顯示字符,漢字,圖片,下回再說。
關于在tft上模擬現實七段數碼管詳見:http://www.zg4o1577.cn/bbs/dpj-30555-1.html