nbhkdz.com冰点文库

5.AD转换以及触摸屏实验

时间:2012-03-31


ARM实验 AD转换以及触摸屏实验

? AD转换:

? 又称为模数转换,是将模拟信号转换为计算机能 够处理的数字信号。
? s3c2440集成了8通道10位CMOS A/D转换器。

ADCCON
? 第15位:用于标识A/D转换是否结束。 ? 第14位:用于使能是否进行预分频。

? 13--6:则存储的是预分频数值,因为A/D转换的速度不能 太快,所以要通过预分频处理才可以得到正确的A/D转换 速度,如我们想要得到A/D转换频率为1MHz,则预分频 的值应为49。
? 5--3:表示的是A/D转换的通道选择。 ? 第2位:可以实现A/D转换的待机模式。

? 第1位:用于是否通过读取操作来使能A/D转换的开始。 第0位:则是在第1位被清零的情况下用于开启A/D转换。

? 1. A/D 转换的数据可以通过中断或查询方式访问。 中断方式的总体转换时间为从A/D 转换器开始到 转换数据的读取,可能由于中断服务程序的返回 时间和数据访问时间而延迟。查询方式是通过检 查转换结束标志位的ADCCON[15],可以确 定读取ADCDAT 寄存器的时间。 ? 2. 还提供了其它启动A/D 转换的方法。在转换的 读启动模式ADCCON[1]设置为1 后,A/D 转换启 动同时读取数据。

? 寄存器ADCDAT0的低10位用于存储A/D转换后 的数据。寄存器ADCCON的第15位用于标识A/D 转换是否结束。

? int readADC(void) ? { rADCCON = (1<<14)|(49<<6); //设置预分频器和

rADCCON &= ~( (7<<3) | ( 1<<2) );
? rADCCON|=0x1;

// A/D通道0, 正常模式
//启动A/D转换

? ? ? ? while(rADCCON & 0x1) ; while(!(rADCCON & 0x8000)) ; //等待A/D转换的结束 //读取A/D转换的数据 //确认A/D转换是否开始

?
? ? return ( (int)rADCDAT0 & 0x3ff );

? }

? 练习:

? 用中断的方式,来进行AD转换,旋转滑动变阻器, 在超级终端上显示数字。

触摸屏接口

MINI2440原理图

触摸屏接口模式
? 触摸屏有四种接口模式: ? (1)普通转换模式 ? 与通用AD转换的使用方式很相似。通过设置ADCCON来初始化,并 以一个读和写ADCDAT0的操作完成。 ? (2)X/Y位置分别转换模式 ? 又可以分成两种模式:X位置转换模式和Y位置转换模式。这两种模 式下,触摸屏分别把X、Y位置转换数据写入到ADCDAT0和 ADCDAT1中之后,向中断控制器发起中断请求。 ? (3)自动(顺序)X/Y位置转换模式 ? 触摸屏控制器依次转换X和Y位置,把转换结果分别写入到ADCDAT0 和ADCDAT1中,然后向中断控制器发起中断请求。 ? (4)等待中断模式 ? 设置ADCTSC为0xD3,当触摸笔按下时,控制器发起中断请求。

中断类型

? 最终向处理器发起的中断请求类型是

? 总中断INT_ADC,它分为两种子中断类型,
? 1. INT_SUB_ADC表示AD采样完成(触摸屏X、 Y位置采样完成); ? 2. INT_SUB_TC表示触摸屏中断,即笔在屏幕上 按下或者离开屏幕。

触摸屏实验 思考:

? 要实现X、Y位置判断,当然是用自动采样模式最 好;而要判断触摸笔的按下与离开,则应使用等 待中断模式。
? 问题是怎么把二者结合起来?

? 方法:

? 采用等待中断模式来判断笔的按下与离开;
? 另外设置一个采样定时器,每隔一定时间 (10ms)对X、Y位置进行采样。

? 注意问题: ? (1)只有在笔按下状态时才进行位置采样,笔不在屏幕 上时,采样是没有意义的。 ? (2)位置采样采用轮询模式实现,即等待采样完成;采 样完成后要恢复ADCTSC,重置为等待中断模式。 ? (3)在普通转换模式,分别采样模式和自动采样模式下, ADCDAT0的最高位无效,不能用它来判断笔的状态。只 有在触摸屏中断(INT_SUB_TC)中才可以用ADCDAT0来 判断触摸笔状态。 ? (4)位置采样完成后要屏蔽BIT_SUB_ADC。否则, ADC持续进行采样,会以很高的频率(因为采样频率很高) 发起INT_SUB_ADC中断请求,最终向处理器发起 INT_ADC请求,这会严重影响处理器的工作。这也是不 采用自动采样,而要用定时器定时采样的原因。

? typedef struct { volatile int btn_state; //笔的状态 volatile int x_pos;// x 坐标 volatile int y_pos;// y 坐标 volatile int int_count;// 转换的次数 volatile int start_flag;// 开始标志 }MOUSE_STATE;
? static MOUSE_STATE g_mouse_state;

初始化:
? rADCDLY = 50000;//延时寄存器 rADCCON = (1 << 14) + (49 << 6);

? rADCTSC = 0xD3;
? pISR_ADC = (unsigned int)TouchPanelIsr; rINTMSK &= (~BIT_ADC); rINTSUBMSK &= (~BIT_SUB_TC); rINTSUBMSK |= BIT_SUB_ADC;

ADCTSC= 011010011

当有笔按下或抬起
? static void __irq TC_interupt(void)// { ….. 中断清0 ? if (0 == g_mouse_state.btn_state)//如果中断前状态为抬起 ? { g_mouse_state.btn_state = 1;//标志按下状态 g_mouse_state.start_flag = 1;//标志开始状态 ? ………..打印状态和坐标 ? rADCTSC = 0x1D3;//设置为抬起中断 } else //如果中断前状态为按下 ? { g_mouse_state.btn_state = 0;//标志抬起状态 ………….打印状态 ? rADCTSC = 0xD3; //设置为按下中断 } }

定时器中断
? 定时器中断每隔10ms中断一次,进入中断处理函数,先判断笔有没 有在屏上,如果没有就直接返回,如果有就转换X,Y坐标。 ? void __irq Timer (void) { if (0 == g_mouse_state.start_flag) return; if (0 == g_mouse_state.btn_state) return;

rINTSUBMSK &= (~BIT_SUB_ADC);//允许AD中断 rADCTSC = 0x0C;//自动x,y转换模式 rADCCON = (1 << 14) + (49 << 6) ;//设置频率 rADCCON |= 0x01;//开始转换 while(rADCCON & 0x01);//AD转换开始且该位在开始后清零 while(!(rADCCON & 0x8000));//等待AD转换结束 while(!(rSUBSRCPND & (1<<10)));//等待产生中断 rINTSUBMSK |= BIT_SUB_ADC;//关AD中断

? g_mouse_state.x_pos = (rADCDAT0 & 0x3FF); g_mouse_state.y_pos = (rADCDAT1 & 0x3FF); g_mouse_state.int_count++; ? //取x,y的值,并且记数器+1 ? rSUBSRCPND = BIT_SUB_ADC;//中断清0 UART0_printf(“[x=%3d,y=%3d]\n”,g_mouse_state.x_ pos,g_mouse_state.y_pos);//打印坐标

? 练习:

? 把整个程序写完,然后在MINI2440上运行,并能 够看到效果,并指出有什么问题?

?

if (0 == (rSUBSRCPND & BIT_SUB_TC)) { rSRCPND |= BIT_ADC; rINTPND |= BIT_ADC; if (0 == g_mouse_state.btn_state) { rADCTSC = 0xD3; } else { rADCTSC = 0x1D3; } }

? 思考: 这段代码有何作用?


赞助商链接