/**************************************************************** * PIC24F_QJ240083S0_Touch_Test * * QJ240083S0の、タッチパネルが動くか確かめるだけの簡単な実験 * * 2.4インチQVGA液晶モジュール(aitendo): QJ240083S0 * * Condition: * 8MHz Internal RC oscillator, 4x PLL (8MHzx4= 32MHz) * Fcy=32MHz/2=16MHz, Tcy=62.5ns * * CPU: PIC24FJ64GA002 * * 2022.5.16 N.Ishii ******************************************************************/ #include "p24FJ64GA002.h" #include "colorlcd_libdsPICVH.h" /// コンフィギュレーション ビットの設定 _CONFIG1( JTAGEN_OFF // JTAGの使用:無効 & GCP_OFF // コードプロテクト:しない & GWRP_OFF // 書き込みプロテクト:しない & BKBUG_OFF // バックグラウンドデバッグ:無効 & COE_OFF // クリップオンエミュレーション:無効 & ICS_PGx1 // EMUC/EMUDをPCG1/PGD1と共用 & FWDTEN_OFF // WDT:無効 ) /// Fosc = FRC (Fosc=32MHz) _CONFIG2( IESO_OFF // 2速度スタートアップ:無効 & FNOSC_FRCPLL // 8MHz Internal RC oscillator, 4x PLL-> 8MHzx4=32MHz & FCKSM_CSDCMD // クロック切り替え・クロックモニタ:供に無効 & OSCIOFNC_ON // OSCOピン機能:RA3ポートとする 161118 & IOL1WAY_OFF // RPレジスタプロテクト:プロテクトしない & I2C1SEL_PRI // I2C1のピン選択:主ピンを使用する & POSCMOD_NONE // 主発振器:使用しない ) /// タッチ・ボタンのキャラクタコード char MsgBUTTON[] = {0xE9, 0}; // ■ /// LEDのキャラクタコード char MsgLEDon[] = {0xE4, 0}; // ● char MsgLEDoff[] = {0xE3, 0}; // ○ /// タッチボタン座標データ int Button[2][2] = {{870,800}, // [0]:ボタン-1 {640,798} // [1]:ボタン-2 }; int Count; char MsgScrn[] = "X=xxxx Y=xxxx"; // 座標表示 /// 関数プロトタイピング void SetupScreen(void); int Getscreen(unsigned int chn); int CheckBtn(int x, int y); void Process(int sw); void itostring(char digit, unsigned int data, char *buffer); ////------------------------------------------------------------------------------------------------------------- /************************************************ * メイン関数 ************************************************/ int main(void){ //// I/O設定 AD1PCFG = 0xFFFF; // A/D Digi 選択:まずは全デジタルI/Oに設定 CLKDIV = 0x0000; // System Clock devider 1:1 /// Setup PORT In/Out TRISA = 0x0009; // RA5- 15は実装されて無い:0 // RA4:0:LCD_RST/出力 // RA3:1:XL入力 // RA2:0:debug pin出力 // RA1:0:debug led出力 // RA0:1:YD入力 TRISB = 0x000F; // RB4- 15:0:QVGAポート出力 // RB3 :1:AN5/RB3入力 // RB2 :1:AN4/RB2入力 // RB1 :1:SW2入力 // RB0 :1:SW1入力 /// Set Pull Up CNPU1 = 0x0030; // Pull Up Port is RB0:SW1, RB1;SW2 LATAbits.LATA4 = 1; // LCD_RST pin初期レベル= Hi LATAbits.LATA1 = 1; // debug led off // 液晶表示器の初期化 lcd_Init(); lcd_Clear(BLACK); lcd_Str(0, 0, "Touch Test", CYAN, BLACK); lcd_Str(0, 15, MsgBUTTON, GREEN, BLACK); // ボタン-1表示(キャラクタ) lcd_Str(8, 15, MsgBUTTON, YELLOW, BLACK); // ボタン-2表示(キャラクタ) lcd_Str(4, 14, MsgLEDoff, RED, BLACK); // LED消灯表示(キャラクタ) /// タイマ1設定 50msec周期 タッチスクリーン用 /// Fosc=32M・タイマ入力源:Fcy=16M(Fcy=Fosc/2)・PS=256・PR1= 3124 /// Ft1=Fcy/PS*(PR1+1)= 16M/256*3125=20Hz=50mS周期 T1CON = 0x0030; PR1 = 3124; // 50mS IPC0bits.T1IP = 5; // 割り込みレベル5に設定 IEC0bits.T1IE = 1; // 割り込み許可 /// 変数初期化 Count = 0; SetupScreen(); // タッチスクリーン用ADC設定 //// SetupScreen(); コール この関数の中で以下を実行している。 /// 最初は、X座標入力からなので以下の設定を行う。 /// AD1PCFGbits.PCFG4 = 0; // XR(AN4/RB2)は、アナログ入力 /// AD1PCFGbits.PCFG5 = 1; // YU(AN5/RB3)は、デジタル入出力 /// タイマ1 T1CONbits.TON = 1; /// メイン ループ while(1){ } } //-------------------------------------------------------------------------------- /****************************************** * タイマ1割り込み処理(50msec周期) * タッチスクリーン アナログ入力 *******************************************/ void __attribute__((interrupt, auto_psv)) _T1Interrupt(void) { static int Xset, Yset, Xold, Yold; IFS0bits.T1IF = 0; // 割り込みフラグクリア /// debug pinに、約実測400uSの負パルスを出力 LATAbits.LATA2 = 0; delay_us(450); LATAbits.LATA2 = 1; ////////// X座標入力 /// VCC印加ステージ TRISBbits.TRISB3 = 0; // RB3(YU) は、デジタル出力 TRISAbits.TRISA0 = 0; // RA0(YD) は、デジタル出力 LATBbits.LATB3 = 1; // YU- YD間にVCC印加 LATAbits.LATA0 = 0; /// 座標読込みステージ TRISBbits.TRISB2 = 1; // RB2(AN4):XR入力(AD1PFGでアナログ入力設定するだけでなくTRISで入力に設定する必要がある) TRISAbits.TRISA3 = 1; // RA3:XL側は、入力設定で、Hi-Zとする delay_us(20); // 充電待ち 約20usec Xset = Getscreen(4); // 座標値取得 ////////// Y座標入力 AD1PCFGbits.PCFG4 = 1; // XR(AN4/RB2)を、デジタル入出力に戻す。 AD1PCFGbits.PCFG5 = 0; // YU(AN5/RB3)は、アナログ入力 /// VCC印加ステージ TRISAbits.TRISA3 = 0; // RA3(XL)は、デジタル出力 TRISBbits.TRISB2 = 0; // RB2(XR)は、デジタル出力 LATAbits.LATA3 = 1; // XL- XR間にVCC印加 LATBbits.LATB2 = 0; /// 座標読込みステージ TRISBbits.TRISB3 = 1; // RB3(AN5):YU入力 TRISAbits.TRISA0 = 1; // RA0:YD側は、入力設定で、Hi-Zとする delay_us(40); // 充電待ち 約40usec Yset = Getscreen(5); // 座標値取得 /// 次回50mS後の割込みに備え、X座標入力のポート設定にしておく。 AD1PCFGbits.PCFG4 = 0; // XR(AN4/RB2)は、アナログ入力 AD1PCFGbits.PCFG5 = 1; // YU(AN5/RB3)は、デジタル入出力 /// タッチしていないときの回避 if((Xset > 60)&&(Yset < 1000)){ // X・Y座標読込み結果が、この範囲ならタッチしたと判断し以下を実行 /// 確実なタッチの検出 if((abs(Xset - Xold) < 15) && abs(Yset - Yold) < 15){ // 現在の各座標値と、1つ前に読込んだ各座標値の差が15未満なら以下を実行 Count++; // 座標読込み回数インクリメント if(Count >= 3){ // 現在の各座標値と、1つ前に読込んだ各座標値の差が15未満が3回以上だったら確実なタッチと判断し以下を実行 LATAbits.LATA1 = 0; // debug led on Count = 0; // カウント初期化 Process(CheckBtn(Xset, Yset)); // 押されてボタンの処理とタッチ座標位置表示 } } else{ LATAbits.LATA1 = 1; // debug led off Count = 0; // 確実にタッチしてなければカウントを初期化 } /// 現在の各座標値を、オールド座標変数に退避 Xold = Xset; Yold = Yset; } /// 完全にタッチしていない時は、何もしないで抜ける。 } /******************************** * 座標取得実行関数 ********************************/ int Getscreen(unsigned int chn) { AD1CON1bits.ADON = 0; AD1CHS = chn; // Select Channel AD1CON1bits.ADON = 1; AD1CON1bits.SAMP = 1; delay_us(10); // Wait Aquisition ≒11usec(実測) AD1CON1bits.SAMP = 0; // A/D convert start while(!AD1CON1bits.DONE); // wait conversion return(ADC1BUF0); // return result } /**************************************** * タッチスクリーン用ADC設定 ****************************************/ void SetupScreen(void) { /// ADCの設定 AD1CON1bits.ADON = 0; AD1CON1 = 0x0000; // ADオフ、手動制御、10bit分解能 AD1CON2 = 0; // AVdd, AVss, SCANなし,MUXAのみ AD1CON3 = 0x0304; // 3Tad , Tad = 5*Tcy AD1CHS = 0x0000; // チャネル選択 /// 最初は、X座標入力からなので以下の設定を行う。 AD1PCFGbits.PCFG4 = 0; // XR(AN4/RB2)は、アナログ入力 AD1PCFGbits.PCFG5 = 1; // YU(AN5/RB3)は、デジタル入出力 AD1CSSL = 0; // 自動スキャンなし AD1CON1bits.ADON = 1; // AD有効化 } /********************************************************** * タッチボタン判定処理 * タッチポイントの座標から、押されたボタンの種別No.を取得 * し、その値を返す ***********************************************************/ int CheckBtn(int x, int y) { int i, btn; /// タッチ座標位置表示(デバッグ用) itostring(4, x, MsgScrn+2); itostring(4, y, MsgScrn+9); lcd_Str(3, 16, MsgScrn, GREEN, BLACK); /// ボタンチェック btn = -1; for(i=0; i<2; i++){ if((x > Button[i][0]-60)&&(x < Button[i][0]+40)){ if((y > Button[i][1]-70)&&(y < Button[i][1]+70)) btn = i; } } return(btn); } /************************************************** * タッチ・ボタンごとの処理 ***************************************************/ void Process(int sw) { switch(sw){ case 0: /// ボタン-1 lcd_Str(4, 14, MsgLEDon, RED, BLACK); // LED点灯表示(キャラクタ) break; case 1: /// ボタン-2 lcd_Str(4, 14, MsgLEDoff, RED, BLACK); // LED消灯表示(キャラクタ) break; default: break; } } /*************************************** * 整数からASCII文字に変換 ****************************************/ void itostring(char digit, unsigned int data, char *buffer) { char i; buffer += digit; // 最後の数字位置 for(i=digit; i>0; i--) { // 変換は下位から上位へ buffer--; // ポインター1 *buffer = (data % 10) + '0'; // ASCIIへ data = data / 10; // 次の桁へ } }