日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ADC触摸屏

發(fā)布時間:2023/12/15 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ADC触摸屏 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

  • ADC觸摸屏
    • 硬件原理
    • 等效電路
    • 測量邏輯
    • 程序設(shè)計(一)獲得ADC
      • 寄存器初始化
      • 中斷初始化
      • ADC模式(中斷、測量)
      • 中斷函數(shù)
    • 程序設(shè)計(二)獲得坐標(biāo)
      • 生產(chǎn)者與消費者
      • ADC獲取
    • 程序優(yōu)化
    • 個人修改意見
    • TODO

title: ADC觸摸屏
tags: ARM
date: 2018-11-02 18:35:45
---

ADC觸摸屏

硬件原理

s3c2440有8通道的ADC,一次同時只能查詢一個通道。分為A0~A7。這里的P(positive)表示的是正的意思

ADC通道
A4TSYM-Y
A5TSYP+Y
A6TSXM-X
A7TSXP+X

觸摸屏采樣有3種方式:

  • 自動反轉(zhuǎn)XY軸相關(guān)開關(guān)采樣
  • 手動切換開關(guān)采樣
  • 等待中斷模式,這個是平時沒按下的狀態(tài)

電阻屏的觸摸原理,其實就是在一個均勻的電阻上采樣后得到電壓,然后基于vcc算出相對偏移.假設(shè)電阻總長為L,采樣電壓為V1,那么長度偏移則是V/DVDD*L.

基于此在X方向和Y方向均有均勻電阻.所以觸摸屏實際是兩片透明且均勻的電阻,不按下的時候中間并不導(dǎo)通.轉(zhuǎn)換選擇導(dǎo)通X方向與Y方向依次測的X坐標(biāo)與Y坐標(biāo).也就是先連接Xm--Xp,側(cè)的Yp的采樣,就能獲得X的偏移.

板載電路

這里X軸和Y軸接反了,尅使用Tslib庫旋轉(zhuǎn)倒置等

等效電路

關(guān)閉模式:斷開上拉電阻與4線電路,防止漏電流

空閑等待中斷:這個狀態(tài)是平時沒有按下觸摸屏,等待按下觸發(fā)一個按下的中斷,當(dāng)左右兩邊電阻觸發(fā)的時候,導(dǎo)通了XP到Y(jié)M到GND,這將使Y_ADC=0,--↓__產(chǎn)生一個下降沿等待中斷模式設(shè)置值為 ADCTSC=0xd3; // XP_PU, XP_Dis, XM_Dis,YP_Dis,YM_En同樣的,當(dāng)按下后,還是同樣的等效電路,當(dāng)松開的時候,會有一個上升延中斷.配置ADCTSC的BIT8即可.

X軸采樣:這里連通XP-XM,采樣X_ADC

Y軸采樣:這里連通YP-YM,采樣Y_ADC

測量邏輯

觸摸屏實際有兩層,按下的時候,導(dǎo)通了上下兩個平面,通過等效電路,可以看出通過切換開關(guān),能夠得到兩種阻值。

  • 按下觸摸屏觸發(fā)中斷,打開ADC采樣,等待ADC采樣完成中斷
  • 松開觸摸屏觸發(fā)中斷,退出流程
  • ADC中斷中獲得XY的坐標(biāo),然后依然需要采樣輸出,這里可以采用打開定時器,定時采樣
  • 定時器中斷到后,判斷是否抬起,如果依然按下,觸發(fā)ADC采樣,這里關(guān)閉定時器自身的處理函數(shù)(關(guān)閉定時器中斷).如果抬起,觸摸屏轉(zhuǎn)換到等待狀態(tài),關(guān)閉自身中斷.
  • 流程圖在這里
  • 程序設(shè)計(一)獲得ADC

    寄存器初始化

    這里的DELAY 可以用作穩(wěn)定ADC輸出,也就是按下后多長時間開始采樣

    /* 1. 設(shè)置允許分配,分配系數(shù)為49+1,時鐘為100M/50=2 2. 選擇A0通道,因為后面選擇自動轉(zhuǎn)換,可以不考慮通道 */ ADCCON = (1<<14) | (49<<6) | (0<<3);/* 按下觸摸屏, 延時一會再發(fā)出TC中斷* 延時時間 = ADCDLY * 晶振周期 = ADCDLY * 1 / 12000000 = 5ms*/ ADCDLY = 60000;

    中斷初始化

    //清除掛起標(biāo)志 SUBSRCPND = (1<<TC_INT_BIT) | (1<<ADC_INT_BIT); //取消次級屏蔽 INTSUBMSK &= ~((1<<ADC_INT_BIT) | (1<<TC_INT_BIT)); //注冊中斷函數(shù),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個模式的切換,空閑的時候進入等待按下中斷的模式,然后進入自動測量的模式,在測量完成后需要進入等待松開的中斷模式.此時可以設(shè)置定時器等待觸發(fā)下一次的自動測量

    // 空閑下等待觸發(fā)落下中斷 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; }

    中斷函數(shù)

  • 定時器中斷函數(shù)
  • adc中斷函數(shù),包括adc采樣完成中斷和觸摸屏觸發(fā)中斷
  • 備注:可以發(fā)現(xiàn),松開狀態(tài)下進入中斷,都進入空閑等待按下中斷模式

    觸摸屏中斷

    if 松開中斷關(guān)閉一切,進入等待按下模式 else 按下中斷進入自動測量模式打開adc

    定時器中斷

    if 松開關(guān)閉定時器進入等待按下模式 else 按下進入自動測量模式打開adc

    ADC中斷

    if 松開關(guān)閉定時器進入等待按下模式 else 按下打印adc值*進入等待中斷模式打開定時器//這里可以優(yōu)化做平均值 if 松開關(guān)閉定時器進入等待按下模式上報數(shù)據(jù) else 按下if 測量計數(shù)到達16次返回平均值,開啟定時器else 直接進入自動測量模式

    優(yōu)化版本

    進入adc中斷 進入觸摸屏中斷 進入定時器中斷后 都先關(guān)閉定時器進入adc中斷后 if按下滿16次采樣后打開定時器,進入等待松開中斷未滿16次繼續(xù)打開adc采樣 else 松開進入等待按下中斷上報0進入觸摸屏中斷 if 按下 打開adc開始采樣 else 松開進入等待按下中斷上報0進入定時器中斷且當(dāng)前定時器狀態(tài)為open if 按下 打開adc采樣 else 松開進入等待按下中斷上報0

    程序設(shè)計(二)獲得坐標(biāo)

    同理,Y軸的坐標(biāo)也按照相同的方式計算.程序設(shè)計中依次畫出5個十字架,用戶點擊后計算K與b偏差

    生產(chǎn)者與消費者

    生產(chǎn)者:這里ADC完成測量后上報ADC采樣,可以理解為生產(chǎn)者.在ADC采樣完成16次并且依然按下的情況下上報實際adc,其他情況上報0.這里設(shè)置一個標(biāo)志,只有等消費者取出數(shù)據(jù)之后,再上傳數(shù)據(jù).這里都是在中斷中上報數(shù)據(jù)

    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;} }

    消費者:中斷中生產(chǎn)數(shù)據(jù),循環(huán)中獲取數(shù)據(jù),取得數(shù)據(jù)后清除標(biāo)志允許生產(chǎn)者上傳數(shù)據(jù).

    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; }

    狀態(tài)標(biāo)志: g_ts_data_valid是標(biāo)志.0表示消費者已經(jīng)取走數(shù)據(jù),無新數(shù)據(jù)產(chǎn)生

    ADC獲取

  • 等待點擊,直到按鍵按下
  • 按下后檢測彈開,后上報數(shù)據(jù)坐標(biāo)
  • /* 等待點擊 */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軸上的兩個坐標(biāo)A-----B,那么BX-AX應(yīng)大于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沒有反轉(zhuǎn) */elsereturn 1; /* xy反了 */ }
  • 如果顛倒的話,需要將每個點的X與Y互換
  • if (g_ts_xy_swap) {/* 對調(diào)所有點的XY坐標(biāo) */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); }
  • 坐標(biāo)計算
  • /* ---------------------------- | | | +(A) (B)+ | | | | | | | | +(E) | | | | | | | | +(D) (C)+ | | | ----------------------------*//* 確定公式的參數(shù)并保存 */ 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; }

    程序優(yōu)化

    視頻教學(xué)修改要點

  • 啟動ADC時不應(yīng)該進入等待中斷模式,它會影響數(shù)據(jù),視頻教程中會有adc中斷和定時器中斷碰撞的問題,也就是adc采樣未完成,可能先發(fā)生定時器中斷的問題,然后定時器中斷去觸發(fā)等待中斷的模式
  • 只有在"等待中斷模式"下才可以使用ADCDAT0'BIT 15來判斷觸摸筆狀態(tài)
  • 校準(zhǔn)非常重要,所以在程序種多次測量求平均值(不僅僅是在adc中斷中求平均值)
  • 寄存器ADCDAT0只有在等待中斷的模式中才能用來判斷是按下還是松開狀態(tài),所以定時器中斷中不能用該寄存器.所以當(dāng)定時器中斷發(fā)生在ADC采樣中的時候,不應(yīng)該打斷adc采樣.韋東山的優(yōu)化是先判斷是否是自動采樣模式,如果是在采樣則退出.

    void touchscreen_timer_irq(void) {//定時器開關(guān)if (get_status_of_ts_timer() == 0)return; /*------------------------------------------------------------ 定時器開關(guān)只會被ADC采樣16次完成后打開,其他狀態(tài)下均會關(guān)閉定時器, 包括進入本函數(shù)這里的按下狀態(tài)后進入自動測量模式***************************************************************/ if (is_in_auto_mode())return;/* 只有在"等待中斷模式"下才可以使用ADCDAT0'BIT 15來判斷觸摸筆狀態(tài) */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 /* 按下狀態(tài) */{/* 進入"自動測量"模式 */enter_auto_measure_mode();/* 啟動ADC */ADCCON |= (1<<0);} }

    個人修改意見

    我覺得更應(yīng)該更改為如果開啟了adc的采樣,應(yīng)該是去關(guān)閉定時器的標(biāo)志.防止碰撞.定時器中斷必須在采樣16次完成之后才會發(fā)生.然后進入定時器中斷處理的時候就能確保不會與adc中斷沖突,也就是一定是在等待中斷模式,上述的is_in_auto_mode也是可以去除的.

    if (is_in_auto_mode())return;

    所以我的優(yōu)化方案是

    進入adc中斷 進入觸摸屏中斷 進入定時器中斷后 都先關(guān)閉定時器進入adc中斷后 if按下滿16次采樣后打開定時器,進入等待松開中斷未滿16次繼續(xù)打開adc采樣 else 松開進入等待按下中斷上報0進入觸摸屏中斷 if 按下 打開adc開始采樣 else 松開進入等待按下中斷上報0進入定時器中斷且當(dāng)前定時器狀態(tài)為open if 按下 打開adc采樣 else 松開進入等待按下中斷上報0

    總結(jié)

  • 處理好各種中斷下的模式
  • 判斷斷開還是按下應(yīng)該是在等待中斷模式下的
  • 校準(zhǔn)值應(yīng)該求平均
  • 采樣畫點值也該求平均
  • TODO

    參考tslib 中更牛逼的矯正算法

    轉(zhuǎn)載于:https://www.cnblogs.com/zongzi10010/p/10023639.html

    總結(jié)

    以上是生活随笔為你收集整理的ADC触摸屏的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。