<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                我的開發板是FL2440,其他的開發板在以下代碼中基本上是一樣的,還需要注意的是,不同的內核用的頭文件可能不一樣。還要注意下LCD顯示屏和觸摸屏是兩個概念,觸摸屏用的是兩章很薄的電阻紙片重合在一起貼在LCD顯示屏上的。觸摸屏是對ADC轉換的一種應用,初學者要多看寄存器手冊,上面講得很詳細,開始可以參考別人的代碼,但是一定要理解過來,轉換成自己的思想,廢話不多說了,請看下面的代碼。 內核版本2.6.28.7 ? ? ??虛擬機ubuntu :9.1 ~~~ #include ? #include ? #include ? #include ? #include ? #include ? #include ? #include ? #include ? #include ? #include ? #include ? #include ? #include ? #include ? struct s3c_ts_regs { ??/* 是adc所用到的寄存器,放到結構體中方便我們后面用指針操作 ,只是定義了這種類型沒有分配內存,不能添加static,后面代碼中必須把這個結構體的首地址映射到adc寄存器的首地址,我們就可以直接操作adc寄存器了,記住adc寄存器必須是連續的,我們映射是一一對應的,我們才入口函數中映射*/ 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; ? ? ? ? ? ? ? ? /* 定義input_dev類型的結構體指針,input輸入事件是重中之重 */ static volatile struct s3c_ts_regs *s3c_ts_regs; static struct timer_list ts_timer; ? ? ? ? ? ? ? ? /* 對定時器的操作,方便定時 */ static void enter_wait_pen_down_mode(void) ? /* 等待觸摸筆按下模式 */ { s3c_ts_regs->adctsc = 0xd3; } static void enter_wait_pen_up_mode(void) ?/* 等待觸摸筆按下模式 */ { s3c_ts_regs->adctsc = 0x1d3; } static void enter_measure_xy_mode(void) ??/* 等進入測量模式 */ { s3c_ts_regs->adctsc = (1//禁止上拉,設置自動進入測量模式 } static void start_adc(void) ? ??/* 開始啟動轉換ADC */ { s3c_ts_regs->adccon |= (1<<0); } 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 0; return 1; } static void s3c_ts_timer_function(unsigned long data) ? ?/* 定時器的子函數 */ { if (s3c_ts_regs->adcdat0 & (1<<15)) { /* 已經松開 */ input_report_abs(s3c_ts_dev, ABS_PRESSURE, 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(); ?/* 開始轉換后ADC */ } } static irqreturn_t pen_down_up_irq(int irq, void *dev_id) ? /* 觸摸筆按下將產生一個中斷 */ { if (s3c_ts_regs->adcdat0 & (1<<15)) { //printk("pen up\n"); input_report_abs(s3c_ts_dev, ABS_PRESSURE, 0); input_report_key(s3c_ts_dev, BTN_TOUCH, 0); input_sync(s3c_ts_dev); 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) ? ?/* adc轉換完成將產生一個中斷 */ { static int cnt = 0; static int x[4], y[4]; int adcdat0, adcdat1; /* 優化措施2: 如果ADC完成時, 發現觸摸筆已經松開, 則丟棄此次結果 */ adcdat0 = s3c_ts_regs->adcdat0; adcdat1 = s3c_ts_regs->adcdat1; if (s3c_ts_regs->adcdat0 & (1<<15)) { /* 已經松開 */ cnt = 0; input_report_abs(s3c_ts_dev, ABS_PRESSURE, 0); input_report_key(s3c_ts_dev, BTN_TOUCH, 0); input_sync(s3c_ts_dev); enter_wait_pen_down_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; enter_wait_pen_up_mode(); /* 啟動定時器處理長按/滑動的情況 */ mod_timer(&ts_timer, jiffies + HZ/100); } 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->keybit); input_set_abs_params(s3c_ts_dev, ABS_X, 0, 0x3FF, 0, 0); input_set_abs_params(s3c_ts_dev, ABS_Y, 0, 0x3FF, 0, 0); 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));??/* 這里就把我們定義的結構體類型和adc寄存器地址相關連起來了,這里映射函數有興趣的朋友可以去分析分析,看看怎么把物理地址轉換成虛擬地址的 */ /* bit[14] ?: 1-A/D converter prescaler enable * bit[13:6]: A/D converter prescaler value, * ? ? ? ? ? ?49, ADCCLK=PCLK/(49+1)=50MHz/(49+1)=1MHz * bit[0]: A/D conversion starts by enable. 先設為0 */ 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_LICENSE("GPL"); ~~~ 測試如下: ~~~ 1\. make menuconfig 去掉原來的觸摸屏驅動程序 -> Device Drivers ? -> Input device support ? ? -> Generic input layer ? ? ? -> Touchscreens ? ? ? <> ? S3C2410/S3C2440 touchscreens ~~~ make uImage 使用新內核啟動 ~~~ 2\. insmod s3c_ts.ko 按下/松開觸摸筆 1\. ls /dev/event*? 2\. insmod s3c_ts.ko 3\. ls /dev/event*? 4\. hexdump /dev/event0 ? ? ? ? ? ? 秒 ? ? ? 微秒 ? type code ? ?value 0000000 29a4 0000 8625 0008 0003 0000 0172 0000 0000010 29a4 0000 8631 0008 0003 0001 027c 0000 0000020 29a4 0000 8634 0008 0003 0018 0001 0000 0000030 29a4 0000 8638 0008 0001 014a 0001 0000 0000040 29a4 0000 863c 0008 0000 0000 0000 0000 0000050 29a4 0000 c85e 0008 0003 0000 0171 0000 0000060 29a4 0000 c874 0008 0003 0001 027d 0000 0000070 29a4 0000 c87b 0008 0000 0000 0000 0000 0000080 29a4 0000 ed37 0008 0003 0018 0000 0000 0000090 29a4 0000 ed48 0008 0001 014a 0000 0000 00000a0 29a4 0000 ed4a 0008 0000 0000 0000 0000 ~~~ 或者使用tslib庫來測試校驗觸摸屏函數,前提是你lcd驅動程序能夠正常工作,具體實現方法請看我tslib移植這篇文章。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看