UMEHOSHI ITA TOP PAGE    COMPUTER SHIEN LAB

[UMEHOSHI ITA]の制御で使っているIC「PIC32MX270F256B-I/SO」のフラッシュメモリには、テスト用プログラムが書き込まれいています。
以降では、このプログラムを「テスト・ウメ・フラッシュ」と呼ぶことにして解説します。
また、「テスト・ウメ・フラッシュ」を利用したユーザー用のプログラムを 「ウメ・エディットプログラム」と呼ぶことにします。
「ウメ・エディットプログラム」の開発では「umehoshiEditツール」が必要で、 その取得や最初の操作情報は、こちらを参照してください。

このページで作ったHEXファイル(テスト・ウメ・フラッシュ)を、Pythonで[UMEHOSHI ITA]へ転送して動作させる例は、 ここに 示します。

ADCデフォルトプログラムを書き換える。 

ADCデフォルトの割り込みを自前の処理に置き換える考え方は、 ADCデフォルト処理の置き換え例のページで示しています。
この ADCデフォルト処理の置き換え例で示した内容は、 下記のようにAN0とAN1の2つの入力をADCに交互に入力するイメージで、 内部の「テスト・ウメ・フラッシュ」に記憶されているADCと、Timer3の割り込み処理と同等の処理を 定義して、それで置き換える方法を示しました。

この方法では、AN0またはAN1の一方だけをUSB経由で取得する場合でも、2つの交互サンプリングが一つの周期になり 余計な処理を必要としています。

そこで以下では次のイメージのように、AN1の一方だけAD変換して、それだけをUSB経由で取得するようにする例を示します。
交互サンプリングではなく、特定の入力のサンプリングだけを行う方法です。

上記赤のマークでADCの割り込みが行われるように、 AD1CON2bits.SMPI = 0; と割り込みあたりサンプリング設定を1つに変更しています。
上記の赤の部分がサンプリング周期で、 そのサンプリングレートは、8KHzとして、無限ループ録音にするプログラムです。
以下では、既存のADCの割り込み処理とTimer3の割り込みそれぞれを、ここで定義したadc_umeFunc1_1関数とadc_usb_out関数に 置き換えて実現しています。

#include <xc.h> // ADC_8K_AN1_4B.c  8KHx AN1 4block 
#include "common.h"

#define MY_ADC_ERR_OVERFLOW  0x0001 // ADC取得データの送信が間に合わなないエラー

#define AdrStart	0x80005000
__attribute__((address( AdrStart  ))) void start (void);

#define AdrStop	0x80006000
__attribute__((address( AdrStop))) void stop (void);

void adc_umeFunc1_1(struct ADC_BUFF *p_buff);//自前のADC割り込みルーチン
void adc_usb_out(struct ADC_BUFF *p_buff);//自前のUSBに出力するTimer3の割り込みルーチン

void start()
{
    _RB15 = ! _RB15 ;// LEDの点灯を反転
    _HANDLES[_IDX_ADC_1_FUNC]=  (void *)adc_umeFunc1_1;//ADCの割り込み(バッファに記憶)を自作の処理に置き換える
    _HANDLES[_IDX_TIMER_3_FUNC] = (void *)adc_usb_out;//Timer3割り込み(バッファの出力)を自作の処理に置き換える

    PR3=4999; // 8KHzサンプリン用設定値:(1/8e3)/(1/40e6)-1 = 4999
    // AD1CON2bits.SMPI = 0 なので1チャンネルだけをADCの対象にしているのための設定

    _set_adc_mode(2,0); // チャンネル指定と、bin/textの選択
    _set_adc_exe(4 , 1);// ブロックのサンプリングを繰り返し数とループフラグ指定

    T3CONbits.ON = 0; // timer3停止
    AD1CON2bits.ALTS = 0; // MUX AおよびMUX B入力マルチプレクサ設定を交互に使わない
    AD1CON2bits.SMPI = 0; // 割り込みあたりサンプリング
    AD1CHSbits.CH0SA = 1; // MUX A チャンネル 0 の正極性入力に AN1 を選択する
    // 上記設定を0にして、下記設定を1すると AN0を選択したことになります。
    AD1CHSbits.CH0SB = 0; // MUX B チャンネル 0 の正極性入力に AN0 を選択する

    T3CONbits.ON = 1; // timer3停止
}

void stop()
{
    _set_adc_exe(4 , 0);// 現ブロック送信で終了
}

// ADCの新しい割り込み処理
void adc_umeFunc1_1(struct ADC_BUFF *p_buff) {
    static int no_send_count = 0; // 送信できない場合のデクリメント
    static uint16_t valAN0, valAN1;

    // 割り込み中で、下記バッファを必ず操作しなければならない。
    // (そうしないと、割込みが永続(persistent)のため、連続発生の不具合が生じる。)
    // バッファへの格納先を確認(ビットチェック格納先を判定)
    int idx = (AD1CON2 & _AD1CON2_BUFS_MASK) != 0;
    if (idx) {//1:ADC はバッファ0x8〜0xF に書き込み中(ユーザは0x0〜0x7 にアクセス可能)
        valAN0 = ADC1BUF0; //MUX A のAD変換値
    } else { //0: ADC はバッファ0x0〜0x7 に書き込み中(ユーザは0x8〜0xF にアクセス可能)   
        valAN0 = ADC1BUF8; //MUX A のAD変換値
    }

    if (p_buff->index_adc_sample >= ADC_BUFF_SIZE) {
        if (p_buff->index_adc_out_block != ADC_OUT_NONE) {
            // エラーのサンプリング停止(メモリオーバー USB出力が間に合わない).
            no_send_count--;
            goto end_proc; // 下記のサンプリングをしない
        }
        // オルタネイト・バッファブが一杯なので、切り替える 
        p_buff->index_adc_sample = 0;
        int next_index_block_sample = p_buff->index_adc_block_sample;
        next_index_block_sample++;
        if (next_index_block_sample == 2) {
            next_index_block_sample = 0;
        }
        p_buff->index_adc_out_block = p_buff->index_adc_block_sample;
        p_buff->index_adc_block_sample = next_index_block_sample;
    }

    if (no_send_count != 0) {// USB出力が間に合わないくて、出力されなかったデータ数?
        valAN0 = valAN1 = no_send_count; //出力できなかった数を(負の数)セット
        no_send_count = 0;
    }
    p_buff->adc_buffer0[p_buff->index_adc_block_sample][p_buff->index_adc_sample] = valAN0;
    p_buff->index_adc_sample++;

end_proc:
    IFS0CLR = _IFS0_AD1IF_MASK; // Clear ADC interrupt flag  
}

int usb_receiver_disable_flag = 0;//受信を無効にするフラグ

int my_adc_set_err = 0;

// Timer3の新しい割り込み処理
void adc_usb_out(struct ADC_BUFF *p_buff) {
    static int flag_start_ADC = 1;
    static int flag_end_ADC = 0;
    static int i, idx_block, i_pos;
    static int16_t data;

    static int tim3_skip_count=0;// timer3が早すぎる場合の送出調整用★
    static int skip_timing =0;//★
    skip_timing = PR3;

    if( skip_timing < 100) { // 1つのサンプル周期が約400KHz以上?★
        skip_timing = 100 - skip_timing;
        tim3_skip_count++;
        if(tim3_skip_count < skip_timing ) {
            IFS0CLR = _IFS0_T3IF_MASK; // 次の割り込みを可能にする
            return;
        }
        tim3_skip_count =0;
     }//★

    struct ADC_CTRL *p_ctrl = p_buff->p_ctrl;

    if (p_buff->index_adc_out_block == ADC_OUT_NONE) {// USB送信するデータがない? 
        IFS0CLR = _IFS0_T3IF_MASK; // Clear the timer interrupt status flag
        return;
    }
    int size = _get_capacity();
    if (size < 50) {
        IFS0CLR = _IFS0_T3IF_MASK; // Clear the timer interrupt status flag
        return; //USB出力バッファに余裕がないので、次の呼び出しにする。  
    }
    if (_request_acc_outbuff(_ID_ACCESS_T3_TASK) == 0) {
        IFS0CLR = _IFS0_T3IF_MASK; // Clear the timer interrupt status flag
        return;   //USB出力権限取得失敗で、、次の呼び出しにする。
    }

    // ADC DATA 送出.============>USB
    int text_mode = p_ctrl->adc_out_usb == (void (*)()) _HANDLES[_IDX_API_SEND_HEX_LOW]; 
    if (flag_start_ADC) {// ----------送出ブロック開始----------------
        p_buff->adc_buff_data_numb = ADC_BUFF_SIZE;
        ((void (*)(struct ADC_BUFF*))_UME_ENCODE_ADC_BUFF)(p_buff);

        //_send_string("\r\nADC_START0\r\n");
        _send_string("\r\nADC_START1\r\n"); // USB応答文字列で、「umehoshiEdit」ツールでは下にプロット(ADC_START0なら上にプロット)
        if (text_mode == 1)_send_char('T'); //TextMode
        _send_hex_low(p_ctrl->count_end_ADC); //送信データ数

        _send_string("\r\n");
        usb_receiver_disable_flag = 1; //USB受信不可
        flag_start_ADC = 0; //開始処理を終えた〇
        flag_end_ADC = 0;

    } else if (p_ctrl->counter_ADC >= p_ctrl->count_end_ADC) {
        // ----------送出ブロック終了の処理------
        if (!flag_end_ADC) {
            flag_end_ADC = 0;
            flag_start_ADC = 1;
            _send_string("ADC_END\r\n");
            usb_receiver_disable_flag = 0; //USB受信不可解除
            if (p_ctrl->set_sequence_flag) {// set_ADCの登録がある時
                p_ctrl->set_sequence_flag = 0;
                if (p_ctrl->block_size_ADC != 0) {// 継続データ指示がある ?
                    // 目標サンプル数 設定があればセット
                    p_ctrl->count_end_ADC = p_buff->adc_buff_data_numb * p_ctrl->block_size_ADC;
                    if (p_ctrl->out_channel_bits == 0x3) {
                        p_ctrl->count_end_ADC <<= 1;  //AN0,AN1 の2つ分
                    }
                } else {
                    T3CONbits.ON = 0; // timer3停止
                    p_buff->index_adc_out_block = ADC_OUT_NONE;
                }
            }
            if (!p_ctrl->loop_flag_ADC) {//ループしない?
                T3CONbits.ON = 0; // timer3割込みオフ.
                p_ctrl->block_size_ADC = 0;
                p_buff->index_adc_out_block = ADC_OUT_NONE;
            }
            p_ctrl->counter_ADC = 0;
        }

    } else {// ------------- ADC データブロック送出中 -------------------------
        for (i = 0; i < 2; i++) {// ADCの値の1ワードを2つ分送出する。
            idx_block = p_buff->index_adc_out_block;
            i_pos = p_buff->index_adc_out_pos;

            data = p_buff->adc_buffer0[idx_block][i_pos]; //出力対象
            //data = p_buff->adc_buffer1[idx_block][i_pos]; //出力対象
            if (data < 0) my_adc_set_err=MY_ADC_ERR_OVERFLOW;
            p_ctrl->adc_out_usb(data);// USBへデータを出力
            p_ctrl->counter_ADC++;

            ++p_buff->index_adc_out_pos;
            if (p_ctrl->counter_ADC % 16 == 0 && text_mode == 1) {
                // TEXT MODE 出力の場合だけ出力(バイナリ時は出力しない)
                _send_string("\r\n");
            }
            if (p_buff->index_adc_out_pos >= p_buff->adc_buff_data_numb) {
                p_buff->index_adc_out_pos = 0;
                p_buff->index_adc_out_block = ADC_OUT_NONE; // CHUNKブロックのUSB出力終了.
            }
        }
    }
    _release_acc_outbuff(_ID_ACCESS_T3_TASK);
    IFS0CLR = _IFS0_T3IF_MASK; // Clear the timer interrupt status flag
}

AN0とAN1の交互サンプリングを使わないので、サンプリング周期のPR3設定値の計算方法が変わります。(2で割る必要がない)
また、 AD1CHSbits.CH0SA = 1; で MUX A チャンネル 0 の正極性入力に AN1 を選択して、その入力に固定しています。
そして、この入力はADC割り込みで、p_buff->adc_buffer0にだけ記憶しています。(交互サンプリング時は、adc_buffer1も使っていました。)
同様にTimer3割り込みで、p_buff->adc_buffer0の内容だけをUSBで出力します。
この実行で得られたプロット例と、Communicationタブ内容を下記に示します。

START:80005000

ADC_START1
1000
 ADC_END

このページで作ったHEXファイル(テスト・ウメ・フラッシュ)を、Pythonで[UMEHOSHI ITA]へ転送して動作させる例は、 ここに 示します。