三十九.触摸屏

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的方向是相反的。

10.6410代码
/****************************
@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;	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值