關於Pait_Bmp(x0,
y0, x,
y, BMPaddr);函式

畫素圖在螢幕左上角為(0,0),Pait_Bmp中的x0。y0分別畫素點初始位置,x,y為BMP圖片的X,Y的大小。BMPaddr為BMP圖片轉換的陣列地址



基於T35 TFT LCD屏實現功能

1. 在螢幕上畫一個計算器介面,包含0-9,+。-,*。/;

2. 實現觸控選擇介面上的數字和運算子。

3. 並計算出結果顯示在顯示框內。

注意。僅僅實現整數功能,沒涉及小數。僅僅實現一次運算,不儲存上次運算結果。

實現介面:

實現過程:

開啟LCD電源,初始化LCD>>>LCD填充介面圖片>>>開啟觸控式螢幕中斷>>>獲取鍵值>>>區分數字和功能來呼叫數字圖片顯示。

 

數字圖片

空白圖: 除數為零提示圖:

數字影象:                                 
                                                
                                     

數值過長提示圖:

1、開啟LCD電源,初始化LCD

當中:時序發生器(TIMEGEN)

TIMEGEN產生LCD驅動器的控制訊號。如VFRAME、VLINE、VCLK和VM。這些控制訊號與REGBANK中的LCDCON1/2/3/4/5暫存器配製有著緊密關係。

基於這些可程式設計的REGBANK中LCD控制暫存器的配製,TIMEGEN能夠產生合適的可程式設計控制訊號來支援多種不同型別的LCD驅動器.

TFT屏的工作時序:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbXV5YW5nX3Jlbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

VSYNC為幀同步訊號。每發出一個脈衝表示新的一屏影象資料開始傳輸。

VSF=HSF÷[(VSPW+1)+(VBPD+1)+(VFPD+1)+(LINEVAL+1)]

HSYNC為行同步訊號。每發出一個脈衝表示新的一行影象資料開始傳輸。

HSF=VCLK÷[(HSPW+1)+(HSPD+1)+(HFPD+1)+(HOZVAL+1)]

VCLK為畫素同步訊號,每發出一個脈衝表示新的一個點影象資料開始傳輸。

VCLK=HCLK÷[(CLKVAL+1)×2]

LCD顯示是一幀一幀(一個畫面)的,每一幀裡顯示又是從上到下一行一行的。每一行顯示又是從左到右一個點一個點的。

而VSYNC,HSYNC,VCLK這些決定了他們的顯示速度。

圖中的VSPW,HSPW等決定對應脈衝的寬度。VBPD,HBPD決定了延時時間。

這些引數的設定都是由LCDCONn決定的。

初始化LCD:(設定TIMEGEN)

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbXV5YW5nX3Jlbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

/**************************************************************
TFT LCD功能模組初始化//此函式沒開啟遮蔽功能
**************************************************************/
void LCD_Init(void)
{
#define M5D(n) ((n)&0x1fffff)
#define LCD_ADDR ((U32)LCD_BUFFER)
//con1[6:5]顯示模式選擇為 TFT LCD面板 模式 [4:1]選擇為 TFT的16bpp 畫素模式
rLCDCON1 = (LCD_PIXCLOCK << 8) | (3 << 5) | (12 << 1);
//con2[23:14]設定高度320 VSPW[5:0]決定對應脈衝的寬度; VFPD[13:6]、VBPD[31:24]決定了延時時間; 選擇option.h檔案裡T35定義引數
rLCDCON2 = (LCD_UPPER_MARGIN << 24) | ((LCD_HEIGHT - 1) << 14) | (LCD_LOWER_MARGIN << 6) | (LCD_VSYNC_LEN << 0);
//con3[18:8]設定高度240 HFPD、HBPD決定了延時時間; 選擇option.h檔案裡T35定義引數
rLCDCON3 = (LCD_RIGHT_MARGIN << 19) | ((LCD_WIDTH - 1) << 8) | (LCD_LEFT_MARGIN << 0);
//con4 HSPW[8:0]決定對應脈衝的寬度; 選擇option.h檔案裡T35定義引數
rLCDCON4 = (13 << 8) | (LCD_HSYNC_LEN << 0); #if !defined(LCD_CON5)
# define LCD_CON5 ((1<<11) | (1 << 9) | (1 << 8) | (1 << 3) | (1 << 0))
#endif
rLCDCON5 = LCD_CON5; rLCDSADDR1 = ((LCD_ADDR >> 22) << 21) | ((M5D(LCD_ADDR >> 1)) << 0);
rLCDSADDR2 = M5D((LCD_ADDR + LCD_WIDTH * LCD_HEIGHT * 2) >> 1);
rLCDSADDR3 = LCD_WIDTH; rLCDINTMSK |= 3; //中斷遮蔽
rTCONSEL &= (~7); rTPAL = 0x0;
rTCONSEL &= ~((1<<4) | 1); }

使能LCD

/**************************************************************
LCD視訊和控制訊號輸出或者停止,1開啟視訊輸出
**************************************************************/
void Lcd_EnvidOnOff(int onoff)
{
if(onoff==1)
rLCDCON1|=1; // ENVID=ON
else
rLCDCON1 =rLCDCON1 & 0x3fffe; // ENVID Off
}

開啟LCD電源

/**************************************************************
TFT LCD 電源控制引腳使能
**************************************************************/
void Lcd_PowerEnable(int invpwren,int pwren)
{
//GPG4 is setted as LCD_PWREN
rGPGUP = rGPGUP|(1<<4); // Pull-up disable
rGPGCON = rGPGCON|(3<<8); //GPG4=LCD_PWREN //Enable LCD POWER ENABLE Function
rLCDCON5 = rLCDCON5&(~(1<<3))|(pwren<<3); // PWREN
rLCDCON5 = rLCDCON5&(~(1<<5))|(invpwren<<5); // INVPWREN
}

2、開啟觸控式螢幕中斷

/**************************************************************
TFT LCD *觸控式螢幕中斷函式*
**************************************************************/ void __irq Adc_Tc_Handler(void)
{ rADCTSC|=(1<<3)|(1<<2); //XP上拉電阻無效, 自己主動連續測量X座標和Y座標.
rADCCON|=(1<<0);//ADC轉換開始 while(rADCCON&(1<<0));//檢測ADC轉換是否開始且ADCCON[0]自己主動清0
while(!(rADCCON&(0x1<<15))); //檢測ADCCON[15]是否為1,ADC轉換是否結束,(必須)
while(!(rINTPND&((U32)0x1<<31)));//檢測ADC中斷是否已請求 xdata=rADCDAT0&0x3ff;//讀x座標 >>xdata並非畫素點,而是模擬訊號 0-1000
ydata=rADCDAT1&0x3ff;//讀y座標 Uart_Printf("\n Xdata=%04d, Ydata=%04d\n", xdata, ydata); rSUBSRCPND|=(0x1<<9); //清除中斷
rSRCPND|=((U32)0x1<<31);
rINTPND|=((U32)0x1<<31); rADCTSC =0xd3; //ADC等待中斷模式
rADCTSC|=(0x1<<8); //ADCTSC[8]=1,設定抬起中斷訊號 while(!(rSUBSRCPND&(0x1<<9))); //檢測觸屏抬起中斷是否已請求 rADCTSC &=~(0x1<<8);//ADCTSC[8]=0游標按下中斷訊號 // 因為以下這段程式碼和上面這段程式碼是看到大神們都會加上去的。除錯得到
// 現象:上面的清除中斷實現觸屏中斷,而以下這段則是加快中斷後的響應
// (我的實驗結果是:沒以下的時候,觸屏後的數值顯示時間變長,蜂鳴器的
// 響聲也變長,有種慢一拍的感覺) rSUBSRCPND|=(0x1<<9);
rSRCPND|=((U32)0x1<<31);
rINTPND|=((U32)0x1<<31);
} void Touch_Init(void)
{
rADCCON=((1<<14)|(9<<6)); //A/D分頻時鐘有效,其值為9
rADCTSC=0xd3; //游標按下中斷訊號,YM有效,YP無效,XM有效,XP無效,XP上拉電阻,普通ADC轉換,等待中斷模式
rADCDLY=50000; //正常轉換模式轉換延時大約為(1/3.6864M)*50000=13.56ms rINTSUBMSK &=~(0x1<<9);//TC中斷使能
rINTMSK &=~((U32)0x1<<31);//ADC總中斷使能 pISR_ADC=(U32)Adc_Tc_Handler;//指向中斷向量表 }

3、獲取鍵值

並定義變數botten1儲存鍵值,flag1按鍵標記。flag2運算標記

/**************************************************************
------------獲取鍵值--------------
**************************************************************/
void get_key(void){
//數字塊
if( xdata >= 70 && xdata <= 285 && ydata >= 100 && ydata < 262 ) //0
{ Beep(2000, 100);botten1 = 0;flag1=1;xdata = ydata = 0; }
else if( xdata >= 70 && xdata <= 285 && ydata >= 263 && ydata < 425 ) //1
{ Beep(2000, 100);botten1 = 1;flag1=1;xdata = ydata = 0; }
else if( xdata >= 285 && xdata <= 500 && ydata >= 263 && ydata < 425 ) //2
{ Beep(2000, 100);botten1 = 2;flag1=1;xdata = ydata = 0; }
else if( xdata >= 500 && xdata <= 715 && ydata >= 263 && ydata < 425 ) //3
{ Beep(2000, 100);botten1 = 3;flag1=1;xdata = ydata = 0; }
else if( xdata >= 70 && xdata <= 285 && ydata >= 425 && ydata < 587 ) //4
{ Beep(2000, 100);botten1 = 4;flag1=1;xdata = ydata = 0; }
else if( xdata >= 285 && xdata <= 500 && ydata >= 425 && ydata < 587 ) //5
{ Beep(2000, 100);botten1 = 5;flag1=1;xdata = ydata = 0; }
else if( xdata >= 500 && xdata <= 715 && ydata >= 425 && ydata < 587 ) //6
{ Beep(2000, 100);botten1 = 6;flag1=1;xdata = ydata = 0; }
else if( xdata >= 70 && xdata <= 285 && ydata >= 587 && ydata < 750 ) //7
{ Beep(2000, 100);botten1 = 7;flag1=1;xdata = ydata = 0; }
else if( xdata >= 285 && xdata <= 500 && ydata >= 587 && ydata < 750 ) //8
{ Beep(2000, 100);botten1 = 8;flag1=1;xdata = ydata = 0; }
else if( xdata >= 500 && xdata <= 715 && ydata >= 587 && ydata < 750 ) //9
{ Beep(2000, 100);botten1 = 9;flag1=1;xdata = ydata = 0; }
else
//功能運算塊
if( xdata >= 715 && xdata <= 930 && ydata >= 100 && ydata < 262 ) //除
{ Beep(2000, 100);botten1 = '/';flag1=1;flag2=1;xdata = ydata = 0; }
else if( xdata >= 715 && xdata <= 930 && ydata >= 263 && ydata < 425 ) //乘以
{ Beep(2000, 100);botten1 = '*';flag1=1;flag2=2;xdata = ydata = 0; }
else if( xdata >= 715 && xdata <= 930 && ydata >= 425 && ydata < 587 ) //減法
{ Beep(2000, 100);botten1 = '-';flag1=1;flag2=3;xdata = ydata = 0; }
else if( xdata >= 715 && xdata <= 930 && ydata >= 587 && ydata < 750 ) //加法
{ Beep(2000, 100);botten1 = '+';flag1=1;flag2=4;xdata = ydata = 0; }
else
if( xdata >= 500 && xdata <= 715 && ydata >= 100 && ydata < 262 ) //等於
{ Beep(2000, 100);botten1 = '=';flag1=1;xdata = ydata = 0; }
else
if( xdata >= 285 && xdata <= 500 && ydata >= 100 && ydata < 262 ) // 清空
{ Beep(2000, 100);botten1 = 'c';flag1=1;xdata = ydata = 0; }
}

4、區分鍵值來呼叫數字圖片顯示

/**************************************************************
------------處理鍵值--------------
**************************************************************/
void resout(){ if(flag2==4) {sum1=sum1+sum2; show_picturu(sum1); sum1=0;sum2=0;flag2=0; } //依據標誌flag2 進行對應的 sum1=sum1 ? sum2 的運算,運算完sum1 sum2置零
else if(flag2==3) {sum1=sum1-sum2; show_picturu(sum1); sum1=0;sum2=0;flag2=0; }
else if(flag2==2){sum1=sum1*sum2; show_picturu(sum1); sum1=0;sum2=0;flag2=0; }
else if(flag2==1){
if(sum2==0) {sum1=0;sum2=0;flag2=0; Pait_Bmp(1, 34, 236, 30, error);Delay(500);show_picturu(0);} //對除數為0處理。
else {sum1=sum1/sum2;show_picturu(sum1); sum1=0;sum2=0;flag2=0; }} //注意:除法運算結果會捨去小數部分 }
void cleaning(){
sum1=0,sum2=0;flag2=0;show_picturu(0);
}
void show_num(void){
while(flag1){
flag1=0; //標誌置零
switch(botten1){
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:{sum2=sum2*10+botten1;
if(sum2>999999999){
sum2=0;Pait_Bmp(2, 34, 236, 30, numerror);
Delay(500);show_picturu(sum2);
}
else show_picturu(sum2);
} break; //按鍵值存於 sum2 case '+':
case '-':
case '*':
case '/': sum1=sum2,sum2=0; break; //sum2值轉存於sum1,sum2置零 case '=': resout(); break; //之前把以下的這段放在這裡,觀察變數發現sum1和和sum2到這裡就置零了(按下=後永遠等於0),無奈之下試試把推斷放進一個函式 resout(); 裡看看。結果成功了! !。
/* if(flag2==4) {show_picturu(sum1+sum2); sum2=0;flag2=0;} //依據標誌flag2 進行對應的 sum1=sum1 ? sum2 的運算
else if(flag2==3) {show_picturu(sum1-sum2); sum2=0;flag2=0; }
else if(flag2==2){show_picturu(sum1*sum2); sum2=0;flag2=0; }
else if(flag2==1){
if(sum2==0) {sum1=0;sum2=0;flag2=0; Pait_Bmp(1, 34, 236, 30, error);Delay(500);show_picturu(0);} //對除數為0處理。
else {show_picturu(sum1/sum2); sum2=0;flag2=0; }} //注意:除法運算結果會捨去小數部分
*/ case 'c': cleaning(); break;
} }
}

5、呼叫圖片

<span style="font-size:10px;">/**************************************************************
------------呼叫圖片函式--------------
**************************************************************/
void show_picturu(int sum){
int k=0,j=0;
Pait_Bmp(1, 34, 238, 30, clean);
if(sum>0){ //數值大於0時
for(;sum>0;){
k=sum%10; //k用來取餘數
sum=sum/10; //num捨去最後一位
++j; //j用來標誌k的餘數在原數值中的實際位數
numTOpic(k,j);
}
}
else if(sum==0){ //數值等於0時
numTOpic(0,1);
}
else if(sum<0){ //數值小於0時
sum=-sum;
for(;sum>0;){
k=sum%10; //k用來取餘數
sum=sum/10; //num捨去最後一位
++j; //j用來標誌k的餘數在原數值中的實際位數
numTOpic(k,j);
}
Pait_Bmp(238-13*(j+1), 34, 13, 30, num_);
} }
void numTOpic(int m ,int n){
switch(m){
case 0:Pait_Bmp(238-13*n, 34, 13, 30, num0);break;
case 1:Pait_Bmp(238-13*n, 34, 13, 30, num1);break;
case 2:Pait_Bmp(238-13*n, 34, 13, 30, num2);break;
case 3:Pait_Bmp(238-13*n, 34, 13, 30, num3);break;
case 4:Pait_Bmp(238-13*n, 34, 13, 30, num4);break;
case 5:Pait_Bmp(238-13*n, 34, 13, 30, num5);break;
case 6:Pait_Bmp(238-13*n, 34, 13, 30, num6);break;
case 7:Pait_Bmp(238-13*n, 34, 13, 30, num7);break;
case 8:Pait_Bmp(238-13*n, 34, 13, 30, num8);break;
case 9:Pait_Bmp(238-13*n, 34, 13, 30, num9);break;
}
}
</span>

附:

硬體環境:J-link v8、mini2440、J-link轉接板、串列埠轉USB線、T35 TFT LCD屏

軟體環境:windows7(32位)、開發板uboot(NandFlash)、J-link驅動(J-Link ARM V4.10i)、SecureCRT、ADS1.2

完整專案下載

版權宣告:本文部落格原創文章,部落格,未經同意,不得轉載。