1.触摸屏优势:作为输入设备,简单方便,反应速度快,节省空间。
2.分类:
(1)电阻屏
(2)电容屏
3.电阻屏原理
(1)结构:
(2)工作流程:
a.手指触摸屏幕,使得两个相互绝缘的导电层接触
b.顶层触摸点电压会传递到底层,底层电压发生变化
c.CPU对底层电压AD转换
d.得到转换后的值与顶层电压的最大值相比,乘以屏幕总的长度,即可得到相对于电压为0的点的距离。
4.电容屏原理:
(1)结构:
(2)优势:反应更灵敏, 支持多点触控。
(3)工作流程:
a.手指触控屏幕,电流流经手指(表面的电压很小,但是必须有)
b.这个电流从屏幕的四个角流出,故产生四个方向的电流,且与他们到电极的距离成比例。
c.CPU对四个电流进行计算,从而得到触摸点的位置。
5.电阻屏驱动设计:
初始化:
(1)ADC时钟初始化:
ADCCLK = PCLK/(PRESCAL + 1),计算的时候都已MHZ为计算单位。一般不高于2MHz。(ADCCON)
(2)设置中断屏蔽位
INTMSK打开INT_ADC中断,INTSUBMSK使能ADC_TC中断,屏蔽ADC转换完成中断。
(3)进入等待按下中断模式
ADCTSC控制进入等待中断模式,而且是等待进入按下模式。
#define ADCCON (*(volatile unsigned *)0x58000000) //ADC control
#define ADCTSC (*(volatile unsigned *)0x58000004) //ADC touch screen control
#define ADCDLY (*(volatile unsigned *)0x58000008) //ADC start or Interval Delay
#define ADCDAT0 (*(volatile unsigned *)0x5800000c) //ADC conversion data 0
#define ADCDAT1 (*(volatile unsigned *)0x58000010) //ADC conversion data 1
/*interrupt registes*/
#define SRCPND (*(volatile unsigned long *)0x4A000000)
#define INTMSK (*(volatile unsigned long *)0x4A000008)
#define INTOFFSET (*(volatile unsigned long *)0x4A000014)
#define SUBSRCPND (*(volatile unsigned long *)0x4A000018)
#define INTSUBMSK (*(volatile unsigned long *)0x4A00001c)
#define INTPND (*(volatile unsigned long *)0x4A000010)
//#define X_TOUCH (*(volatile unsigned long *)0x33000000)
//#define Y_TOUCH (*(volatile unsigned long *)0x33000004)
int x_touch,y_touch;
void ts_init()
{
ADCCON = (1 << 14) | (49 << 6);
ADCDLY = 50000;
INTMSK &= ~(1 << 31);
INTSUBMSK &= ~(1 <<9);
ADCTSC = 0xd3;
}
触摸处理函数
(1)启动XY坐标自动转换
ADCTSC
ADCCON
(2)等待转换完成
(3)获取坐标
ADCDAt0
ADCDAT1
(4)清除按下中断
SRCPND
INTPND
SUBSRCPND(只用到INT_TC)
(5)等待弹起中断(在等待进入按下模式的前面,即第8位置1即可)
(6)清除弹起中断
和清除按下中断一样,他们使用的中断源一样
(7)再次进入等待按下中断模式
和初始化的最后一步骤一样
void tc_handle()
{
ADCTSC |= (1 << 2);
ADCCON |= (1 << 0);
while(!(ADCCON & (1 << 15)));
x_touch = (int)(ADCDAT0 & 0x3ff);
y_touch = (int)(ADCDAT1 & 0x3ff);
SUBSRCPND |= (1 <<9);
SRCPND |= (1 << 31);
INTPND |= (1 << 31);
ADCTSC = 0xd3;
ADCTSC |= (1 << 8);
while(!(SUBSRCPND & (1 << 9)));
SUBSRCPND |= (1 <<9);
SRCPND |= (1 << 31);
INTPND |= (1 << 31);
printf("x is : %d y is : %d\n\r",x_touch,y_touch);
ADCTSC = 0xd3;
}
6.大家注意自己在复制三星数据手册的时候,他的地址有时候会少一个0,今天就是被他浪费了时间,一直找不到错误,仔细一看原来是ADC相关寄存器地址只有7位,还以为自己连地址都不会定义了。
7.还有一个问题,当在lcd上输出图片以后,再去采集触摸位置,这时候输出不正常,得不到合理的位置的值。起初以为我声明用来存放x和y坐标的变量被之前我们存放到内存的图片数据覆盖了,所以得不到合理的值,直接取不出来。但后来我指定了XY坐标变量的在内存的地址,还是一样,这里表示有疑问????
8.老师的代码是直接屏蔽了按键中断,其实可以同时打开,如果后面中断源多了,还要设置中断优先级。
9.屏幕校准应该实现,还有我读出来的X和Y的值与现实中我们认为的x和y的方向是相反的。
/****************************
@File:touch_screen.c
@
@Tiny6410裸机下学期代码
@触摸屏配置文件
@Author:小君君
@****************************/
int x = 0;
int y = 0;
#include "common.h"
void tc_handle()
{
//int x = 0;
//int y = 0;
printf("x is: %d\ty is : %d\n",x,y);
/*0.现场保护*/
__asm__(
"sub lr, lr, #4\n"
"stmfd sp!, {r0-r12, lr}\n"
:
:
);
/*1.启动XY坐标自动转换*/
(vi ADCTSC) |= (1 << 2);
(vi ADCCON) |= (1 << 0);
/*2.等待转换完成*/
while(((vi ADCCON) & (1 << 15)) == 0);
/*3.获取坐标*/
x = ((vi ADCDAT0) & (0x3FF));
//y = ((vi ADCDAT1) & (0xFFF));
/*4.清除按下中断*/
(vi ADCCLRINT) = 0;
(vi ADCCLRINTPNDNUP) = 0;
(vi ADCUPDN) &= ~(3 << 0);
/*5.进去等待弹起中断模式*/
(vi ADCTSC) = 0xd3;
(vi ADCTSC) |= (1 << 8);
while(((vi ADCTSC) & (1 << 1)) == 0);
/*6清除弹起中断*/
(vi ADCCLRINT) |= 0x1;
(vi ADCCLRINTPNDNUP) |= 0x1;
(vi ADCUPDN) &= ~(3 << 0);
/*7.再次进入等待按下中断*/
(vi ADCTSC) = 0xd3;
printf("x is: %d\ty is : %d\n",x,y);
(vi VIC0ADDRESS) = 0;
(vi VIC1ADDRESS) = 0;
/*8.恢复现场*/
__asm__(
"ldmfd sp!, {r0-r12, pc}^ \n"
:
:
);
return ;
}
void ts_init()
{
/*1.选择AD位数10bit还是12bit(10bit)
使能时钟预分频
设置分频系数(PCLK = 66.5MHz,所以设置为65)
选择normal模式
禁止READ_ START*/
(vi ADCCON) &= ~((1 << 2) | (1 << 1));
(vi ADCCON) |= ((1 << 14) | (65 << 6) | (0 << 3));
/*2.设置延时时间*/
(vi ADCDLY) = 66000;
/*3.设置中断屏蔽位
使能INT_ADC
INT_PENDNUP*/
(vi VIC1INTENABLE) |= (0x1 << 30);
(vi ADCCLRINT) = 0;
(vi ADCCLRINTPNDNUP) = 0;
(vi VIC1SELECT) &= ~(1 << 30);
/*4.进入等待中断模式,而且是等待进入按下模式*/
(vi ADCTSC) = 0xd3;
/*5.注册弹起按下的中断处理函数*/
(vi IPDOWNINT_VECTADDR) = (int)tc_handle;
//(vi ADCINT_VECTADDR) = (int)tc_handle;
/*4.开启向量中断模式*/
__asm__(
"mrc p15,0,r0,c1,c0,0\n"
"orr r0,r0,#(1<<24)\n"
"mcr p15,0,r0,c1,c0,0\n"
"mrs r0,cpsr\n"
"bic r0, r0, #0x80\n"
"msr cpsr, r0\n"
:
:
);
printf("x is: %d\ty is : %d\n",1,1);
return ;
}
int read_adc(int ch)
{
(vi ADCCON) &= ~((1 << 2) | (1 << 1));
(vi ADCCON) |= ((1 << 14) | (65 << 6) | (ch << 3)| (1 << 16));
(vi ADCCON) |= (1 << 0);
/*2.等待转换完成*/
while(((vi ADCCON) & (1 << 15)) == 0);
/*3.获取坐标*/
x = ((vi ADCDAT0) & (0xFFF));
printf("x is: %d\r\n",x);
}
/****************************
@File:main.c
@
@Tiny6410裸机下学期代码
@触摸屏测试文件
@Author:小君君
@****************************/
#include "common.h"
int main(void)
{
int num = 1000;
//mmu_init();//MMU初始化,这里不使用MMU
led_init();//LED的GPIO初始化
button_init();//按键初始化
irq_init();//中断初始化
led_on();//点亮4颗LED
uart_init();//串口初始化
putchar('a');
putchar('\r');
putchar('\n');
putchar('b');
putchar('\r');
putchar('\n');
dma_init();//DMA初始化
dma_start();//启动DMA发送数据到串口
uart_init();//串口再次初始化,使得串口恢复中断或者轮询模式
lcd_init();
lcd_clear_screen(0xFFFFFF);
ts_init();//触摸屏初始化
while(1){
printf("=================================================\n\r");
printf("===================JUN-BOOT======================\n\r");
printf("0.Send the ARP to get yhe host's MAC address\n\r");
printf("1.Download the linux kernel from tftp\n\r");
printf("2.Boot linux OS from SDRAM\n\r");
printf("3.Junjun is a houmorous\n\r");
printf("=================================================\n\r");
printf("===================LCD_TEST======================\n\r");
printf("4.清屏\n\r");
printf("5.画横线\n\r");
printf("6.画竖线\n\r");
printf("7.画十字架\n\r");
printf("8.画同心圆\n\r");
printf("9.AD转换\n\r");
printf(" \n\r");
printf("请输入0-8任意一个数字:\n\r");
scanf("%d",&num);
switch(num){
case 0:
printf("请支持成都国嵌\n\r");
break;
case 1:
printf("国嵌学院=====打造你的嵌入式人生\n\r");
break;
case 2:
printf("学ARM,学Linux,学C++,学安卓,学嵌入式,就到成都国嵌学院\n\r");
break;
case 3:
printf("只要你肯努力,你的明天就会等你!!\n\r");
break;
case 4:
lcd_clear_screen(0x000000);
break;
case 5:
lcd_clear_screen(0x000000);
lcd_draw_hline(HEIGHT/2, 100, WIDTHEIGHT-100, 0xff0000);
break;
case 6:
lcd_clear_screen(0x000000);
lcd_draw_vline(WIDTHEIGHT/2, 50, HEIGHT-50, 0xff0000);
break;
case 7:
lcd_clear_screen(0x000000);
lcd_draw_cross(HEIGHT/2, WIDTHEIGHT/2, 20, 0x777777);
break;
case 8:
lcd_clear_screen(0x000000);
lcd_draw_circle();
break;
case 9:
read_adc(0);
break;
default:
printf("只要你肯努力,你的明天就会等你!!\n\r");
break;
}
}
return 0;
}