国产精品免费无遮挡无码永久视频-国产高潮视频在线观看-精品久久国产字幕高潮-国产精品99精品无码视亚

觸摸屏歸納為輸入子系統

發布時間:2016-4-5 17:37    發布者:信盈達電子

觸摸屏歸納為輸入子系統,這里主要是針對電阻屏,其使用過程如下
當用觸摸筆按下時,產生中斷。
在中斷處理函數處理函數中啟動ADC轉換x,y坐標。
ADC結束,產生ADC中斷
在ADC中斷處理函數里上報(input_event)啟動定時器
再次啟動定時器(可以處理滑動、長按)
松開按鍵

其驅動程序的寫法和之前寫輸入子系統的寫法基本上一致。
寫出入口函數,出口函數并加以修飾,加入相關頭文件,然后開始完善各函數,在入口函數中分配input_dev結構體,設置(能產生哪類事件,能產生這類事件中的哪些事件),注冊設備,硬件相關的操作等。出口函數中主要對之前注冊、分配的一些資源進行釋放。
還應根據2440數據手冊ADC轉換和觸摸屏那一章,對相關寄存器根據實際需要進行設置。

點擊(此處)折疊或打開

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct s3c_ts_regs {                     /* 相關的寄存器 */
    unsigned long adccon;
    unsigned long adctsc;
    unsigned long adcdly;
    unsigned long adcdat0;
    unsigned long adcdat1;
    unsigned long adcupdn;
};
static struct input_dev *s3c_ts_dev;
static volatile struct s3c_ts_regs *s3c_ts_regs;
static struct timer_list ts_timer;
void enter_wait_pen_down_mode(void)  /* 進入等待觸摸筆按下模式 */
{
    s3c_ts_regs->adctsc = 0xd3;      /* 進入等待中斷模式 bit[8]為0 2440手冊P442 */
}
void enter_wait_pen_up_mode(void)       /* 進入等待觸摸筆松開模式 */
{
    s3c_ts_regs->adctsc = 0x1d3;        /* 進入等待中斷模式 bit[8]為1 2440手冊P442 */
}
static void enter_measure_xy_mode(void) /* 進入xy測量模式 */
{
    s3c_ts_regs->adctsc = (1<<3) | (1<<2);
}
static void start_adc(void)
{
    s3c_ts_regs->adccon |= (1<<0);       /* 啟動ADC */
}
static int s3c_filter_ts(int x[, int y[)      /* 軟件過濾 */
{
#define ERR_LIMIT 10      /* 經驗值,容差值 */
    int avr_x, avr_y;
    int det_x, det_y;
    avr_x = (x[0 + x[1)/2;
    avr_y = (y[0 + y[1)/2;
    det_x = (x[2 > avr_x) ? (x[2 - avr_x) : (avr_x - x[2);
    det_y = (y[2 > avr_y) ? (y[2 - avr_y) : (avr_y - y[2);
    if ((det_x > ERR_LIMIT) || (det_y > ERR_LIMIT))
        return 0;
    avr_x = (x[1 + x[2)/2;
    avr_y = (y[1 + y[2)/2;
    det_x = (x[3 > avr_x) ? (x[3 - avr_x) : (avr_x - x[3);
    det_y = (y[3 > avr_y) ? (y[3 - avr_y) : (avr_y - y[3);
    if ((det_x > ERR_LIMIT) || (det_y > ERR_LIMIT))
        return 1;
}
static void s3c_ts_timer_functions(unsigned long data)
{
    if (s3c_ts->adcdat0 & (1<<15))   /* 假設時間到 */
    {
        /* 如果觸摸已經松開 */
        input_report_abs(s3c_ts_dev, ABS_PRESSURE, 0);   /* 上報事件,壓力值為0 */
        input_report_key(s3c_ts_dev, BTN_TOUCH, 0);
        input_sync(s3c_ts_dev);    /* 上報完后要同步 */
        enter_wait_pen_down_mode();  /* 進入觸摸等待模式 */
    }
    else
    {
        /* 否則測量x,y坐標 */
        enter_measure_xy_mode();
        start_adc();
    }
}
static irqreturn_t pen_down_up_irq(int irq, void *dev id)
{
    if (s3c_ts->adcdat0 & (1<<15))   /* 2440手冊P447 ADCDAT0寄存器 */
    {
        printk("pen up\n");
        enter_wait_pen_down_mode();
    }
    else
    {
        //printk("pen down\n");
        //enter_wait_pen_up_mode();
        enter_measure_xy_mode();
        start_adc();
    }
    return IRQ_HANDLED;
}
static irqreturn_t adc_irq(int irq, void *dev id)
{
    static int cnt = 0;
    static int x[4, y[4;
    int adcdat0, adcdat1;
    /* 優化措施2
     * 如果ACD完成時,發現觸摸筆已松開,則丟棄此次結果
     */
    adcdat0 = s3c_ts_regs->adcdat0;
    adcdat1 = s3c_ts_regs->adcdat1;
    if (s3c_ts->adcdat0 & (1<<15))     /* bit[15判斷是否松開 */
    {
        /* 如果已經松開則丟棄結果 */
        cnt = 0;
        input_report_abs(s3c_ts_dev, ABS_PRESSURE, 0);   /* 上報事件,壓力值為0 */
        input_report_key(s3c_ts_dev, BTN_TOUCH, 0);
        input_sync(s3c_ts_dev);
        enter_wait_pen_up_mode();
    }
    else
    {
        /* 如果還是按下,則打印結果并進入等待松開模式 */
        //printk("adc_irq cnt = %d,x = %d, y = %d\n", ++cnt, adcdat0 & 0x3ff, adcdat1 & 0x3ff);
        /* 優化措施3:
         * 多次測量取平均值
         */
        x[cnt = adcdat0 & 0x3ff;    /* 將測量結果存入靜態變量中 */
        y[cnt = adcdat1 & 0x3ff;
        ++cnt;
        if (cnt == 4)
        {
            /* 優化措施4
             * 軟件過濾
             */
             if (s3c_filter_ts(x, y))
            {
                //printk("x = %d, y = %d\n", (x[0+x[1+x[2+x[3)/4, (y[0+y[1+y[2+y[3)/4);
                input_report_abs(s3c_ts_dev, ABS_X, (x[0+x[1+x[2+x[3)/4);
                input_report_abs(s3c_ts_dev, ABS_Y, (y[0+y[1+y[2+y[3)/4);
                input_report_abs(s3c_ts_dev, ABS_PRESSURE, 1);
                input_report_key(s3c_ts_dev, BTN_TOUCH, 1);
                input_sync(s3c_ts_dev);
            }
            cnt = 0;    /* cnt計數清0 */
            enter_wait_pen_up_mode();       /* 測量完后要進入等待松開模式,這樣才能連續操作 */
            /* 啟動定時器處理長按/滑動的情況 */
            mod_timer(&ts_timer, jiffies + HZ/100);  /* 1HZ/100 = 10ms */
        }
        else    /* 否則再測量一次 */
        {
            enter_measure_xy_mode();
            start_adc();
        }
    }
        return IRQ_HANDLED;
}
static int s3c_ts_init(void)
{
    struct clk* clk;
    /* 1.分配一個input_dev結構體 */
    s3c_ts_dev = input_allocate_device();
    /* 2.設置 */
    /* 2.1 能產生哪類事件 */
    set_bit(EV_KEY, s3c_ts_dev->evbit);  /* 能夠產生按鍵事件 */
    set_bit(EV_ABS, s3c_ts_dev->evbit);  /* 能夠產生絕對位移事件 */
    /* 2.2 能產生這類事件里的哪些事件 */
    set_bit(BTN_TOUCH, s3c_ts_dev->evbit); /* 能夠產生按鍵類里面的觸摸屏事件 */
    input_set_abs_params(s3c_ts_dev, ABS_X, 0, 0x3FF, 0, 0);   /* X方向 0xFF是因為觸摸屏ADC是10位 */
    input_set_abs_params(s3c_ts_dev, ABS_Y, 0, 0x3FF, 0, 0);   /* Y方向 */
    input_set_abs_params(s3c_ts_dev, ABS_PRESSURE, 0, 1, 0, 0);/* 壓力方向 */
    /* 3.注冊 */
    input_register_device(s3c_ts_dev);
    /* 4.硬件相關的操作 */
    /* 4.1 使能時鐘CLKCON[15 (總開關,一般對不用的設備,時鐘一般是關閉的) */
    clk = clk_get(NULL, "adc");
    clk_enable(clk);
    /* 4.2 設置S3c2440的ADC/TS寄存器 */
    s3c_ts_regs = ioremap(0x58000000, sizeof(struct s3c_ts_regs));
    /* ADCCON
     * bit[14   : 1 預分頻使能
     * bit[13:6 :   預分頻系數
     *               49 ,ADCCLK = PCLK/(49+1) = 50MHz/(49+1)=1MHz
     * bit[5:3  : 多路選擇
     * bit[2    : 省電模式選擇
     * bit[1    : AD啟動方式,通過讀來啟動
     * bit[0    : 啟動AD轉換,啟動后會自動清零
     */
    s3c_ts_regs->adccon = (1<<14) | (49<<6);
    request_irq(IRQ_TC, pen_down_up_irq, IRQF_SAMPLE_RANDOM, "ts_pen", NULL);
    request_irq(IRQ_ADC, adc_irq, IRQF_SAMPLE_RANDOM, "adc", NULL);
    /* 優化措施1
     * 設置ADCDLY為最大值,使得電壓穩定后再發出中斷IRQ_TC
     */
    s3c_ts_regs->adcdly   = 0xffff;
    /* 優化措施5
     * 使用定時器,用來解決連按或滑動
     */
    init_timer(&ts_timer);
    ts_timer.function = s3c_ts_timer_function;
    add_timer(&ts_timer);
    enter_wait_pen_down_mode();
    return 0;
}
static void s3c_ts_exit(void)
{
    free_irq(IRQ_TC, NULL);
    free_irq(IRQ_ADC, NULL);
    iounmap(s3c_ts_regs);
    input_unregister_device(s3c_ts_dev);
    input_free_device(s3c_ts_dev);
    del_timer(&ts_timer);
}
module_init(s3c_ts_init);
module_exit(s3c_ts_exit);
MODULE_DESCRIPTION("s3c_ts driver for the s3c2440");
MODULE_LICENSE("GPL");




測試方法主要是檢測上報事件是否正常,要想更好的測試,需要移植ts_lib這方面的資料網上都可以找到。
以tslib-1.4.tar.gz為例
sudo apt-get install autoconf
sudo apt-get install automake
sudo apt-get install libtool




編譯:
tar xzf tslib-1.4.tar.gz
cd tslib
./autogen.sh

mkdir tmp      // 安裝目錄
echo "ac_cv_func_malloc_0_nonnull=yes" >arm-linux.cache
./configure --host=arm-linux --cache-file=arm-linux.cache --prefix=$(pwd)/tmp
make
make install

安裝:
cd tmp
cp * -rf /nfsroot    //  /nfsroot可根據實際情況來定


使用:

先安裝s3c_ts.ko, lcd.ko     // lcd.ko是之前編譯好的LCD驅動,如果后面編譯s3c_ts時改過配置,直接裝載之前編譯好的lcd.ko可能會出現段錯誤,重新編譯一下lcd驅動就可以了。

1.
修改 /etc/ts.conf第1行(去掉#號和第一個空格):
# module_raw input
改為:
module_raw input

2.
export TSLIB_TSDEVICE=/dev/event0
export TSLIB_CALIBFILE=/etc/pointercal
export TSLIB_CONFFILE=/etc/ts.conf
export TSLIB_PLUGINDIR=/lib/ts
export TSLIB_CONSOLEDEVICE=none
export TSLIB_FBDEVICE=/dev/fb0

ts_calibrate

ts_test

更多C語言 C++、JAVA、數電模電、51單片機PIC stm32 ARM Linux驅動 嵌入式、安卓系統 FPGADSP Cortex-M3學習

請咨詢  朱工,騰訊QQ3208919269  中國移動15088133726  深圳南山、民治、龍崗、西鄉、長沙、鄭州、南寧同步學習中! 

理論與實踐相結合 一線工程師項目經理教學 結合真實的產品案列 讓你感受前所未有的電子產品的開發流程

2015給自己一個決心,只為自己!高薪就業不是夢,有想法你就來 IT達人等著你!!!


本文地址:http://www.4huy16.com/thread-162607-1-1.html     【打印本頁】

本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
您需要登錄后才可以發表評論 登錄 | 立即注冊

廠商推薦

  • Microchip視頻專區
  • 電動兩輪車設計生態系統
  • 技術熱潮席卷三城,2025 Microchip中國技術精英年會圓滿收官!
  • Microchip第22屆中國技術精英年會上海首站開幕
  • “芯”光璀璨,鵬城共賞——2025 Microchip中國技術精英年會深圳站回顧
  • 貿澤電子(Mouser)專區
關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
快速回復 返回頂部 返回列表