当前位置:首页 > 单片机 > 单片机
[导读]触摸屏是通过中断来实现的。我的程序是在sdram中运行的,要想正确的实现中断跳转,就要使MMU工作,实现物理地址与虚拟地址的映射,把虚拟地址0x00000000映射到物理地址0x30000000(sdram的首地址)。MMU相应的函数在24

触摸屏是通过中断来实现的。我的程序是在sdram中运行的,要想正确的实现中断跳转,就要使MMU工作,实现物理地址与虚拟地址的映射,把虚拟地址0x00000000映射到物理地址0x30000000(sdram的首地址)。MMU相应的函数在2440slib.s中。

触摸屏可分为矢量压力传感式、电阻式、电容式、红外式和表面声波式等,我用的是最普遍的-四线电阻式。


s3c2440集成了4线制电阻式的触摸屏接口,触点坐标的检测是通过A/D转换来实现的。s3c2440提供8路A/D模拟输入,其中有4路是与触摸屏复用的,s3c2440比s3c2410改进的地方是片内部加入了开关用的MOS管,在设计电路时,直接将4路触摸屏引出外加一路基准电压(3.3v)就可以了。
  s3c2440一共有4种触摸屏接口模式,其中,自动(连续)XY坐标转换模式和等待中断模式应用地比较常见。在此,为实现触摸屏的功能,先是设置为等待中断模式,在产生中断后,再设置为自动(连续)XY坐标转换模式,依次读取触点的坐标值。

  还有就是触摸屏的校准, 校准就是实现触摸屏上的x、y坐标和LCD的像素坐标对应起来。比较常见的校正方法是三点校正法(网上找的),即 LCD上每个点PD的坐标为[XD,YD],触摸屏上每个点PT的坐标为[XT,YT]。要实现触摸屏上的坐标转换为LCD上的坐标,需要下列公式进行转换:

XD=A×XT+B×YT+C

YD=D×XT+E×YT+F

其中有ABCDEF六个参数, 分别解ABC和DEF,需要3组数据,那就需要采集3个校准点:
     XD0=A×XT0+B×YT0+C  YD0=D×XT0+E×YT0+F
XD1=A×XT1+B×YT1+C YD1=D×XT1+E×YT1+F
XD2=A×XT2+B×YT2+CYD2=D×XT2+E×YT2+F
可以用矩阵方面的知识解这三元一次函数得:
D0=(XT0-XT2)×(YT1-YT2)-(XT1-XT2)×(YT0-YT2);
D1=(XD0-XD2)×(YT1-YT2)-(XD1-XD2)×(YT0-YT2);
D2=(XT0-XT2)×(XD1-XD2)-(XD0-XD2)×(XT1-XT2);
D3=YT0×(XT2×XD1-XT1×XD2)+YT1×(XT0×XD2-XT2×XD0)+YT2×(XT1×XD0-XT0×XD1);
D4=(YD0-XD2)×(YT1-YT2)-(YD1-XD2)×(YT0-YT2);
D5=(XT0-XT2)×(YD1-YD2)-(YD0-YD2)×(XT1-XT2);
D6=YT0×(XT2×YD1-XT1×YD2)+YT1×(XT0×YD2-XT2×YD0)+YT2×(XT1×YD0-XT0×YD1);
A=D1/D0;B=D2/D0;C=D3/D0;D=D4/D0;F=D5/D0;A=D6/D0;

程序要实现的功能是:程序一开始,界面上会出现3个十字的取样点,分别标有1、2、3,然后用触笔依次的点击,完成后,会进入第二个界面,用触笔随机的点击屏幕,会以触点绘制出边长为4的小正方形。


简单的程序实现:

#include"def.h"
#include"option.h"
#include"2440addr.h"
#include"2440lib.h"
#include"2440slib.h"
#include"mmu.h"
//================================

externchar__ENTRY[];
//voidMMU_SetMTT(intvaddrStart,intvaddrEnd,intpaddrStart,intattr);
//voidMMU_Init(void);

//LCD*****************************************************
#defineM5D(n)((n)&0x1fffff)//用于设置显示缓存区时,取低21位地址

#defineLCD_WIDTH240//屏幕的宽
#defineLCD_HEIGHT320//屏幕的高

//垂直同步信号的脉宽、后肩和前肩-----这些值是根据TopPoly-TD035STED4.pdf文件中的13页的表
#defineVSPW1//(3-1)
#defineVBPD1//(15-1)
#defineVFPD1//(12-1)

//水平同步信号的脉宽、后肩和前肩-----这些值是根据TopPoly-TD035STED4.pdf文件中的13页的表
#defineHSPW(10-1)
#defineHBPD(20-1)
#defineHFPD(10-1)

//显示尺寸
#defineLINEVAL(LCD_HEIGHT-1)
#defineHOZVAL(LCD_WIDTH-1)

//forLCDCON1
#defineCLKVAL_TFT4//设置时钟信号
#defineMVAL_USED0//
#definePNRMODE_TFT3//TFT型LCD
#defineBPPMODE_TFT13//24位TFT型LCD

//forLCDCON5
#defineBPP24BL0//32位数据表示24位颜色值时,低位数据有效,高8位无效
#defineINVVCLK0//像素值在VCLK下降沿有效
#defineINVVLINE1//翻转HSYNC信号
#defineINVVFRAME1//翻转VSYNC信号
#defineINVVD0//正常VD信号极性
#defineINVVDEN0//正常VDEN信号极性
#definePWREN1//使能PWREN信号
#defineBSWP0//颜色数据字节不交换
#defineHWSWP0//颜色数据半字不交换

//定义显示缓存区
volatileunsignedintLCD_BUFFER[LCD_HEIGHT][LCD_WIDTH];

intA,B,C,D,E,F,K;
volatileintxdata,ydata;
intflagIIC;//IIC标志
intflagTS;//触摸屏标志
//lCD******************************************************
//LCD显示函数//////////////////////////////////////////////////
//延时程序
voiddelay(inta)
{
intk;
for(k=0;k}

//绘制屏幕背景颜色,颜色为c
voidBrush_Background(unsignedintc)
{
intx,y;
for(y=0;y{
for(x=0;x{
LCD_BUFFER[y][x]=c;
}
}
}

//绘制“十”字型
voiddrawCross(unsignedintx,unsignedinty,unsignedintcolor)
{
inti;
for(i=x-10;iLCD_BUFFER[y][i]=color;
for(i=y-10;iLCD_BUFFER[i][x]=color;
}

//绘制正方形
voiddrawsquare(unsignedintx,unsignedinty,unsignedintcolor)
{
inti,j;
intx1=x-2;
inty1=y-2;
for(i=y1;i{
for(j=x1;jLCD_BUFFER[i][j]=color;
}
}

//绘制大小为8×16的ASCII码
voidDraw_ASCII(unsignedintx,unsignedinty,unsignedintcolor,constunsignedchar*ch)
{
unsignedshortinti,j;
unsignedcharmask,buffer;

for(i=0;i<16;i++)
{
mask=0x80;
buffer=ch[i];
for(j=0;j<8;j++)
{
if(buffer&mask)
{
LCD_BUFFER[y+i][x+j]=color;
}
mask=mask>>1;
}
}
}

voidinit_port_lcd()//初始化
{
rGPCCON=0xaaaaaaaa;
rGPCUP=0xffff;//ThepullupfunctionisdisabledGPC[15:0]

//***PORTDGROUP
//Ports:GPD15GPD14GPD13GPD12GPD11GPD10GPD9GPD8GPD7GPD6GPD5GPD4GPD3GPD2GPD1GPD0
//Signal:VD23VD22VD21VD20VD19VD18VD17VD16VD15VD14VD13VD12VD11VD10VD9VD8
//Binary:1010,1010,1010,1010,1010,1010,1010,1010
rGPDCON=0xaaaaaaaa;
rGPDUP=0xffff;

rLCDCON1=(CLKVAL_TFT<<8)|(MVAL_USED<<7)|(PNRMODE_TFT<<5)|(BPPMODE_TFT<<1)|0;
rLCDCON2=(VBPD<<24)|(LINEVAL<<14)|(VFPD<<6)|(VSPW);
rLCDCON3=(HBPD<<19)|(HOZVAL<<8)|(HFPD);
rLCDCON4=(HSPW);//
//rLCDCON4=(5<<0);
rLCDCON5=(BPP24BL<<12)|(INVVCLK<<10)|(INVVLINE<<9)|(INVVFRAME<<8)|(0<<7)|(INVVDEN<<6)|(PWREN<<3)|(BSWP<<1)|(HWSWP);

rLCDSADDR1=(((unsignedint)LCD_BUFFER>>22)<<21)|M5D((unsignedint)LCD_BUFFER>>1);
rLCDSADDR2=M5D((M5D((unsignedint)LCD_BUFFER>>1)+((LCD_WIDTH*32/16+0)*320)));//LCD_WIDTH*LCD_HEIGHT*4
rLCDSADDR3=(LCD_WIDTH*32/16)&0x7ff;//参考s3c2440的手册
rLCDINTMSK|=(3);//屏蔽LCD中断
//rTCONSEL=0;//无效LPC3480
rTCONSEL&=(~7);


rTPAL=0x0;
rTCONSEL&=~((1<<4)|1);

rGPGUP=rGPGUP&(~(1<<4))|(1<<4);//GPG4上拉电阻无效
rGPGCON=rGPGCON&(~(3<<8))|(3<<8);//设置GPG4为LCD_PWREN
rGPGDAT=rGPGDAT|(1<<4);//GPG4置1

rLCDCON5=rLCDCON5&(~(1<<3))|(1<<3);//有效PWREN信号
rLCDCON5=rLCDCON5&(~(1<<5))|(0<<5);//PWREN信号极性不翻转

rLCDCON1|=1;//LCD开启
}
//LCD显示函数//////////////////////////////////////////////////


void__irqADCTs(void)
{
rADCTSC=(1<<3)|(1<<2);//上拉电阻无效,自动连续XY坐标转换模式开启
rADCDLY=40000;//延时

rADCCON|=0x1;//开始A/D转换

while(rADCCON&0x1);//检查A/D转换是否开始

while(!(rADCCON&0x8000));//等待A/D转换的结束

while(!(rSRCPND&((unsignedint)0x1<<31)));//判断A/D中断的悬挂位

xdata=(rADCDAT0&0x3ff);//读取X轴坐标
ydata=(rADCDAT1&0x3ff);//读取Y轴坐标

flagTS=1;//置标志

rSUBSRCPND|=0x1<<9;
rSRCPND=0x1<<31;
rINTPND=0x1<<31;
rINTSUBMSK=~(0x1<<9);
rINTMSK=~(0x1<<31);//清A/D中断,开启A/D中断屏蔽

rADCTSC=0xd3;//再次设置等待中断模式,这一次是判断触笔的抬起

rADCTSC=rADCTSC|(1<<8);//设置触笔抬起中断

while(1)//等待触笔的抬起
{
if(rSUBSRCPND&(0x1<<9))//检查A/D触摸屏中断悬挂
{
break;//如果触笔抬起,则跳出该循环
}
}

rADCDLY=50000;
rSUBSRCPND|=0x1<<9;//写1清除标志
rINTSUBMSK=~(0x1<<9);//清0中断使能,ADC的子中断
rSRCPND=0x1<<31;//写1清除标志
rINTPND=0x1<<31;//再次清A/D中断,开启A/D中断屏蔽
rADCTSC=0xd3;//设置等待光标按下中断模式,为下一次触笔的落下做准备
//011010011--//XP_PU,XP_Dis,XM_Dis,YP_Dis,YM_En.
}

constunsignedcharone[]={0x00,0x00,0x00,0x10,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x7C,0x00,0x00};
constunsignedchartwo[]={0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x04,0x04,0x08,0x10,0x20,0x42,0x7E,0x00,0x00};
constunsignedcharthree[]=
{0x00,0x00,0x00,0x3C,0x42,0x42,0x04,0x18,0x04,0x02,0x02,0x42,0x44,0x38,0x00,0x00};
//用PCtoLCD2002字符生成软件

//触摸屏校正
voidTSCal(void)
{
inti=0;
intxt[3],yt[3];
Brush_Background(0xFFFFFF);
drawCross(24,32,0xFF0000);
Draw_ASCII(28,36,0xFF0000,one);//----
drawCross(216,160,0xFF0000);
Draw_ASCII(220,164,0xFF0000,two);//----
drawCross(120,288,0xFF0000);
Draw_ASCII(124,292,0xFF0000,three);//----

//依次读取三个采样点的坐标值
for(i=0;i<3;i++)
{
while(flagTS==0)
delay(500);
xt[i]=xdata;
yt[i]=ydata;
flagTS=0;
}

//计算参数
K=(xt[0]-xt[2])*(yt[1]-yt[2])-(xt[1]-xt[2])*(yt[0]-yt[2]);
D=(32-288)*(yt[1]-yt[2])-(160-288)*(yt[0]-yt[2]);
E=(xt[0]-xt[2])*(160-288)-(32-288)*(xt[1]-xt[2]);
F=yt[0]*(xt[2]*160-xt[1]*288)+yt[1]*(xt[0]*288-xt[2]*32)+yt[2]*(xt[1]*32-xt[0]*160);
A=(24-120)*(yt[1]-yt[2])-(216-120)*(yt[0]-yt[2]);
B=(xt[0]-xt[2])*(216-120)-(24-120)*(xt[1]-xt[2]);
C=yt[0]*(xt[2]*216-xt[1]*120)+yt[1]*(xt[0]*120-xt[2]*24)+yt[2]*(xt[1]*24-xt[0]*216);
}

intMain(intargc,char**argv)
{
inti;
unsignedcharkey;
unsignedintmpll_val=0;
intdata;

intxLcd,yLcd;

mpll_val=(92<<12)|(1<<4)|(1);

//initFCLK=400M,sochangeMPLLfirst
ChangeMPllValue((mpll_val>>12)&0xff,(mpll_val>>4)&0x3f,mpll_val&3);
ChangeClockDivider(key,12);

rINTMOD=0x0;//All=IRQmode
rINTMSK=BIT_ALLMSK;//Allinterruptismasked.

MMU_Init();

init_port_lcd();

//*********************
rADCDLY=50000;//设置延时
rADCCON=(1<<14)+(9<<6);//设置A/D预分频
rADCTSC=0xd3;//设置cm屏为等待中断模式。
pISR_ADC=(int)ADCTs;
rINTMSK=~(0x1<<31);//开启中断
rINTSUBMSK=~(BIT_SUB_TC);

flagTS=0;
//*********************

TSCal();//校正
delay(200000);

Brush_Background(0xFFFFFF);

while(1)
{
if(flagTS)
{
flagTS=0;
xLcd=(A*xdata+B*ydata+C)/K;//计算Y轴坐标
yLcd=(D*xdata+E*ydata+F)/K;//计算X轴坐标
drawsquare(xLcd,yLcd,0xFF0000);//绘制正方形
}
delay(1000000);
}
return0;
}

//-------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------
voidMMU_Init(void)//配置MMU
{
inti,j;
MMU_DisableDCache();
MMU_DisableICache();

for(i=0;i<64;i++)
for(j=0;j<8;j++)
MMU_CleanInvalidateDCacheIndex((i<<26)|(j<<5));


MMU_InvalidateICache();
MMU_DisableMMU();
MMU_InvalidateTLB();

MMU_SetMTT(0x00000000,0x03f00000,0x30000000,RW_CB);//bank0__ENTRY的地址就是0x30000000
MMU_SetMTT(0x04000000,0x07f00000,0,RW_NCNB);//bank0
MMU_SetMTT(0x08000000,0x0ff00000,0x08000000,RW_CNB);//bank1
MMU_SetMTT(0x10000000,0x17f00000,0x10000000,RW_NCNB);//bank2
MMU_SetMTT(0x18000000,0x1ff00000,0x18000000,RW_NCNB);//bank3
//MMU_SetMTT(0x20000000,0x27f00000,0x20000000,RW_CB);//bank4
MMU_SetMTT(0x20000000,0x27f00000,0x20000000,RW_CNB);//bank4forSTRATAFlash
MMU_SetMTT(0x28000000,0x2ff00000,0x28000000,RW_NCNB);//bank5
//30f00000->30100000,31000000->30200000
MMU_SetMTT(0x30000000,0x30100000,0x30000000,RW_CB);//bank6-1
MMU_SetMTT(0x30200000,0x33e00000,0x30200000,RW_NCNB);//bank6-2
//
MMU_SetMTT(0x33f00000,0x33f00000,0x33f00000,RW_CB);//bank6-3
MMU_SetMTT(0x38000000,0x3ff00000,0x38000000,RW_NCNB);//bank7

MMU_SetMTT(0x40000000,0x47f00000,0x40000000,RW_NCNB);//SFR
MMU_SetMTT(0x48000000,0x5af00000,0x48000000,RW_NCNB);//SFR
MMU_SetMTT(0x5b000000,0x5b000000,0x5b000000,RW_NCNB);//SFR
MMU_SetMTT(0x5b100000,0xfff00000,0x5b100000,RW_FAULT);//notused


MMU_SetTTBase(_MMUTT_STARTADDRESS);//写转换表基地址到C2
MMU_SetDomain(0x55555550|DOMAIN1_ATTR|DOMAIN0_ATTR);//写域访问控制位到C3
//DOMAIN1:no_access,DOMAIN0,2~15=client(APischecked)
MMU_SetProcessId(0x0);
MMU_EnableAlignFault();

MMU_EnableMMU();//使能MMU
MMU_EnableICache();//使能ICache
MMU_EnableDCache();//DCache必须要打开,当MMU打开时.DCacheshouldbeturnedonafterMMUisturnedon.

}

//vaddrStart:虚拟起始地址
//vaddrEnd:虚拟结束地址
//paddrStart:物理起始地址
//attr:访问属性
voidMMU_SetMTT(intvaddrStart,intvaddrEnd,intpaddrStart,intattr)
{
volatileunsignedint*pTT;//定义了页表的指针
volatileinti,nSec;
pTT=(unsignedint*)_MMUTT_STARTADDRESS+(vaddrStart>>20);//由于内存块是1M的,写页表的基地址
nSec=(vaddrEnd>>20)-(vaddrStart>>20);//计数有多少个段(每个段为1M)
for(i=0;i<=nSec;i++)
*pTT++=attr|(((paddrStart>>20)+i)<<20);
//页表存储访问信息和存储块的基地址
//(((paddrStart>>20)+i)<<20):对应的物理内存页的地址
//attr:访问权限和缓冲属性
}

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

近期,运动与控制技术的先行者——派克汉尼汾公司宣布推出一款功能强大的测量设备Service Master COMPACT,为行走机械和工业液压应用提供实时监测和诊断服务。产品采用坚固的IP65防护级外壳及耐油性橡胶保护层...

关键字: 触摸屏 触感键盘 传感器

LCD(液晶显示器)和LED(发光二极管)这两个术语通常用于描述显示技术中的不同方面。实际上,大多数液晶显示器都使用LED作为背光光源。因此,这两个术语经常一起使用,而不是相互替代。

关键字: lcd显示器 拖尾 LCD

LED(Light Emitting Diode)与LCD(Liquid Crystal Display)是当今显示技术领域的两大重要分支,各自凭借独特的优势在消费电子、广告传媒、工业控制、家用电器等多个领域占据着主导地...

关键字: LED LCD

液晶显示器(Liquid Crystal Display,简称LCD)作为一种广泛应用于电视、电脑显示器、手机以及各类电子产品的显示技术,其发展历程与科技创新紧密相连。LCD技术以其独特的构造和工作原理,在过去的几十年里...

关键字: LCD 液晶显示

LCD屏幕的优点包括较长的寿命、较便宜的价格、较宽的视角和较好的亮度均匀性,适合对亮度和均匀性有较高要求,注重电池寿命的用户。

关键字: LCD OLED 屏幕

电容式触摸屏又称电容触摸屏,是一种生长在电子行业中的新型非接触式触摸技术,广泛应用在人机交互界面,实现与人机之间信息传递,它带动了科技发展,改变着日常生活。

关键字: 电容式 触摸屏 交互界面

LCD背光源将是下述内容的主要介绍对象,通过这篇文章,小编希望大家可以对它的相关情况以及信息有所认识和了解,详细内容如下。

关键字: LCD 背光源

Holtek A/D Flash LCD MCU新增系列成员HT67F2362A与HT67F2372A,分别为HT67F2362及HT67F2372的延伸产品,特点为新增C-type LCD驱动使得低压时可维持显示效果,...

关键字: MCU LCD LED 驱动电路

LCD与LED是两种采用不同工作原理的显示技术,LCD是由液态晶体组成的显示屏,而LED则是由发光二极管组成的显示屏。

关键字: LED 手机屏 LCD
关闭
关闭