首页 > 代码库 > mini2440裸机试炼之—计算器(LCD显示,触摸屏中断)
mini2440裸机试炼之—计算器(LCD显示,触摸屏中断)
基于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屏的工作时序:
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)
/************************************************************** 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转换开始 rSUBSRCPND|=(0x1<<9); rSRCPND|=((U32)0x1<<31); rINTPND|=((U32)0x1<<31); rADCTSC =0xd3; //ADC等待中断模式 rADCTSC|=(0x1<<8); //ADCTSC[8]=1,设置抬起中断信号 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 = http://www.mamicode.com/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
完整项目下载mini2440裸机试炼之—计算器(LCD显示,触摸屏中断)