/************************************* * File:18326_Logiana_22 = = * 5 Ch ロジックツール Sampl rateはmax 10 us」 * System ClockはConfigで内部32MHzに設定 * PIC16F18326 * Serial port change to RA4:Rx RA5:Tx * use CLC & RESET instruction * CLC1 out feed to CLC2 OK * Created on 2021-10-02 **************************************/ #include <xc.h> #include <stdio.h> #include <stdbool.h> #include <string.h> #define _XTAL_FREQ 32000000 // delay_ms(x) のための定義 #pragma config FEXTOSC = OFF,RSTOSC = HFINT32 // HFINTOSC (1MHz) #pragma config CLKOUTEN = OFF,CSWEN = OFF,FCMEN = OFF #pragma config MCLRE = ON,PWRTE = OFF,WDTE = OFF,LPBOREN = OFF #pragma config BOREN = OFF,BORV = LOW,PPS1WAY = OFF,STVREN = ON #pragma config DEBUG = OFF #pragma config WRT = OFF,LVP = ON,CP = OFF,CPD = OFF //#define pushSW PORTCbits.RC4 // ================= 共通変数 ==================================== bool Err_Cmd = false; // コマンドがエラー時のフラグ bool isRxReady = false; // コマンド受信したフラグ char PortData; // 入力ポートデータ char ChckData; // トリガ検査データ char AqData[1200]; // 収集データバッファ char RxWptr = 0; // 受信書込みポインタのリセット char RxRptr = 0; // 受信読込みポインタのリセット char RxWbuf[20],RxRbuf[20]; // UART Rxバッファ char MskPtn; // トリガマスクパターン char PrePtn; // トリガ準備パターン char TrgPtn; // トリガパターン char TrgChn; // トリガChannel int AqSat; // 収集開始 int AqEnd; // 収集終了 int AqPtr; // 収集ポインタ int RcdNo; // 記録データ数 // ================= プロトタイプ ==================================== void ckCommand(void); void Aquition(void); void outAqData(char *,int); void initClcs(void); // ================= printf関数を使用するための定義 ================= void putch(unsigned char ch) { while (!TXIF); //送信終了待ち TX1REG = ch; } // ******************* main ************************************* void main() { TRISA = 0b111111; // Port すべて入力 TRISC = 0b111111; // Port すべて入力 ANSELA = 0; // すべてデジタル ANSELC = 0; // すべてデジタル WPUA = 0b001111; // RA0-RA3 弱プルアップ ON WPUC = 0b100000; // RC5 弱プルアップ ON RXPPS = 0x04; //RA4->EUSART:RX RA5PPS = 0x14; //RA5->EUSART:TX //------------ Initialize timer 0 ------------------------------- T0CON1 = 0b01000000; // Fosc/4 Sync PreS 1/1 T0CON0 = 0b00000000; // T0 OFF 8bit Post 1/1 //------------ Initialize UART ---------------------------------- RC1STA = 0b10010000; // 8 bit 連続受信 TX1STA = 0b00100100; // 非同期送受信 High Baud Rate選択 BAUD1CON = 0b00001000; // 115200 baud SP1BRGH = 0; SP1BRG = 68; initClcs(); RCIE = 1; // UART Rx 割込みを使用許可 PEIE = 1; // 周辺機能割込みの使用許可 GIE = 1; // 全割込みの使用許可 printf("!!\r\n"); // 準備完了を送信 // ----------- 繰返し -------------------------------------------- while(1){ while(!RxRptr); // コマンド受信待ち ckCommand(); // コマンドの処理 RxRptr = 0; // 受信処理終了を明示 if(Err_Cmd){ // 処理エラーがあった場合 printf("!\r\n"); // 再送要求を送信 continue; // 受信待ちに戻る }else{ // 正常終了 printf("#\r\n"); // 正常終了を送信 } // -----------データの収集----------- Aquition(); // ロジックデータの収集 // -----------データ送信------------- outAqData(AqData+AqPtr, 1100-AqPtr); // 収集 outAqData(AqData, AqPtr); // 収集データ送信 printf("##\r\n"); // データ終了を送信 } } //=========================== void initClcs(){ CLCIN0PPS = 0x10; //RC0->CLC2:CLCIN0; CLCIN1PPS = 0x11; //RC1->CLC2:CLCIN1; CLCIN2PPS = 0x12; //RC2->CLC2:CLCIN2; // Set the CLC1 CLC1POL = 0x02; // G2出力は負極性; 他出力は正極性; CLC1SEL0 = 0x00; // LC1D1S (CLCIN0PPS); CLC1SEL1 = 0x01; // LC1D2S (CLCIN1PPS); CLC1SEL2 = 0x02; // LC1D3S (CLCIN2PPS); CLC1SEL3 = 0x18; // LC1D4S T0_overflow; CLC1GLS0 = 0x80; // G1D4 正接続; G1D3-1 Vss; // CLC1GLS1 = 0x02; // G2D4-2 Vss; G2D1 正接続; CLC1GLS1 = 0x01; // G2D4-2 Vss; G2D1 正接続; CLC1GLS2 = 0x00; // 全てVss; CLC1GLS3 = 0x00; // 全てVss; CLC1CON = 0x84; // EN ○; INT X-X; 1-input D ff; // Set the CLC2 CLC2POL = 0x02; CLC2SEL0 = 0x00; CLC2SEL1 = 0x04; CLC2SEL2 = 0x02; CLC2SEL3 = 0x18; CLC2GLS0 = 0x80; // CLC2GLS1 = 0x05; CLC2GLS1 = 0x06; CLC2GLS2 = 0x00; CLC2GLS3 = 0x00; CLC2CON = 0x84; } /* ******************************************************************** * コマンドの解釈・処理 * *******************************************************************/ void ckCommand(void){ int i; Err_Cmd = true; // 受信文字列のエラー確認 if(RxRptr != 7)return; // 受信文字数の確認 if(RxRbuf[0] != '#')return; // コマンド分離の確認 if(RxRbuf[4] != '#')return; // コマンド分離の確認 Err_Cmd = false; // ----------- 各ChのTrigger条件設定 ------------------------- // 10 = 信号源4を入力(正論理) 01 = 信号源4を反転入力 MskPtn=0;PrePtn=0;TrgPtn=0; // トリガパターン クリア for(i=3; i>0; i--){ // Ch3 -> Ch1を処理 PrePtn<<=2; switch(RxRbuf[i]){ case '0':break; // * 任意 case '1':PrePtn+=1; ;break; // 1 Hi case '2':PrePtn+=2; ;break; // 0 Low case '3':PrePtn+=2;TrgPtn=5;TrgChn=i-1;break; // / 立上り case '4':PrePtn+=1;TrgPtn=6;TrgChn=i-1;break; // \ 立下り default:Err_Cmd = true;return; // 指定文字以外 } } CLC1GLS1 = PrePtn; // CLC1に設定 CLC2GLS1 = TrgPtn; // CLC2に設定 CLC2SEL0 = TrgChn; // ------------------ Sample Rateの設定 --------------------- switch(RxRbuf[5]){ case '0':T0CON1bits.T0CKPS=0;TMR0H= 7;break; // 1us case '1':T0CON1bits.T0CKPS=0;TMR0H= 15;break; // 2us case '2':T0CON1bits.T0CKPS=0;TMR0H= 39;break; // 5us case '3':T0CON1bits.T0CKPS=3;TMR0H= 9;break; // 10us case '4':T0CON1bits.T0CKPS=3;TMR0H= 19;break; // 20us case '5':T0CON1bits.T0CKPS=3;TMR0H= 49;break; // 50us case '6':T0CON1bits.T0CKPS=3;TMR0H= 99;break; // 100us case '7':T0CON1bits.T0CKPS=3;TMR0H=199;break; // 200us case '8':T0CON1bits.T0CKPS=5;TMR0H=124;break; // 500us case '9':T0CON1bits.T0CKPS=5;TMR0H=249;break; // 1ms // case 'A':T0CON1bits.T0CKPS=3;TMR0H=9;break; // 2ms // case 'B':T0CON1bits.T0CKPS=3;TMR0H=9;break; // 5ms // case 'C':T0CON1bits.T0CKPS=3;TMR0H=9;break; // 10ms default:Err_Cmd = 1;return; // エラー 指定文字以外 } // ------------------- 収集開始および終了の指定 -------------------- switch(RxRbuf[6]){ case '0':AqSat= 100;AqEnd=1000;break; // トリガは前方 case '1':AqSat= 0;AqEnd=2000;break; // トリガから1ウインド後 case '2':AqSat= 0;AqEnd=3000;break; // トリガから2ウインド後 case '3':AqSat=1100;AqEnd= 0;break; // フリーラン case '4':AqSat= 550;AqEnd= 550;break; // トリガは中央 case '5':AqSat=1000;AqEnd= 100;break; // トリガは後方 default:Err_Cmd = true;return; // エラー 指定文字以外 } } /* ******************************************************************** * 入力データの取り込み処理 * *******************************************************************/ void Aquition(void){ T0CON0bits.T0EN = 1; // Timer1スタート AqPtr = 0; // 収集ポインタ リセット // -------------- トリガ前保存 および FreeRun -------------- while(AqSat--){ // AqSat(取得開始)数まで保存 while(!TMR0IF); // 取得タイミングを待つ TMR0IF = 0; // AqData[AqPtr++] = PORTC; // 保存 if(AqPtr >= 1100) AqPtr = 0; // 保存ポインタを循環 } if(AqEnd==0)return; // FreeRun時は、保存完了 do{ // ---------------- トリガ条件の確認 ------------------------- while(!TMR0IF); // 取得タイミングを待つ TMR0IF = 0; AqData[AqPtr++] = PORTC; // 保存 if(AqPtr >= 1100) AqPtr = 0; }while(!LC2OUT); // トリガ前条件成立まで待つ // ------------------- トリガ後保存 ---------------------------- while(AqEnd--){ // AqEnd(取得完了)数まで保存 while(!TMR0IF); // 取得タイミングを待つ TMR0IF = 0; // AqData[AqPtr++] = PORTC; // 保存 if(AqPtr >= 1100) AqPtr = 0; // 保存ポインタを循環 } T0CON0bits.T0EN = 0; // Timer1停止 } /* ******************************************************************** * Data配列送信 * 配列のデータを送信する 一行50文字+CRLF * adata:Data配列名 ptr:データ数 * ch1_pos;データのあるbit位置 * *******************************************************************/ void outAqData(char *adata, int ptr){ int i = 0; char c; while(ptr--){ // 指示文字数分繰り返す c = *adata++; // データを取り出しポインタを進める c = c & 0x1F; // 下位5ビットを取り出す c = c | '@'; // 「@」からの文字コードに変換 putch(c); // 一文字送信 // while(U1STAbits.UTXBF); // 送信バッファが空なら // U1TXREG = c; // 一文字送信 if((++i >= 50) | (ptr == 0)){ // 50文字毎または i = 0; // 指定数送信完了で printf("\r\n"); // CRLFを挿入 } } } /* ******************************************************************** * Uart1 Rx割込み処理 * RxWptr,RxRptr; RxWbuf[20],RxRbuf[20]; * *******************************************************************/ void __interrupt() Rx_isr(void) { char RxData; if(RCIF){ if(RC1STAbits.OERR){ // 受信エラーなら RC1STAbits.CREN = 0; // エラークリア RC1STAbits.CREN = 1; // エラークリア RxWptr = 0; // 既存データはすべて廃棄 }else{ // 正常受信なら RxData = RC1REG; switch(RxData){ // CRLFを受信したら、 case 0x0A: // それまでの受信データを case 0x0D: // RxRbufに転送する if(RxWptr){ // ただし、CRLFは転送しない memcpy(RxRbuf, RxWbuf, RxWptr); RxRptr = RxWptr; // バッファ転送し受信数保存 RxWptr = 0; // ポインタリセット } break; case '!': // トリガ中止コマンド RESET(); // デバイスのリセット命令 break; default: // 一般文字なら RxWbuf[RxWptr++] = RxData; // 受信バッファに保存 if(RxWptr >= 20)RxWptr = 0; // 容量超えはすべて廃棄 break; } } } }