UMEHOSHI ITA TOP PAGE COMPUTER SHIEN LAB
[UMEHOSHI ITA]の制御で使っているIC「PIC32MX270F256B-I/SO」のフラッシュメモリには、テスト用プログラムが書き込まれいています。
以降では、このプログラムを「テスト・ウメ・フラッシュ」と呼ぶことにして解説します。
また、「テスト・ウメ・フラッシュ」を利用したユーザー用のプログラムを
「ウメ・エディットプログラム」と呼ぶことにします。
「ウメ・エディットプログラム」の開発では「umehoshiEditツール」が必要で、
その取得や最初の操作情報は、こちらを参照してください。
このページで作ったHEXファイル(テスト・ウメ・フラッシュ)を、Pythonで[UMEHOSHI ITA]へ転送して動作させる例は、 ここに 示します。
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]へ転送して動作させる例は、 ここに 示します。