文章目錄
- 步驟1 將ADS7843的驅動檔案夾加入APP路徑中
- 步驟2 編寫ADS7843的驅動
- 步驟3 觸控螢幕驅動測試
準備資料
1 觸控螢幕控制晶片ADS7843中文資料[1]_百度文庫
2 觸控螢幕原理與分類_百度文庫
3 [原創].觸控螢幕濾波的一點心得
4 [筆記].如何使用Nios II的中斷:PIO中斷與定時器中斷
操作步驟步驟1 將ADS7843的驅動檔案夾加入APP路徑中
步驟2 編寫ADS7843的驅動
我們先看下觸控螢幕晶片採樣的座標與TFT-LCD顯示的座標的區別和聯絡。圖中的TFT-LCD方向為所定義方向,亦即
#define ID_AM 110
其XY座標與ADS7843採樣之座標翻了。故ADS7843採樣及濾波之後,需要把XY座標翻回來。此外我們可以看到TFT-LCD顯示地區是觸控螢幕採樣晶片採樣地區的子集,因此如若將程式移植到你的平台上,請坐相應的座標校準動作。這和我們的觸控螢幕手機的校準功能是類似的的。
廢話不多說,直接貼代碼,有什麼不明白的地方,請給我留言。
代碼2.1 ads7843.h
#ifndef ADS7843_H_#define ADS7843_H_#include "my_types.h"#include "my_regs.h"#define CHX 0x90#define CHY 0xD0void ads_SPIStart(void);void ads_SPIWrite(u8 cmd);u16 ads_SPIRead(void);bool ads_ReadXY(void);bool ads_GetXY(void);u8 *intostr(u16 n);#endif /* ADS7843_H_ */
代碼2.2 ads7843.c
#include "ads7843.h"#include <unistd.h>// 全域變數,用以儲存座標資訊u16 X=0, Y=0;// SPI開始狀態void ads_SPIStart(void){ ads_CLK=0; ads_nCS=1; ads_DIN=1; ads_CLK=1; ads_nCS=0;}// SPI寫一個bytevoid ads_SPIWrite(u8 cmd){ u8 i; ads_CLK=0; for(i=0; i<8; i++) // 上升沿有效 { ads_DIN = (cmd >> (7-i)) & 0x1; // MSB在前,LSB在後 ads_CLK=0; usleep(1); ads_CLK=1; usleep(1); }}// SPI讀12個bitu16 ads_SPIRead(void){ u8 i; u16 temp=0; for(i=0; i<12; i++) // 下降沿有效 { temp<<=1; ads_CLK=1; usleep(1); ads_CLK=0; usleep(1); if(ads_DOUT) temp++; } return temp;}// 讀取ADS7843採集到X、Y值// 返回:超出螢幕範圍,則返回0bool ads_ReadXY(void){ ads_SPIStart(); ads_SPIWrite(CHX); ads_CLK=1; usleep(1); ads_CLK=0; usleep(1); X = ads_SPIRead(); ads_SPIWrite(CHY); ads_CLK=1; usleep(1); ads_CLK=0; usleep(1); Y = ads_SPIRead(); ads_nCS=1; if((X>350 && X<3800) && (Y>300 && Y<3800)) // 根據自己的屏自行矯正 return 1; // 讀數成功(範圍限制) else return 0; // 讀數失敗}// 處理從ADS7843讀取的X、Y值,然後互換#define SAMP_CNT 4#define SAMP_CNT_DIV2 2bool ads_GetXY(void){ u8 i, j, k, min; u16 temp; u16 tempXY[2][SAMP_CNT], XY[2]; // 採樣 for(i=0; i<SAMP_CNT; i++) { if(ads_ReadXY()) { tempXY[0][i] = X; tempXY[1][i] = Y; } } // 濾波 for(k=0; k<2; k++) { // 降序排列 for(i=0; i<SAMP_CNT-1; i++) { min=i; for (j=i+1; j<SAMP_CNT; j++) { if (tempXY[k][min] > tempXY[k][j]) min=j; } temp = tempXY[k][i]; tempXY[k][i] = tempXY[k][min]; tempXY[k][min] = temp; } // 設定閾值 if((tempXY[k][SAMP_CNT_DIV2]-tempXY[k][SAMP_CNT_DIV2-1]) > 5) return 0; // 求中間值的均值 XY[k] = (tempXY[k][SAMP_CNT_DIV2]+tempXY[k][SAMP_CNT_DIV2-1]) / 2; } // 矯正座標 Y = ((XY[0]-350)/11); X = ((XY[1]-400)/14); return 1;}// 整型轉字串(顯示X、Y座標,3個ASCII碼)u8 *intostr(u16 n){ u8 *p; static u8 buf[3]; p = &buf[3]; *p = (n/100) - ((n/1000)*10)+48; *(p+1) = (n/10) - ((n/100)*10) +48; *(p+2) = n- ((n/10) *10) +48; *(p+3) = 0; return p;}
步驟3 觸控螢幕驅動測試
代碼 main.c
#include <unistd.h> // usleep()#include "my_types.h" // 資料類型#include "my_regs.h" // 自訂引腳及寄存器映射#include "debug.h" // debug#include "ili932x.h" // ILI9325#include "ads7843.h" // ADS7843#include "sd_card.h" // SD Card#include "system.h" // 系統#include "altera_avalon_pio_regs.h" // PIO,ads_nIRQ#include "sys/alt_irq.h" // 中斷// 變數申明extern u16 X, Y;// 函數申明vu16 nirq_isr_context; // 定義全域變數以儲存isr_context指標void nIRQ_Initial(void);void nIRQ_ISR(void* isr_context);void ResetTouch(void);// 調試資訊顯示開關#define ENABLE_APP_DEBUG // turn on debug message#ifdef ENABLE_APP_DEBUG #define APP_DEBUG(x) DEBUG(x)#else #define APP_DEBUG(x)#endif// nIRQ中斷初始化void nIRQ_Initial(void){ // 改寫timer_isr_context指標以匹配alt_irq_register()函數原型 void* isr_context_ptr = (void*) &nirq_isr_context; IOWR_ALTERA_AVALON_PIO_IRQ_MASK(ADS_NIRQ_BASE, 1); // 使能中斷 IOWR_ALTERA_AVALON_PIO_EDGE_CAP(ADS_NIRQ_BASE, 1); // 清中斷邊沿捕獲寄存器 // 註冊ISR alt_ic_isr_register( ADS_NIRQ_IRQ_INTERRUPT_CONTROLLER_ID, // 中斷控制器標號,從system.h複製 ADS_NIRQ_IRQ, // 硬體中斷號,從system.h複製 nIRQ_ISR, // 中斷服務子函數 isr_context_ptr, // 指向與裝置驅動執行個體相關的資料結構體 0x0); // flags,保留未用}// 中斷服務子函數void nIRQ_ISR(void* isr_context){ IOWR_ALTERA_AVALON_PIO_EDGE_CAP(ADS_NIRQ_BASE, 1); // 清中斷邊沿捕獲寄存器 if(ads_GetXY()) { if((X>190 && X<240 && Y>300 && Y<320)) ResetTouch(); else { ili_PutString(34, 289, intostr(X), Blue, White); ili_PutString(34, 305, intostr(Y), Blue, White); ili_PlotBigPoint(X, Y, Red); } }}//void ResetTouch(void){ ili_ClearScreen(White); ili_PutString(190, 305, (u8 *)("Clear"), Blue, White); ili_PutString(10, 289, (u8 *)("X: 0"), Blue, White); ili_PutString(10, 305, (u8 *)("Y: 0"), Blue, White);}int main(void){ ili_Initial(); nIRQ_Initial(); ResetTouch(); while(1); return 0;}
第34~47行,初始化nIRQ引腳下降沿中斷;第51~65行,編寫nIRQ中斷函數。其他就不多說了。
測試效果如下:
源碼下載
lcd_at_nios_nii_part.zip
目錄
1 [原創][連載].基於SOPC的簡易數位相框 - Quartus II部分(硬體部分)
2 [原創][連載].基於SOPC的簡易數位相框 - Nios II SBTE部分(軟體部分)- 配置工作
3 [原創][連載].基於SOPC的簡易數位相框 - Nios II SBTE部分(軟體部分)- SD卡(SPI模式)驅動
4 [原創][連載].基於SOPC的簡易數位相框 - Nios II SBTE部分(軟體部分)- TFT-LCD(控制器為ILI9325)驅動
5 [原創][連載].基於SOPC的簡易數位相框 - Nios II SBTE部分(軟體部分)- 從SD卡內讀取圖片檔案,然後顯示在TFT-LCD上
6 [原創][連載].基於SOPC的簡易數位相框 - Nios II SBTE部分(軟體部分)- 最佳化工作
7 [原創][連載].基於SOPC的簡易數位相框 - Nios II SBTE部分(軟體部分)- ADS7843觸控螢幕驅動測試