/*************************************
* 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;
}
}
}
}