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]へ転送して動作させる例は、 ここに 示します。