触摸屏驱动程序设计
触摸屏工作原理:
四线电阻屏结构上如图,是在玻璃或丙稀酸基板上覆盖两层均匀导电的ITO层,分别作为x电极和y电极,他们之间由均匀排列的透明格点分来绝缘。X电极和y电极的正负端由导电线(黑色粗体线)从两端引出,引出x-,x+,y-,y+.
当接触触摸屏表面并施加压力时,上层的ITO导电层和下层的ITO导电层发生接触,形成上面右图的等效电路。
1.y坐标计算:
在y+加驱动电压V-drive,y-接地。X+作为引出端测量接触点的电压,由于ITO层均匀导电,触电电压与V-drive电压之比等于Y坐标与屏高度之比。
2.x坐标计算:
在x+加驱动电压V-drive电压,x-接地。Y+作为引出端测量接触点的电压,由于ITO层均匀导电,触点电压与V-drive电压比等于x坐标与屏宽度之比。
y=Vx/V-driv *heightx=Vy/ V-driv * width
触摸屏工作流程(理解好这几步流程,代码至少能看懂30%)
1.设置触摸屏接口为等待中断模式,等待触摸屏被按下。
2.如果中断(INT_TC)发生,选择X,Y坐标转换模式(x/y坐标分别转换模式,x/y坐标自动转换),启动AD转换。
3.当AD转换完后,通过中断(INT_ADC),获取x/y坐标,
ADCDAT0 bit[9:0]-x坐标;
ADCDAT1 bit[9:0]-y坐标;
4.设置触摸屏接口为等待中断模式,等待触摸笔离开触摸屏。
5.返回步骤1,等待下次触摸笔被按下。
#define GLOBAL_CLK 1
#include <stdlib.h>
#include <string.h>
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "2440lib.h"
#include "2440slib.h"
#include "mmu.h"
#include "profile.h"
#include "memtest.h"
#define ADC_FREQ 2500000
//#define ADC_FREQ 1250000
int count = 0;
volatile U32 preScaler;
int xdata,ydata;
void Test_Touchpanel(void);
static void __irq AdcTsAuto(void);
static void cal_cpu_bus_clk(void);
void Set_Clk(void);
/*************************************************
Function name: delay
Parameter : times
Description : 延时函数
Return : void
Argument : void
Autor & date : Daniel
**************************************************/
void delay(int times)
{
int i,j;
for(i=0;i<times;i++)
for(j=0;j<400;j++);
}
/*************************************************
Function name: Main
Parameter : void
Description : 主功能函数
Return : void
Argument : void
Autor & date : Daniel
**************************************************/
int Main(void)
{
int Scom=0;
MMU_Init();
Set_Clk();
Uart_Init(0,115200);
Uart_Select(Scom);
// Uart_Printf("\nHello World!\n");
Test_Touchpanel();
while(1);
return 0;
}
/*************************************************
Function name: Test_Touchpanel
Parameter : void
Description : 触摸屏初始化
Return : void
Argument : void
Autor & date : Daniel
**************************************************/
void Test_Touchpanel(void)
{
rADCDLY=50000; //Normal conversion mode delay about (1/3.6864M)*50000=13.56ms
/*设置AD转频率*/
preScaler = ADC_FREQ;
Uart_Printf("ADC conv,freq. = %dHz\n",preScaler);
preScaler = 50000000/ADC_FREQ - 1; //PCLK=50M
rADCCON = (1<<14)|(preScaler<<6); //ADCPRS En,PRSCVL
// rADCCON=(1<<14)+(preScaler<<6); //ADCPRS En, ADCPRS Value
Uart_Printf("ADC touch screen test\n");
/*设置触摸屏为等待中断模式,等待触摸笔被按下*/
rADCTSC=0xd3; //Wfait,XP_PU,XP_Dis,XM_Dis,YP_Dis,YM_En
/*clear irq*/
//ClearPending(BIT_ADC);
rSRCPND = 0x80000000;
rINTPND = 0x80000000;
ClearSubPending(BIT_SUB_TC);
pISR_ADC = (U32)AdcTsAuto;
/*enable INT_TC irq*/
//EnableIrq(BIT_ADC);
rINTMSK = 0x7fffffff;//允许中断
EnableSubIrq(BIT_SUB_TC);
}
/*************************************************
Function name: AdcTsAuto
Parameter : void
Description : 中断服务程序
Return : void
Argument : void
Autor & date : Daniel
**************************************************/
static void __irq AdcTsAuto(void)
{
U32 saveAdcdly;
/****************stylus down************************/
/*检测子中断源,判断是否是INT_TC中断,且触摸笔按下*/
if(rSUBSRCPND & (BIT_SUB_TC))//产生中断
{
if( !(rADCDAT0&0x8000))//按下产生的中断
Uart_Printf("\nStylus down\n");
else //抬起产生的中断
Uart_Printf("\nStylus up\n");
}
/*pull-up disable,自动连续X,Y坐标转换*/
rADCTSC = (1<<3)|(1<<2);
saveAdcdly=rADCDLY;
rADCDLY=40000; //延时 //Normal conversion mode delay about (1/50M)*40000=0.8ms
/*开始AD转换*/
rADCCON|=0x1; //start ADC
while(rADCCON & 0x1); //check if Enable_start is low
while(!(rADCCON & 0x8000));//转换是否结束 //check if EC(End of Conversion) flag is high, This line is necessary~!!
while(!(rSRCPND & 0x80000000)); //check if ADC is finished with interrupt bit
/*获取X,Y坐标*/
xdata=(rADCDAT0&0x3ff);
ydata=(rADCDAT1&0x3ff);
ClearSubPending(BIT_SUB_TC);
//ClearPending(BIT_ADC);
rSRCPND = 0x80000000;
rINTPND = 0x80000000;
EnableSubIrq(BIT_SUB_TC);
//EnableIrq(BIT_ADC);
rINTMSK = 0x7fffffff;
/****************stylus down************************/
/****************stylus up**************************/
/*设置触摸屏为等待中断模式,等待触摸笔抬起*/
rADCTSC =0xd3; //Waiting for interrupt
rADCTSC=rADCTSC|(1<<8); // Detect stylus up interrupt signal.
while(1) //to check Pen-up state
{
if(rSUBSRCPND & (BIT_SUB_TC)) //check if ADC is finished with interrupt bit
{
Uart_Printf("Stylus Up Interrupt~!\n");
break; //if Stylus is up(1) state
}
}
/****************stylus up**************************/
Uart_Printf("count=%03d XP=%04d, YP=%04d\n", count++, xdata, ydata);
rADCDLY=saveAdcdly;
/*设置触摸屏为等待中断模式,等待下次触摸笔按下*/
rADCTSC =0xd3; //Waiting for interrupt
ClearSubPending(BIT_SUB_TC);
//ClearPending(BIT_ADC);
rSRCPND = 0x80000000;
rINTPND = 0x80000000;
EnableSubIrq(BIT_SUB_TC);
//EnableIrq(BIT_ADC);
rINTMSK = 0x7fffffff;
}
/*************************************************
Function name: Set_Clk()
Parameter : void
Description : 设置CPU的时钟频率
Return : void
Argument : void
Autor & date : Daniel
**************************************************/
void Set_Clk(void)
{
int i;
U8 key;
U32 mpll_val = 0 ;
i = 2 ; //don't use 100M!
//boot_params.cpu_clk.val = 3;
switch ( i ) {
case 0: //200
key = 12;
mpll_val = (92<<12)|(4<<4)|(1);
break;
case 1: //300
key = 13;
mpll_val = (67<<12)|(1<<4)|(1);
break;
case 2: //400
key = 14;
mpll_val = (92<<12)|(1<<4)|(1);
break;
case 3: //440!!!
key = 14;
mpll_val = (102<<12)|(1<<4)|(1);
break;
default:
key = 14;
mpll_val = (92<<12)|(1<<4)|(1);
break;
}
//init FCLK=400M, so change MPLL first
ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3); //set the register--rMPLLCON
ChangeClockDivider(key, 12); //the result of rCLKDIVN [0:1:0:1] 3-0 bit
cal_cpu_bus_clk(); //HCLK=100M PCLK=50M
}
/*************************************************
Function name: cal_cpu_bus_clk
Parameter : void
Description : 设置PCLK\HCLK\FCLK的频率
Return : void
Argument : void
Autor & date : Daniel
**************************************************/
static void cal_cpu_bus_clk(void)
{
static U32 cpu_freq;
static U32 UPLL;
U32 val;
U8 m, p, s;
val = rMPLLCON;
m = (val>>12)&0xff;
p = (val>>4)&0x3f;
s = val&3;
//(m+8)*FIN*2 不要超出32位数!
FCLK = ((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100; //FCLK=400M FIN=12000000
val = rCLKDIVN;
m = (val>>1)&3;
p = val&1;
val = rCAMDIVN;
s = val>>8;
switch (m) {
case 0:
HCLK = FCLK;
break;
case 1:
HCLK = FCLK>>1;
break;
case 2:
if(s&2)
HCLK = FCLK>>3;
else
HCLK = FCLK>>2;
break;
case 3:
if(s&1)
HCLK = FCLK/6;
else
HCLK = FCLK/3;
break;
}
if(p)
PCLK = HCLK>>1;
else
PCLK = HCLK;
if(s&0x10)
cpu_freq = HCLK;
else
cpu_freq = FCLK;
val = rUPLLCON;
m = (val>>12)&0xff;
p = (val>>4)&0x3f;
s = val&3;
UPLL = ((m+8)*FIN)/((p+2)*(1<<s));
UCLK = (rCLKDIVN&8)?(UPLL>>1):UPLL;
}
分享到:
相关推荐
mini2440 ADC数模转换裸机程序,已在板上通过运行调试
arm9裸机开发之ADC实验 开发板采用的TQ2440,基于s3c2440的裸机开发程序,本实验是ADC实验。 通过adc的采集后,用UART串口输出采集的信息.
mini2440ADC转换,裸机源代码!
包含了mini2440开发板的几乎所有裸机程序。按键,LED,LCD,ADC,触摸屏,串口等等
mini2440 ADC 嵌入式开发-驱动开发
mini2440全套裸机程序(MDK),包括的外部中断 LCD 触摸屏 timer ADC 外部中断,等驱动程序。 可配套国嵌的mini2440 视频教程.平台是MDK的。
mini2440 ADC中断方式采样,含详细说明
基于mini2440裸机的ADC操作源代码。有轮询的和中断的。
mini2440的ADC驱动和触摸屏驱动, 包括修改后mini2440的BSP(linux-2.6.39.4). ADC驱动注册为misc device, 挂载再platform bus 触摸屏驱动注册为input device, 挂载再platform bus上, 并根据官方自带的BSP进行...
ADC单次转换,规则通道的外部触发为定时器3的TRGO,定时器3TRGO事件来源于更新事件,每500ms更新一次,即ADC每500ms转换一次 ADC1开启3个规则通道,转换序列为:通道0(PA0),通道1(PA1),通道2(PA2) 在规则...
mini2440的ADC驱动代码, 隶属于platform bus和miscdevice, 与网上能检索到的基于FriendlyArm的代码不太相同, 有兴趣的朋友可以下载了相互学习。 测试信息: #/home/readadc adc value: 417 Do you want to read ...
mini2440开发板的6个用C#和VB实现的实例原代码。
mini2440裸机各个模块编程模板,ADC IIC NAND RTC UART LCD 触摸屏等
mini2440-adc-test.rar
mini2440开发板x35 240*320 TFT LCD显示屏。 先进行触摸屏校准,然后可以描绘轨迹。 存在问题是轨迹点不连续。
mini2440实现数模ADC转换程序源码,以测试过直接可以用。编译器使用的是arm-linux-gcc 4.3.2。
在规则通道每个通道转换完成之后,DMA负责将转换的数据从ADC_DR寄存器传输到用户指定的目的地址 开启3个注入通道,转换序列为:通道0(PA0),通道1(PA1),通道2(PA2) 注入通道触发选择为自动注入(当规则通道...
MDK下编写的mini2440的ADC简单裸机实验,详细说明见: http://blog.csdn.net/mybelief321/article/details/8979795
包括:(ARM9的全部功能部件)外部中断、定时器、看门狗、DMA、PWM控制、UART通信、红外模块控制、实时时钟控制、IIC总线应用、Nor flash、Nand flash、TFT LCD、触摸屏、ADC、IIS音频总线、USB、SD卡、TFTP以太网...
eetop.cn-SARADC的设计-李福乐-2019