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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

s3c2440arm裸机编程之ADC触摸屏

發布時間:2025/4/5 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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触摸屏的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。