欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

s3c2440arm裸机编程之ADC触摸屏

发布时间:2025/4/5 65 豆豆
生活随笔 收集整理的这篇文章主要介绍了 s3c2440arm裸机编程之ADC触摸屏 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

ADC触摸屏

硬件原理

s3c2440有8通道的ADC,一次同时只能查询一个通道。分为A0~A7。这里的P(positive)表示的是正的意思

ADC通道  
A4TSYM-Y
A5TSYP+Y
A6TSXM-X
A7TSXP+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采样,等待ADC采样完成中断
  • 松开触摸屏触发中断,退出流程
  • ADC中断中获得XY的坐标,然后依然需要采样输出,这里可以采用打开定时器,定时采样
  • 定时器中断到后,判断是否抬起,如果依然按下,触发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; }

    中断函数

  • 定时器中断函数
  • adc中断函数,包括adc采样完成中断和触摸屏触发中断
  • 备注:可以发现,松开状态下进入中断,都进入空闲等待按下中断模式

    触摸屏中断

    if 松开中断关闭一切,进入等待按下模式 else 按下中断进入自动测量模式打开adc

    定时器中断

    if 松开关闭定时器进入等待按下模式 else 按下进入自动测量模式打开adc

    ADC中断

    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获取

  • 等待点击,直到按键按下
  • 按下后检测弹开,后上报数据坐标
  • /* 等待点击 */do {ts_read_raw(&x, &y, &pressure); } while (pressure == 0);/* 等待弹开 */ do {*px = x;*py = y;ts_read_raw(&x, &y, &pressure); printf("get raw data: x = %08d, y = %08d\n\r", x, y); } while (pressure);
  • 判断XY是否颠倒.取X轴上的两个坐标A-----B,那么BX-AX应大于BY-AY,BY-AY约等于0
  • int is_ts_xy_swap(int a_ts_x, int a_ts_y, int b_ts_x, int b_ts_y) {int dx = b_ts_x - a_ts_x;int dy = b_ts_y - a_ts_y;if (dx < 0)dx = 0 - dx;if (dy < 0)dy = 0 - dy;if(dx > dy)return 0; /* xy没有反转 */elsereturn 1; /* xy反了 */ }
  • 如果颠倒的话,需要将每个点的X与Y互换
  • if (g_ts_xy_swap) {/* 对调所有点的XY坐标 */swap_xy(&a_ts_x, &a_ts_y);swap_xy(&b_ts_x, &b_ts_y);swap_xy(&c_ts_x, &c_ts_y);swap_xy(&d_ts_x, &d_ts_y);swap_xy(&e_ts_x, &e_ts_y); }
  • 坐标计算
  • /* ---------------------------- | | | +(A) (B)+ | | | | | | | | +(E) | | | | | | | | +(D) (C)+ | | | ----------------------------*//* 确定公式的参数并保存 */ ts_s1 = b_ts_x - a_ts_x; ts_s2 = c_ts_x - d_ts_x; lcd_s = xres-50 - 50;ts_d1 = d_ts_y - a_ts_y; ts_d2 = c_ts_y - b_ts_y; lcd_d = yres-50-50;g_kx = ((double)(2*lcd_s)) / (ts_s1 + ts_s2); g_ky = ((double)(2*lcd_d)) / (ts_d1 + ts_d2);g_ts_xc = e_ts_x; g_ts_yc = e_ts_y;g_lcd_xc = xres/2; g_lcd_yc = yres/2;printf("A lcd_x = %08d, lcd_y = %08d\n\r", get_lcd_x_frm_ts_x(a_ts_x), get_lcd_y_frm_ts_y(a_ts_y));int get_lcd_x_frm_ts_x(int ts_x) {return g_kx * (ts_x - g_ts_xc) + g_lcd_xc; }int get_lcd_y_frm_ts_y(int ts_y) {return g_ky * (ts_y - g_ts_yc) + g_lcd_yc; }

    程序优化

    视频教学修改要点

  • 启动ADC时不应该进入等待中断模式,它会影响数据,视频教程中会有adc中断和定时器中断碰撞的问题,也就是adc采样未完成,可能先发生定时器中断的问题,然后定时器中断去触发等待中断的模式
  • 只有在"等待中断模式"下才可以使用ADCDAT0'BIT 15来判断触摸笔状态
  • 校准非常重要,所以在程序种多次测量求平均值(不仅仅是在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触摸屏的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。