/* *************************************************** * ロジックアナライザー データ収集・表示 * *************************************************** * コマンド受信は割込みで処理 * クロックは4MHzXtalをPLLで20倍にし、80MHz(40MIPS) * * Target PIC dsPic33FJ128GP802 * MPLAB X , Microchip XC16 * Created on 2014/12/22, 17:45 * 20211116 CXL を RESET命令に変更 * ******************************************************/ #define FCY 40000000UL // 80MHz / 2 #define ch1_pos 6 // Ch1のPortB入力端子位置 //******************************************************* #include <xc.h> #include <string.h> #include <libpic30.h> // 遅延ライブラリ // コンフィギュレーション ****** XT(3-10MHz)発振 + PLL ****** _FGS(GWRP_OFF & GCP_OFF); _FOSCSEL(FNOSC_PRIPLL); _FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_XT); _FWDT(FWDTEN_OFF); // プロトタイプ ********************************************* void ckCommand(void); void Aquition(void); void intl_UART1(void); void UART_str(char *, char); void UART_rom(const char *); void outAqData(int *, int); // 共通変数 ************************************************* int __attribute__((address(0x800))) AqData[1200]; // 収集データバッファ int Err_Cmd; // エラー発生フラグ int freeRun; // フリーランコマンド受信 int MskPtn; // トリガマスクパターン int PrePtn; // トリガ準備パターン int TrgPtn; // トリガパターン int AqSat; // 収集開始 int AqEnd; // 収集終了 int PortData; // 入力ポートデータ int ChckData; // トリガ検査データ int AqPtr; // 収集ポインタ int RcdNo; // 記録データ数 unsigned char RxWptr,RxRptr; // UART Rx文字数 char RxWbuf[20],RxRbuf[20]; // UART Rxバッファ // メイン *********************************************************** int main (void){ // -------------- PLLに関連する設定 ---------------------------- PLLFBD = 78; // M = 80 4MHz x80/2/2 CLKDIVbits.PLLPOST=0; // N2 = 2 = 80MHz CLKDIVbits.PLLPRE=0; // N1 = 2 while (OSCCONbits.LOCK!=1); // PLLの安定(LOCK)を待つ // ---------------- 初期設定 ------------------------------------ Err_Cmd = 0; // エラー発生フラグ // ----------------------------------- T1CON = 0x0010; // Timer1 PS 1:8 初期設定 RxWptr = 0; // 受信書込みポインタのリセット RxRptr = 0; // 受信読込みポインタのリセット intl_UART1(); // UART設定 _U1RXIP = 4; // Rx割込優先度を4に設定 (既定値) _U1RXIF = 0; // Rx割込フラッグをクリア _U1RXIE = 1; // Rx割込を許可 // ---------------- メインループ ------------------------------- while(1){ // ----------コマンド受信---------- while(!RxRptr); // 待ち ckCommand(); // コマンドの処理 RxRptr = 0; // 受信処理終了を明示 if(Err_Cmd){ // 処理エラーがあった場合 UART_rom("!\r\n"); // 再送要求を送信 continue; // 受信待ちに戻る }else{ // 正常終了 UART_rom("#\r\n"); // 正常終了を送信 } // -----------データの収集----------- Aquition(); // -----------データ送信------------- outAqData(AqData+AqPtr, 1100-AqPtr); // 収集 outAqData(AqData, AqPtr); // 収集データ送信 UART_rom("##\r\n"); // データ終了を送信 } return 0; } /* ******************************************************************** * PCからのコマンドでトリガ条件を設定する * #〇〇〇#〇〇 * ||| |└Trigger位置 * ||| └ Sample Rate * ||└ Ch3 Trigger条件 * |└─ Ch2 Trigger条件 * └── Ch1 Trigger条件 * Err_Cmd 「1」での復帰はエラーを示す * 使用する共通変数 * Err_Cmd, RxRptr, RxRbuf * MskPtn, PrePtn, TrgPtn * PR1 * AqSat, AqEnd * *******************************************************************/ void ckCommand(void){ int i; Err_Cmd = 1; // 受信文字列のエラー確認 if(RxRptr != 7)return; // 受信文字数の確認 if(RxRbuf[0] != '#')return; // コマンド分離の確認 if(RxRbuf[4] != '#')return; // コマンド分離の確認 Err_Cmd = 0; // ----------- 各ChのTrigger条件設定 ------------------------- MskPtn=0;PrePtn=0;TrgPtn=0; // トリガパターン クリア for(i=3; i>0; i--){ // Ch3 -> Ch1を処理 MskPtn<<=1; PrePtn<<=1; TrgPtn<<=1; switch(RxRbuf[i]){ case '0':break; // * 任意 case '1':MskPtn++;PrePtn++;TrgPtn++;break; // 1 Hi case '2':MskPtn++; break; // 0 Low case '3':MskPtn++; TrgPtn++;break; // / 立上り case '4':MskPtn++;PrePtn++; break; // \ 立下り default:Err_Cmd = 1;return; // 指定文字以外 } } // Ch位置をボードの接続端子位置に合わせる MskPtn<<=ch1_pos; PrePtn<<=ch1_pos; TrgPtn<<=ch1_pos; // ------------------ Sample Rateの設定 --------------------- switch(RxRbuf[5]){ case '0':PR1 = 4;break; // 1us case '1':PR1 = 9;break; // 2us case '2':PR1 = 24;break; // 5us case '3':PR1 = 49;break; // 10us case '4':PR1 = 99;break; // 20us case '5':PR1 = 249;break; // 50us case '6':PR1 = 499;break; // 100us case '7':PR1 = 999;break; // 200us case '8':PR1 = 2499;break; // 500us case '9':PR1 = 4999;break; // 1ms case 'A':PR1 = 9999;break; // 2ms case 'B':PR1 = 24999;break; // 5ms case 'C':PR1 = 49999;break; // 10ms default:Err_Cmd = 1;return; // エラー 指定文字以外 } // ------------------- 収集開始および終了の指定 -------------------- freeRun = 0; 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;freeRun= 1;break; // フリーラン case '4':AqSat= 550;AqEnd= 550;break; // トリガは中央 case '5':AqSat=1000;AqEnd= 100;break; // トリガは後方 default:Err_Cmd = 1;return; // エラー 指定文字以外 } } /* ******************************************************************** * 入力データの取り込み処理 * *******************************************************************/ void Aquition(void){ T1CONbits.TON = 1; // Timer1スタート AqPtr = 0; // 収集ポインタ リセット RcdNo = 0; // トリガ後データ数 リセット do{ // -------------- トリガ前保存 および FreeRun -------------- while(!_T1IF); // 取得タイミングを待つ _T1IF = 0; // PortData = PORTB; // データを読込 AqData[AqPtr++] = PortData; // 保存 if(AqPtr > 1100) AqPtr = 0; // 保存ポインタを循環 }while(AqPtr < AqSat); // AqSat(取得開始)数まで保存 if(freeRun)return; // FreeRun時は、保存完了 do{ // ---------------- トリガ条件の確認 ------------------------- do{ // -------------- 前条件の確認 --------------------------- while(!_T1IF); // 取得タイミングを待つ _T1IF = 0; // PortData = PORTB; // データ読込 AqData[AqPtr++] = PortData; // 保存 if(AqPtr > 1100) AqPtr = 0; // 保存ポインタを循環 ChckData = PortData & MskPtn; // 条件検査用データ作成 }while(ChckData != PrePtn); // トリガ前条件成立まで待つ do{ // ----------------トリガ条件の成立待機 ------------------ while(!_T1IF); // 取得タイミングを待つ _T1IF = 0; // PortData = PORTB; // データ読込 AqData[AqPtr++] = PortData; // 保存 if(AqPtr > 1100) AqPtr = 0; // 保存ポインタを循環 ChckData = PortData & MskPtn; // 条件検査用データ作成 }while(ChckData ==PrePtn); // トリガ前条件成立なら繰返 }while(ChckData !=TrgPtn); // トリガ条件一致で抜ける do{ // ------------------- トリガ後保存 ---------------------------- while(!_T1IF); // 取得タイミングを待つ _T1IF = 0; // PortData = PORTB; // データ読込 AqData[AqPtr++] = PortData; // 保存 if(AqPtr > 1100) AqPtr = 0; // 保存ポインタを循環 }while(++RcdNo < AqEnd); // AqSat(取得完了)数まで保存 T1CONbits.TON = 0; // Timer1停止 } /* ******************************************************************** * UARTの初期設定 * 115200bps @ 40MHz * *******************************************************************/ void intl_UART1(void){ // U1BRG = 259; // 9600bps @ 40MHz U1BRG = 21; // 115200bps @ 40MHz U1MODE = 0x8000; // 8bit, No Parity, U1STA = 0x0400; // No Flow Control _PCFG4 = 1; // UART Portをデジタル設定 _PCFG5 = 1; // UART Portをデジタル設定 _U1RXR = 2; // UART1 RX を RP2(RB2 AN4)に設定 _RP3R = 3; // UART1 TX を RP3(RB3 AN5)に設定 __delay_ms(200); // UART安定動作を待つ遅延 } /* ******************************************************************** * UART1 文字列送信 * 文字配列の指定文字数だけ 送信する * *******************************************************************/ void UART_str(char *str, char ptr){ while(ptr--){ // 指示文字数分繰り返す while(U1STAbits.UTXBF); // 送信バッファが空なら U1TXREG = *str++; // 一文字送信 ポインタを進める } } /* ******************************************************************** * UART1 ROM文字列送信 * 指定文字列を送信する * *******************************************************************/ void UART_rom(const char *str){ while(*str){ // 終端の「0」になるまで繰り返す while(U1STAbits.UTXBF); // 送信バッファが空なら U1TXREG = *str++; // 一文字送信 ポインタを進める } } /* ******************************************************************** * Data配列送信 * 配列のデータを送信する 一行50文字+CRLF * adata:Data配列名 ptr:データ数 * ch1_pos;データのあるbit位置 * *******************************************************************/ void outAqData(int *adata, int ptr){ int i = 0; char c; while(ptr--){ // 指示文字数分繰り返す c = *adata++ >> ch1_pos; // データを取り出しポインタを進める c = c & 0xF; // 下位4ビットを取り出す c = c | '@'; // 「@」からの文字コードに変換 while(U1STAbits.UTXBF); // 送信バッファが空なら U1TXREG = c; // 一文字送信 if((++i >= 50) | (ptr == 0)){ // 50文字毎または i = 0; // 指定数送信完了で UART_rom("\r\n"); // CRLFを挿入 } } } /* ******************************************************************** * Uart1 Rx割込み処理 * RxWptr,RxRptr; RxWbuf[20],RxRbuf[20]; * *******************************************************************/ void __attribute__ ((interrupt, no_auto_psv)) _U1RXInterrupt(void) { char RxData; _U1RXIF = 0; if(U1STAbits.OERR){ // 受信エラーなら U1STAbits.OERR = 0; // エラークリア RxWptr = 0; // 既存データはすべて廃棄 }else{ // 正常受信なら RxData = U1RXREG; switch(RxData){ // CRLFを受信したら、 case 0x0A: // それまでの受信データを case 0x0D: // RxRbufに転送する if(RxWptr){ // ただし、CRLFは転送しない memcpy(RxRbuf, RxWbuf, RxWptr); RxRptr = RxWptr; // バッファ転送し受信数保存 RxWptr = 0; // ポインタリセット } break; case '!': // トリガ中止コマンド asm("RESET"); // PICをソフトウエアでリセット break; default: // 一般文字なら RxWbuf[RxWptr++] = RxData; // 受信バッファに保存 if(RxWptr >= 20)RxWptr = 0; // 容量超えはすべて廃棄 break; } } }