基於mini2440簡單計算器的實現(裸機程式碼)
阿新 • • 發佈:2019-01-24
基於mini2440簡易計算器使用的是陣列實現,並非逆波蘭式,因此功能不夠強大,僅供驅動學習,以及C語言基礎程式設計學習之用.有時間讀者可以用逆波蘭式來實現強大功能計算器,原理也很簡單,建議讀《c程式設計第二版》裡面有演算法的程式碼.讀者自行研究.此程式基於電子相簿的改進,觸控式螢幕,LCD,字元現實,數字輸入等等.
主函式部分:
計算器的輸入及其計算部分,結合觸控式螢幕,利用陣列實現字元和數字的儲存等:#include "def.h" #include "option.h" #include "2440addr.h" #include "profile.h" extern U32 X,Y; extern void BMP_display(int x0,int y0,int x1,int y1,const U8 *bmp); extern void CLK_init(void); extern void LCD_IO_init(void); extern void LCD_POWER(void); extern void LCD_init(void); extern void LCD_on(void); extern void LCD_off(void); extern void Tc_calibrate(void); extern void input(void); extern void Touch_Init(void); extern void word(int x,int y,char* string); extern unsigned char gImage[]; //extern宣告引用外部陣列 void Main(void) { rGPBCON=(1<<0); rGPBDAT=(0<<0);//關閉蜂鳴器 CLK_init(); LCD_POWER(); LCD_IO_init(); LCD_init(); LCD_on(); Touch_Init(); MMU_Init(); //初始化MMU,解決中斷向量表入口地址與記憶體地址之間不一致問題,進行地址的重對映 BMP_display(0, 0, 320,240, gImage); //顯示圖片 while(1) { Tc_calibrate(); input(); } }
#include "def.h" #include "2440addr.h" #define touch_p (X>0&&X<80&&Y>198&&Y<240) #define touch_0 (X>80&&X<160&&Y>198&&Y<240) #define touch_e (X>160&&X<240&&Y>198&&Y<240) #define touch_a (X>240&&X<320&&Y>198&&Y<240) #define touch_1 (X>0&&X<80&&Y>156&&Y<198) #define touch_2 (X>80&&X<160&&Y>156&&Y<198) #define touch_3 (X>160&&X<240&&Y>156&&Y<198) #define touch_s (X>240&&X<320&&Y>156&&Y<198) #define touch_4 (X>0&&X<80&&Y>113&&Y<156) #define touch_5 (X>80&&X<160&&Y>113&&Y<156) #define touch_6 (X>160&&X<240&&Y>113&&Y<156) #define touch_m (X>240&&X<320&&Y>113&&Y<156) #define touch_7 (X>0&&X<80&&Y>72&&Y<113) #define touch_8 (X>80&&X<160&&Y>72&&Y<113) #define touch_9 (X>160&&X<240&&Y>72&&Y<113) #define touch_d (X>240&&X<320&&Y>72&&Y<113) #define touch_c (X>241&&X<320&&Y>44&&Y<73) #define white 0xffffff #define B_off rGPBDAT=(0<<0) //關閉蜂鳴器 #define B_on rGPBDAT=(1<<0) //開啟蜂鳴器 extern U32 X,Y; extern unsigned char gImage[]; //extern宣告引用外部陣列 extern Draw_REC(int x,int y,int x1,int y1,U32 color); extern void BMP_display(int x0,int y0,int x1,int y1,const U8 *bmp); extern void Draw_ASCII(U32 x,U32 y,U32 color,const unsigned char ch[]); extern void word(int x,int y,char* string); extern void Main(void); char op,opf;//用於何種元算的分揀操作符 int Num1,Num2;//參與運算兩個數 int F1,F2;//答案 char num[10000];//用於顯示的字元陣列 int num1[100],num2[100];//儲存輸入數字的陣列 int n[100],t[100]; //提取答案的各個位 int n1=0,n2=0;//用於輸入數字分揀操作符 int len=0,len1=0;//用於計算答案的位數 int i=0,j=0,k=0,a=0; /********************************** *清除各個標誌函式 **********************************/ void Clear_f(void) { int b=0,c=0; for(c=0;c<10000;c++) { num[c]=' '; } for(b=0;b<100;b++) { num1[b]=0; num2[b]=0; n[b]=0; t[b]=0; } op=0;opf=0; Num1=0;Num2=0; F1=0;F2=0; n1=0;n2=0; len=0;len1=0; i=0;j=0;k=0;a=0; } /********************************** *四則運算函式 **********************************/ void Calc(int *Num_1,int *Num_2,int *f) { switch(op) //分揀操作符 { case'n': //無運算或等號 *f = *f; break; case '+': //加 *f = *Num_1+*Num_2; break; case '-': //減 *f = *Num_1-*Num_2; break; case '*': //乘 *f =*Num_1*(*Num_2); break; case '/': //除 *f = *Num_1/(*Num_2); break; } } /********************************** *延遲函式 **********************************/ void delay(int times) { int i; for(;times>0;times--) for(i=0;i<400;i++); } /********************************** *介面輸入函式 **********************************/ void input(void) { int flag=0; int numb[10]={0,1,2,3,4,5,6,7,8,9}; char nums[10]={'0','1','2','3','4','5','6','7','8','9'}; if(op=='+'||op=='-'||op=='*'||op=='/') flag=1; else flag=0; if(flag==0)//無操作符 { if(touch_0) { num[i]='0'; num1[i]=0; i++; n1++; Draw_REC(80,198,160,239,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_1) { num[i]='1'; num1[i]=1; i++; n1++; Uart_Printf("n1=%4d\n",n1); Draw_REC(0,156,80,198,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_2) { num[i]='2'; num1[i]=2; i++; n1++; Draw_REC(80,156,160,198,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_3) { num[i]='3'; num1[i]=3; i++; n1++; Draw_REC(160,156,240,198,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_4) { num[i]='4'; num1[i]=4; i++; n1++; Draw_REC(0,113,80,156,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_5) { num[i]='5'; num1[i]=5; i++; n1++; Draw_REC(80,113,160,156,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_6) { num[i]='6'; num1[i]=6; i++; n1++; Draw_REC(160,113,240,156,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_7) { num[i]='7'; num1[i]=7; i++; n1++; Draw_REC(0,72,80,113,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_8) { num[i]='8'; num1[i]=8; i++; n1++; Draw_REC(80,72,160,113,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_9) { num[i]='9'; num1[i]=9; i++; n1++; Draw_REC(160,72,240,113,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } } else { if(touch_0) { num[i]='0'; num2[j]=0; i++; j++; n2++; Draw_REC(80,198,160,239,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_1) { num[i]='1'; num2[j]=1; i++; j++; n2++; Draw_REC(0,156,80,198,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_2) { num[i]='2'; num2[j]=2; i++; j++; n2++; Draw_REC(80,156,160,198,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_3) { num[i]='3'; num2[j]=3; i++; j++; n2++; Draw_REC(160,156,240,198,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_4) { num[i]='4'; num2[j]=4; i++; j++; n2++; Draw_REC(0,113,80,156,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_5) { num[i]='5'; num2[j]=5; i++; j++; n2++; Draw_REC(80,113,160,156,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_6) { num[i]='6'; num2[j]=6; i++; j++; n2++; Draw_REC(160,113,240,156,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_7) { num[i]='7'; num2[j]=7; i++; j++; n2++; Draw_REC(0,72,80,113,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_8) { num[i]='8'; num2[j]=8; i++; j++; n2++; Draw_REC(80,72,160,113,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_9) { num[i]='9'; num2[j]=9; i++; j++; n2++; Draw_REC(160,72,240,113,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } } if(touch_p) { op='.'; num[i]='.'; i++; Draw_REC(0,198,80,239,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_e) { opf='='; //num[i]='='; //i++; Draw_REC(160,198,240,239,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_a) { op='+'; num[i]='+'; i++; Draw_REC(240,198,319,239,white); B_on; delay(1000); B_off; BMP_display(0,0, 320,240,gImage); } else if(touch_s) { op='-'; num[i]='-'; i++; Draw_REC(240,156,319,198,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_m) { op='*'; num[i]='*'; i++; Draw_REC(240,113,319,156,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_d) { op='/'; num[i]='/'; i++; Draw_REC(240,72,319,113,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); } else if(touch_c) { Draw_REC(241,44,319,73,white); B_on; delay(1000); B_off; BMP_display(0,0,320,240,gImage); Clear_f(); } switch(n1) { case 1:Num1=num1[0];break; case 2:Num1=num1[0]*10+num1[1];break; case 3:Num1=num1[0]*100+num1[1]*10+num1[2];break; case 4:Num1=num1[0]*1000+num1[1]*100+num1[2]*10+num1[3];break; case 5:Num1=num1[0]*10000+num1[1]*1000+num1[2]*100+num1[3]*10+num1[4];break; case 6:Num1=num1[0]*100000+num1[1]*10000+num1[2]*1000+num1[3]*100+num1[4]*10+num1[5];break; } switch(n2) { case 1:Num2=num2[0];break; case 2:Num2=num2[0]*10+num2[1];break; case 3:Num2=num2[0]*100+num2[1]*10+num2[2];break; case 4:Num2=num2[0]*1000+num2[1]*100+num2[2]*10+num2[3];break; case 5:Num2=num2[0]*10000+num2[1]*1000+num2[2]*100+num2[3]*10+num2[4];break; case 6:Num2=num2[0]*100000+num2[1]*10000+num2[2]*1000+num2[3]*100+num2[4]*10+num2[5];break; } word(0,28,num); X=0; Y=0; if(opf=='=') { Calc(&Num1,&Num2,&F1); F2=F1; while(F2>0) { t[a++]=F2%10; F2=F2/10; len++; } len1=len; a=0; while(len1--) { n[len1]=t[a++]; } switch(len) { case 1: { for(k=0;k<10;k++) {if(numb[k]==n[0]) num[i+1]=nums[k];};break; } case 2: { for(k=0;k<10;k++) {if(numb[k]==n[0]) num[i+1]=nums[k];} for(k=0;k<10;k++) {if(numb[k]==n[1]) num[i+2]=nums[k];};break; } case 3: { for(k=0;k<10;k++) {if(numb[k]==n[0]) num[i+1]=nums[k];} for(k=0;k<10;k++) {if(numb[k]==n[1]) num[i+2]=nums[k];} for(k=0;k<10;k++) {if(numb[k]==n[2]) num[i+3]=nums[k];};break; } case 4: { for(k=0;k<10;k++) {if(numb[k]==n[0]) num[i+1]=nums[k];} for(k=0;k<10;k++) {if(numb[k]==n[1]) num[i+2]=nums[k];} for(k=0;k<10;k++) {if(numb[k]==n[2]) num[i+3]=nums[k];} for(k=0;k<10;k++) {if(numb[k]==n[3]) num[i+4]=nums[k];};break; } case 5: { for(k=0;k<10;k++) {if(numb[k]==n[0]) num[i+1]=nums[k];} for(k=0;k<10;k++) {if(numb[k]==n[1]) num[i+2]=nums[k];} for(k=0;k<10;k++) {if(numb[k]==n[2]) num[i+3]=nums[k];} for(k=0;k<10;k++) {if(numb[k]==n[3]) num[i+4]=nums[k];} for(k=0;k<10;k++) {if(numb[k]==n[4]) num[i+5]=nums[k];};break; } } word(0,28,num); Uart_Printf("Num1=%4d, Num2=%4d,F1=%4d\n",Num1,Num2,F1); op=0; opf=0; } }
LCD驅動部分:
#define GLOBAL_CLK 1 #include "def.h" #include "option.h" #include "2440addr.h" #include "profile.h" #define LCD_WIDTH 320 //螢幕寬度 #define LCD_HEIGHT 240 //螢幕高度 #define CLKVAL 4 //時鐘訊號 //垂直同步訊號的脈寬、後肩和前肩 #define VSPW (2-1) #define VBPD (11-1) #define VFPD (5-1) //水平同步訊號的脈寬、後肩和前肩 #define HSPW (2-1) #define HBPD (69-1) #define HFPD (5-1) //顯示尺寸 #define HOZVAL (LCD_WIDTH-1) #define LINEVAL (LCD_HEIGHT-1) //定義顯示快取,volatile宣告編譯不對此進行優化,直接讀取原始地址 volatile unsigned short LCD_BUFFER[LCD_HEIGHT][LCD_WIDTH]; //宣告為靜態函式,僅在本檔案可見,其他檔案不能使用該函式 /********************************** *時鐘初始化 **********************************/ void CLK_init(void) { rMPLLCON &= ~0xFFFFF; rMPLLCON |= (127<<12)|(2<<4)|1; //初始化FCLK為405M rCLKDIVN = (2<<1)|1; //HCLK = FCLK/4 =100M,PCLK = HCLK/2 = 50M } /********************************** *LCD埠初始化 **********************************/ void LCD_IO_init(void) { rGPCUP=0xff; //GPC口上拉電阻不可用 rGPCCON=0xaaaa02aa;//GPC8-15設定為VD, VM,VFRAME,VLINE,VCLK,LEND rGPDUP=0xff; //GPD口上拉電阻不可用 rGPDCON=0xaaaaaaaa; //GPD0-15設定為VD } /********************************** *LCD電源管理 **********************************/ void LCD_POWER(void) { rGPGUP=(1<<4); rGPGCON=(3<<8); //GPG4設定為LCD_PWREN rLCDCON5=(1<<3); //Enable PWREN signal } /********************************** *LCD開啟 **********************************/ void LCD_on(void) { rLCDCON1 |=1; //利用LCDCON1控制相關引數實現開啟LCD } /********************************** *LCD關閉 **********************************/ void LCD_off(void) { rLCDCON1 &=~1; //利用LCDCON1控制相關引數實現關閉LCD } /********************************** *LCD初始化 **********************************/ void LCD_init(void) { CLK_init(); LCD_POWER(); LCD_IO_init(); LCD_on(); rLCDCON1=(CLKVAL<<8)|(3<<5)|(12<<1)|(0<<0); //VCLK=10M,TFT LCD,16bpp rLCDCON2=(VBPD<<24)|(LINEVAL<<14)|(VFPD<<6)|(VSPW); rLCDCON3=(HBPD<<19)|(HOZVAL<<8)|(HFPD); rLCDCON4=HSPW; /*5:6:5Format,Enable PWREN signal,Swap Enable*/ rLCDCON5=(1<<11)|(1<<9)|(1<<8)|(1<<3)|1; /*視訊記憶體起始地址[30:22]儲存到LCDSADDR1[29:21],視訊記憶體始地址[21:1]位 儲存到LCDSADDR1[20:0],視訊記憶體結束地址[21:1]儲存到LCDSADDR2[20:0]*/ rLCDSADDR1=(((U32)LCD_BUFFER>>22)<<21)|(((U32)LCD_BUFFER&0x3fffff)>>1); rLCDSADDR2=(((U32)LCD_BUFFER+LCD_WIDTH*LCD_HEIGHT*2)>>1)&0x1fffff; rLCDSADDR3=LCD_WIDTH; //設定虛擬屏設定為螢幕寬度,沒有可以不設定 rTPAL=0; //臨時調色盤不可用 rLCDINTMSK |=3; //遮蔽 LCD 中斷 rTCONSEL &=~(0x17); //LCC3600,LPC3600不可用 }
GUI部分,字元,圖片處理函式等:
#include "def.h"
#include "Font_libs.h"
#define LCD_WIDTH 320 //螢幕寬度
#define LCD_HEIGHT 240 //螢幕高度
//定義顯示快取,volatile宣告編譯不對此進行優化,直接讀取原始地址
extern volatile unsigned short LCD_BUFFER[LCD_HEIGHT][LCD_WIDTH];
/**********************************
*重新整理背景顏色
**********************************/
void LCD_clear(U32 color)
{
U32 x,y;
for(y=0;y<LCD_HEIGHT;y++)
{
for(x=0;x<LCD_WIDTH;x++)
{
LCD_BUFFER[y][x]=color;
}
}
}
/**********************************
*BMP陣列圖片顯示
**********************************/
void BMP_display(int x0,int y0,int x1,int y1,const U8 *bmp)
{
int x,y,p=0;
U32 data;
for(y=0;y<y1;y++)
{
for(x=0;x<x1;x++)
{
data=(bmp[p]<<8|bmp[p+1]);
if((x0+x)<LCD_WIDTH && (y0+y)<LCD_HEIGHT)
LCD_BUFFER[y0+y][x0+x]=data;
p=p+2;
}
}
}
/**********************************
*繪製畫素點
**********************************/
void PutPixel(U32 x,U32 y,U32 c )
{
LCD_BUFFER[y][x]=c;
}
/**********************************
*繪製大小為16×16的中文字元
**********************************/
void Draw_Text16(U32 x,U32 y,U32 color,const unsigned char ch[])
{
unsigned short int i,j;
unsigned char mask,buffer;
for(i=0;i<16;i++)
{
mask=0x80; //掩碼
buffer=ch[i*2]; //提取一行的第一個位元組
for(j=0;j<8;j++)
{
if(buffer&mask)
{
PutPixel(x+j,y+i,color); //為筆畫上色
}
mask=mask>>1;
}
mask=0x80; //掩碼復位
buffer=ch[i*2+1]; //提取一行的第二個位元組
for(j=0;j<8;j++)
{
if(buffer&mask)
{
PutPixel(x+j+8,y+i,color); //為筆畫上色
}
mask=mask>>1;
}
}
}
/**********************************
*繪製大小為8×16的ASCII碼
**********************************/
void Draw_ASCII(U32 x,U32 y,U32 color,const unsigned char ch[])
{
unsigned short int i,j;
unsigned char mask,buffer;
for(i=0;i<16;i++)
{
mask=0x80;
buffer=ch[i];
for(j=0;j<8;j++)
{
if(buffer&mask)
{
PutPixel(x+j,y+i,color);
}
mask=mask>>1;
}
}
}
/**********************************
*繪製中文字元或ASCII
**********************************/
void word(int x,int y,char* string)
{
int i,j=0;
unsigned char qh,wh;
const unsigned char *mould;
int length=0;
while(string[length]!='\0')
{length++;}
for(i=0;i<=length-1;i++)
{
if(string[i]&0x80) //中文字元
{
qh=string[i]-0xa0; //區號
wh=string[i+1]-0xa0; //位號
mould=& __CHS[((qh-1)*94+wh-1)*32 ];
Draw_Text16(x+j,y,0xffffff,mould);
j+=16;//每寫完一個右移16個畫素
i++;
}
else //ASCII碼字元
{
mould=&__ASCII[string[i]*16];
Draw_ASCII(x+j,y,0xffffff,mould);
j+=8;//每寫完一個右移8個畫素
}
}
}
/**********************************
*畫直線
**********************************/
void Draw_Line(int x1,int y1,int x2,int y2,U32 color)
{
int dx,dy,e;
dx=x2-x1;
dy=y2-y1;
if(dx>=0)
{
if(dy >= 0) // dy>=0
{
if(dx>=dy) // 1/8 octant
{
e=dy-dx/2;
while(x1<=x2)
{
PutPixel(x1,y1,color);
if(e>0){y1+=1;e-=dx;}
x1+=1;
e+=dy;
}
}
else // 2/8 octant
{
e=dx-dy/2;
while(y1<=y2)
{
PutPixel(x1,y1,color);
if(e>0){x1+=1;e-=dy;}
y1+=1;
e+=dx;
}
}
}
else // dy<0
{
dy=-dy; // dy=abs(dy)
if(dx>=dy) // 8/8 octant
{
e=dy-dx/2;
while(x1<=x2)
{
PutPixel(x1,y1,color);
if(e>0){y1-=1;e-=dx;}
x1+=1;
e+=dy;
}
}
else // 7/8 octant
{
e=dx-dy/2;
while(y1>=y2)
{
PutPixel(x1,y1,color);
if(e>0){x1+=1;e-=dy;}
y1-=1;
e+=dx;
}
}
}
}
else //dx<0
{
dx=-dx; //dx=abs(dx)
if(dy >= 0) // dy>=0
{
if(dx>=dy) // 4/8 octant
{
e=dy-dx/2;
while(x1>=x2)
{
PutPixel(x1,y1,color);
if(e>0){y1+=1;e-=dx;}
x1-=1;
e+=dy;
}
}
else // 3/8 octant
{
e=dx-dy/2;
while(y1<=y2)
{
PutPixel(x1,y1,color);
if(e>0){x1-=1;e-=dy;}
y1+=1;
e+=dx;
}
}
}
else // dy<0
{
dy=-dy; // dy=abs(dy)
if(dx>=dy) // 5/8 octant
{
e=dy-dx/2;
while(x1>=x2)
{
PutPixel(x1,y1,color);
if(e>0){y1-=1;e-=dx;}
x1-=1;
e+=dy;
}
}
else // 6/8 octant
{
e=dx-dy/2;
while(y1>=y2)
{
PutPixel(x1,y1,color);
if(e>0){x1-=1;e-=dy;}
y1-=1;
e+=dx;
}
}
}
}
}
/**************************************************************
在LCD螢幕上畫一個矩形
**************************************************************/
void Draw_REC(int x1,int y1,int x2,int y2,U32 color)
{
Draw_Line(x1,y1,x2,y1,color);
Draw_Line(x2,y1,x2,y2,color);
Draw_Line(x1,y2,x2,y2,color);
Draw_Line(x1,y1,x1,y2,color);
}
/**********************************
*畫圓函式
**********************************/
void Draw_Circular(U32 c)
{
int x,y ;
int tempX,tempY;
int radius=80;
int SquareOfR=radius*radius;
for( y=0;y<LCD_WIDTH;y++ )
{
for( x=0; x<LCD_HEIGHT;x++ )
{
if(y<=120&&x<=160)
{
tempY=120-y;
tempX=160-x;
}
else if(y<=120&&x>=160)
{
tempY=120-y;
tempX=x-160;
}
else if(y>=120&& x<=160)
{
tempY=y-120;
tempX=160-x;
}
else
{
tempY=y-120;
tempX=x-160;
}
if ((tempY*tempY+tempX*tempX)<=SquareOfR)
LCD_BUFFER[y][x] =c;
}
}
}
觸控式螢幕的ADC驅動部分:
#include "def.h"
#include "mmu.h"
#include "2440addr.h"
#include "2440lib.h"
#define PRSCVL 9
volatile int xdata, ydata;
int inte=1;
void __irq Adc_Tc_Handler(void);
void Touch_Init(void)
{
rADCCON=((1<<14)|(PRSCVL<<6)); //A/D分頻時鐘有效,其值為9
rADCTSC=0xd3; //游標按下中斷訊號,YM有效,YP無效,XM有效,XP無效,XP上拉電阻,普通ADC轉換,等待中斷模式
rADCDLY=50000; //正常轉換模式轉換延時大約為(1/3.6864M)*50000=13.56ms
rINTSUBMSK &=~(1<<9);//TC中斷使能
rINTMSK &=~(1<<31);//ADC總中斷使能
pISR_ADC=(int)Adc_Tc_Handler;//指向中斷向量表
}
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&(1<<15))); //檢測ADCCON[15]是否為1,ADC轉換是否結束,(必須)
while(!(rINTPND&(1<<31)));//檢測ADC中斷是否已請求
xdata=rADCDAT0&0x3ff;//讀x座標
ydata=rADCDAT1&0x3ff;//讀y座標
Uart_Printf("\nXdata=%04d, Ydata=%04d\n", xdata, ydata);
rSUBSRCPND|=(1<<9);
rSRCPND|=(1<<31);
rINTPND|=(1<<31);
rADCTSC =0xd3; //ADC等待中斷模式
rADCTSC|=(1<<8); //ADCTSC[8]=1,設定擡起中斷訊號
while(!(rSUBSRCPND&(1<<9))); //檢測觸屏擡起中斷是否已請求
rADCTSC &=~(1<<8);//ADCTSC[8]=0游標按下中斷訊號
rSUBSRCPND|=(1<<9);
rSRCPND|=(1<<31);
rINTPND|=(1<<31);
inte=1;
}
觸控式螢幕矯正及其計算部分(三點矯正):
#include "def.h"
#include "2440addr.h"
#include "2440lib.h"
#define LCD_CALIBRATE 0 //1時開啟觸控式螢幕校驗
#define BLACK (0x000000) //黑色
#define WHITE (0xffffff) //白色
#define YdataClear ydata=0
#define XdataClear xdata=0
extern volatile int xdata, ydata;
extern int inte;
extern void LCD_clear(U32 n);
extern void Draw_X(int x,int y,U32 color);
extern void CLK_init(void);
extern void LCD_IO_init(void);
extern void LCD_POWER(void);
extern void LCD_init(void);
extern void LCD_on(void);
extern void LCD_off(void);
extern void Touch_Init(void);
U32 X,Y;
float x0,y0,x1,y1,x2,y2;
float xt,yt;
float A=-0.363030314,B=-0.00609157188,C=349.596954,D=-0.00253245141,E=0.312928855,F=-38.1721191,K=292207;
//讀取TC座標
void Touch_GetAdXY(float *x,float *y)
{
*x=xdata;
*y=ydata;
}
//矯正引數A,B,C,D,E,F,K的計算
void Calculate_P(float xt0,float yt0,float xt1,float yt1,float xt2,float yt2)
{
float xd0=160,yd0=40,xd1=40,yd1=180,xd2=260,yd2=200;
K=(xt0-xt2)*(yt1-yt2)-(xt1-xt2)*(yt0-yt2);
A=((xd0-xd2)*(yt1-yt2)-(xd1-xd2)*(yt0-yt2))/K;
B=((xt0-xt2)*(xd1-xd2)-(xd0-xd2)*(xt1-xt2))/K;
C=(yt0*(xt2*xd1-xt1*xd2)+yt1*(xt0*xd2-xt2*xd0)+yt2*(xt1*xd0-xt0*xd1))/K;
D=((yd0-yd2)*(yt1-yt2)-(yd1-yd2)*(yt0-yt2))/K;
E=((xt0-xt2)*(yd1-yd2)-(yd0-yd2)*(xt1-xt2))/K;
F=(yt0*(xt2*yd1-xt1*yd2)+yt1*(xt0*yd2-xt2*yd0)+yt2*(xt1*yd0-xt0*yd1))/K;
}
//資料的矯正
void Tc_Correct(float xt,float yt)
{
X=(U32)(A*xt+B*yt+C);
Y=(U32)(D*xt+E*yt+F);
}
//觸控式螢幕矯正函式
void Tc_calibrate(void)
{
#if LCD_CALIBRATE==1
CLK_init();
LCD_POWER();
LCD_IO_init();
LCD_init();
LCD_on();
Touch_Init();
LCD_clear(BLACK);//全屏顯示黑色
//位置1
Draw_X(160,40,WHITE);
YdataClear;
XdataClear;
while(1)
{
Touch_GetAdXY(&x0,&y0);//讀取座標位置
if((252<y0)&&(y0<256))//按鍵按下
{
Draw_X(160,40,BLACK);
break;
}
}
//位置2
Draw_X(40,180,WHITE);
YdataClear;
XdataClear;
while(1)
{
Touch_GetAdXY(&x1,&y1);//讀取座標位置
if((702<y1)&&(y1<706))//按鍵按下
{
Draw_X(40,180,BLACK);
break;
}
}
//位置3
Draw_X(260,200,WHITE);
YdataClear;
XdataClear;
while(1)
{
Touch_GetAdXY(&x2,&y2);//讀取座標位置
if((762<y2)&&(y2<764))//按鍵按下
{
Draw_X(260,200,BLACK);
break;
}
}
Calculate_P(x0,y0,x1,y1,x2,y2);
#endif
if(inte)
{
Touch_GetAdXY(&xt,&yt);//讀取座標位置
Tc_Correct(xt,yt);
Uart_Printf("X=%4d, Y=%4d\n",X,Y);
inte=0;
}
}
注:字型檔檔案"Font_libs.h",和圖片的取模讀者自行製作.每個部分為獨立C檔案.
用到的介面圖片如下: