s3c2440arm裸机编程之ADC触摸屏
ADC触摸屏
硬件原理
s3c2440有8通道的ADC,一次同时只能查询一个通道。分为A0~A7。这里的P(positive)表示的是正的意思
| A4 | TSYM | -Y |
| A5 | TSYP | +Y |
| A6 | TSXM | -X |
| A7 | TSXP | +X |
触摸屏采样有3种方式:
- 自动反转XY轴相关开关采样
- 手动切换开关采样
- 等待中断模式,这个是平时没按下的状态
电阻屏的触摸原理,其实就是在一个均匀的电阻上采样后得到电压,然后基于vcc算出相对偏移.假设电阻总长为L,采样电压为V1,那么长度偏移则是V/DVDD*L.
基于此在X方向和Y方向均有均匀电阻.所以触摸屏实际是两片透明且均匀的电阻,不按下的时候中间并不导通.转换选择导通X方向与Y方向依次测的X坐标与Y坐标.也就是先连接Xm--Xp,侧的Yp的采样,就能获得X的偏移.
板载电路
这里X轴和Y轴接反了,尅使用Tslib库旋转倒置等
等效电路
关闭模式:断开上拉电阻与4线电路,防止漏电流
空闲等待中断:这个状态是平时没有按下触摸屏,等待按下触发一个按下的中断,当左右两边电阻触发的时候,导通了XP到YM到GND,这将使Y_ADC=0,--↓__产生一个下降沿等待中断模式设置值为 ADCTSC=0xd3; // XP_PU, XP_Dis, XM_Dis,YP_Dis,YM_En同样的,当按下后,还是同样的等效电路,当松开的时候,会有一个上升延中断.配置ADCTSC的BIT8即可.
X轴采样:这里连通XP-XM,采样X_ADC
Y轴采样:这里连通YP-YM,采样Y_ADC
测量逻辑
触摸屏实际有两层,按下的时候,导通了上下两个平面,通过等效电路,可以看出通过切换开关,能够得到两种阻值。
程序设计(一)获得ADC
寄存器初始化
这里的DELAY 可以用作稳定ADC输出,也就是按下后多长时间开始采样
/* 1. 设置允许分配,分配系数为49+1,时钟为100M/50=2 2. 选择A0通道,因为后面选择自动转换,可以不考虑通道 */ ADCCON = (1<<14) | (49<<6) | (0<<3);/* 按下触摸屏, 延时一会再发出TC中断* 延时时间 = ADCDLY * 晶振周期 = ADCDLY * 1 / 12000000 = 5ms*/ ADCDLY = 60000;中断初始化
//清除挂起标志 SUBSRCPND = (1<<TC_INT_BIT) | (1<<ADC_INT_BIT); //取消次级屏蔽 INTSUBMSK &= ~((1<<ADC_INT_BIT) | (1<<TC_INT_BIT)); //注册中断函数,INTMSK &= ~(1<<irq); 取消源的mask register_irq(31, AdcTsIntHandle);void register_irq(int irq, irq_func fp) {irq_array[irq] = fp;INTMSK &= ~(1<<irq); }ADC模式(中断、测量)
ADC在工作中存在3个模式的切换,空闲的时候进入等待按下中断的模式,然后进入自动测量的模式,在测量完成后需要进入等待松开的中断模式.此时可以设置定时器等待触发下一次的自动测量
// 空闲下等待触发落下中断 void enter_wait_pen_down_mode(void) {ADCTSC = WAIT_PEN_DOWN | PULLUP_ENABLE | YM_ENABLE | YP_DISABLE | XP_DISABLE | XM_DISABLE | WAIT_INT_MODE; } //等待抬起的中断 void enter_wait_pen_up_mode(void) {ADCTSC = WAIT_PEN_UP | PULLUP_ENABLE | YM_ENABLE | YP_DISABLE | XP_DISABLE | XM_DISABLE | WAIT_INT_MODE; } //自动测量模式 void enter_auto_measure_mode(void) {ADCTSC = AUTO_PST | NO_OPR_MODE; }中断函数
备注:可以发现,松开状态下进入中断,都进入空闲等待按下中断模式
触摸屏中断
if 松开中断关闭一切,进入等待按下模式 else 按下中断进入自动测量模式打开adc定时器中断
if 松开关闭定时器进入等待按下模式 else 按下进入自动测量模式打开adcADC中断
if 松开关闭定时器进入等待按下模式 else 按下打印adc值*进入等待中断模式打开定时器//这里可以优化做平均值 if 松开关闭定时器进入等待按下模式上报数据 else 按下if 测量计数到达16次返回平均值,开启定时器else 直接进入自动测量模式优化版本
进入adc中断 进入触摸屏中断 进入定时器中断后 都先关闭定时器进入adc中断后 if按下满16次采样后打开定时器,进入等待松开中断未满16次继续打开adc采样 else 松开进入等待按下中断上报0进入触摸屏中断 if 按下 打开adc开始采样 else 松开进入等待按下中断上报0进入定时器中断且当前定时器状态为open if 按下 打开adc采样 else 松开进入等待按下中断上报0程序设计(二)获得坐标
同理,Y轴的坐标也按照相同的方式计算.程序设计中依次画出5个十字架,用户点击后计算K与b偏差
生产者与消费者
生产者:这里ADC完成测量后上报ADC采样,可以理解为生产者.在ADC采样完成16次并且依然按下的情况下上报实际adc,其他情况上报0.这里设置一个标志,只有等消费者取出数据之后,再上传数据.这里都是在中断中上报数据
void report_ts_xy(int x, int y, int pressure) {//printf("x = %08d, y = %08d\n\r", x, y);if (g_ts_data_valid == 0){g_ts_x = x;g_ts_y = y;g_ts_pressure = pressure;g_ts_data_valid = 1;} }消费者:中断中生产数据,循环中获取数据,取得数据后清除标志允许生产者上传数据.
void ts_read_raw(int *px, int *py, int *ppressure) {while (g_ts_data_valid == 0);*px = g_ts_x;*py = g_ts_y;*ppressure = g_ts_pressure;g_ts_data_valid = 0; }状态标志: g_ts_data_valid是标志.0表示消费者已经取走数据,无新数据产生
ADC获取
程序优化
视频教学修改要点
寄存器ADCDAT0只有在等待中断的模式中才能用来判断是按下还是松开状态,所以定时器中断中不能用该寄存器.所以当定时器中断发生在ADC采样中的时候,不应该打断adc采样.韦东山的优化是先判断是否是自动采样模式,如果是在采样则退出.
void touchscreen_timer_irq(void) {//定时器开关if (get_status_of_ts_timer() == 0)return; /*------------------------------------------------------------ 定时器开关只会被ADC采样16次完成后打开,其他状态下均会关闭定时器, 包括进入本函数这里的按下状态后进入自动测量模式***************************************************************/ if (is_in_auto_mode())return;/* 只有在"等待中断模式"下才可以使用ADCDAT0'BIT 15来判断触摸笔状态 */if (ADCDAT0 & (1<<15)) /* 如果松开 */{printf("timer set pen down\n\r");ts_timer_disable();enter_wait_pen_down_mode();report_ts_xy(0, 0, 0);return;}else /* 按下状态 */{/* 进入"自动测量"模式 */enter_auto_measure_mode();/* 启动ADC */ADCCON |= (1<<0);} }个人修改意见
我觉得更应该更改为如果开启了adc的采样,应该是去关闭定时器的标志.防止碰撞.定时器中断必须在采样16次完成之后才会发生.然后进入定时器中断处理的时候就能确保不会与adc中断冲突,也就是一定是在等待中断模式,上述的is_in_auto_mode也是可以去除的.
if (is_in_auto_mode())return;所以我的优化方案是
进入adc中断 进入触摸屏中断 进入定时器中断后 都先关闭定时器进入adc中断后 if按下满16次采样后打开定时器,进入等待松开中断未满16次继续打开adc采样 else 松开进入等待按下中断上报0进入触摸屏中断 if 按下 打开adc开始采样 else 松开进入等待按下中断上报0进入定时器中断且当前定时器状态为open if 按下 打开adc采样 else 松开进入等待按下中断上报0总结
TODO
参考tslib 中更牛逼的矫正算法
转载:https://www.cnblogs.com/zongzi10010/p/10023639.html
总结
以上是生活随笔为你收集整理的s3c2440arm裸机编程之ADC触摸屏的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: u-boot分析之两阶段代码分析(三)
- 下一篇: 从0写bootloader