ADコンバータとDTC転送(ソフトウエアトリガ、スキャン、ワンショット変換)で他の端子のアナログデータを読み込む

アナログAN3-AN9の7CHをスキャンモードでDTC転送で読み込んでいます。

メインループで、タイマー1msec割り込みを利用し、2msec毎にADスタート、DTCスタートしております。

AD変換終了割り込みでCHを切替ていますが、CS+のウオッチで変換データbuffer3~9を見ていると、

たまにbuffer3にbuffer4のデータが読み込まれたり(ほかのCHも同じことがおこっている)

しています。

ADスタートかDTC転送のどこを修正したらよいか困っており、ご教授をお願い致します。

 

ソース

メインループ r_main.c

while (1U)
{

---

if(timer_2msec == 0) /****** 2m sec 周期 *****/
{
timer_2msec = 2; 
NOP();
R_ADC_Start(); //A/Dコンバータスタート
R_DTCD0_Start(); // DTC enabled
}

 

割り込み処理 r_cg_adc_user.c

static void __near r_adc_interrupt(void)
{
/* Start user code. Do not edit comment generated here */

R_ADC_Stop(); //ADCS = 0U


if(ad_ch_fg == 0){
buffer3 = (g_ad_value[0U] & 0xFFC0U) >> 6U;
buffer4 = (g_ad_value[1U] & 0xFFC0U) >> 6U;
buffer5 = (g_ad_value[2U] & 0xFFC0U) >> 6U;
buffer6 = (g_ad_value[3U] & 0xFFC0U) >> 6U;

NOP();
ADS = 0x07; // AN7-AN10に切替
NOP();
NOP();
NOP();
R_ADC_Start(); //ADCS = 1U
R_DTCD0_Start(); //DTCスタート
}
else if(ad_ch_fg == 1){
buffer7 = (g_ad_value[0U] & 0xFFC0U) >> 6U;
buffer8 = (g_ad_value[1U] & 0xFFC0U) >> 6U;
buffer9 = (g_ad_value[2U] & 0xFFC0U) >> 6U;
bufferA = (g_ad_value[3U] & 0xFFC0U) >> 6U;

NOP();
ADS = 0x03; // AN3-AN6に切替
NOP();
NOP();
NOP();
ad_fin_fg = 0;
}

ad_ch_fg ^= 0x01;
NOP();

/* End user code. Do not edit comment generated here */
}

 

  • チョコです。
    DTCの再設定はどうされているのでしょうか?
    そもそも,DTCはどんな設定で動作させているかが不明なのですが。

    以上
  • DTCは初期設定のみですが、再設定が必要ですか?

    初期設定は、下記のようにしています。

    #pragma address dtc_vectortable = 0xFFB00U
    uint8_t __near dtc_vectortable[53U];

    #pragma address dtc_controldata_0 = 0xFFB40U
    st_dtc_data __near dtc_controldata_0;


    void R_DTC_Create(void)
    {
    /* Enable input clock supply */
    DTCEN = 1U;
    /* Disable all DTC channels operation */
    DTCEN0 = 0x00U;
    DTCEN1 = 0x00U;
    DTCEN2 = 0x00U;
    DTCEN3 = 0x00U;
    DTCEN4 = 0x00U;
    DTCEN5 = 0x00U;
    DTCEN6 = 0x00U;
    /* Set base address */
    DTCBAR = 0xFBU;
    /* Set DTCD0 */
    dtc_vectortable[9] = 0x40U;
    dtc_controldata_0.dtccr = _01_DTC_TRANSFER_MODE_REPEAT | _40_DTC_DATA_SIZE_16BITS | _00_DTC_REPEAT_AREA_DEST |
    _00_DTC_SOURCE_ADDR_FIXED | _00_DTC_CHAIN_TRANSFER_DISABLE | _20_DTC_REPEAT_INT_ENABLE;
    dtc_controldata_0.dtbls = _01_DTCD0_TRANSFER_BLOCKSIZE;
    dtc_controldata_0.dtcct = _04_DTCD0_TRANSFER_BYTE;
    dtc_controldata_0.dtrld = _04_DTCD0_TRANSFER_BYTE;
    dtc_controldata_0.dtsar = _FF1E_DTCD0_SRC_ADDRESS;
    dtc_controldata_0.dtdar = _F900_DTCD0_DEST_ADDRESS;
    }
  • チョコです。
    リピート転送で,転送先が0xF900(下位8bitが0x00)ならば,再設定は必要ないですね。
    そうなると,ADCの設定が本当にワンショット変換になっているかと,R_ADC_Start();とR_DTCD0_Start();の順番が気になりますね。
  • チョコさん、ご確認ありがとうございます。

    ADCの設定はワンショット変換になっていると思います。
    ADM1 = _00_AD_TRIGGER_SOFTWARE | _20_AD_CONVMODE_ONESELECT;

    R_ADC_Start();とR_DTCD0_Start();の順番、メインループ、割り込み処理とも種々変えてみましたが、変わらずでした。。。
    DTCEN1のレジスタを読み出してウォッチで見ていると、7ビットのキー入力が使っていないのに、起動許可”1”
    になっていますが、何か関係ありますでしょうか?

    ちなみにADCの設定は、下記のようになってます。

    void R_ADC_Create(void)
    {
    ADCEN = 1U; /* supply AD clock */
    ADM0 = _00_AD_ADM0_INITIALVALUE; /* disable AD conversion and clear ADM0 register */
    ADMK = 1U; /* disable INTAD interrupt */
    ADIF = 0U; /* clear INTAD interrupt flag */
    /* Set INTAD low priority */
    ADPR1 = 1U;
    ADPR0 = 1U;
    /* The reset status of ADPC is analog input, so it's unnecessary to set. */
    /* Set ANI0 - ANI9 pin as analog input */
    PM8 |= 0xFFU;
    PM3 |= 0x18U;
    ADM0 = _38_AD_CONVERSION_CLOCK_2 | _00_AD_TIME_MODE_NORMAL_1 | _40_AD_OPERMODE_SCAN;
    ADM1 = _00_AD_TRIGGER_SOFTWARE | _20_AD_CONVMODE_ONESELECT;
    ADM2 = _40_AD_POSITIVE_AVREFP | _20_AD_NEGATIVE_AVREFM | _00_AD_AREA_MODE_1 | _00_AD_RESOLUTION_10BIT;
    ADUL = _FF_AD_ADUL_VALUE;
    ADLL = _00_AD_ADLL_VALUE;
    ADS = _03_AD_INPUT_CHANNEL_3_6;
    ADCE = 1U; /* enable AD comparator */
    }
  • チョコです。
    >DTCEN1のレジスタを読み出してウォッチで見ていると、7ビットのキー入力が使っていないのに、起動許可”1”
    >になっていますが、何か関係ありますでしょうか?
    関係あると思われます。
    キー入力を使っていないとのことですが,"dtc_vectortable[9] = 0x40U;"とキー入力(要因番号9)の設定になっていますね。
    期にはなっていたのですが,DTCの起動要因が53もあるようなデバイスに心当たりがなかったので,そのデバイスでは,要因番号9はA?D変換完了かと勝手に解釈していました。
  • まゆみ さん、こんにちは。NoMaYと申します。

    ちょっと失礼します。ちなみに、お使いのデバイスは何でしょうか?

  • NoMaYさん、こんにちは。
    使っているデバイスはRL78/F15 R5F113LLBです。
  • チョコさん、ご回答ありがとうございます。
    使用しているデバイスは、RL78/F15なのですが、要因番号9はA/D変換ではないでしょうか?
  • チョコです。
    RL78/F15は,ハードウェア マニュアルで確認したところ要因番号9はA/D変換のようですね。
    デバイスがわからなかったので,RL78/G1xでDTC搭載のものをいくつか確認したところ,
    全て要因番号9はキー入力でした。
    ということで,前回のコメントとなりました。
    そうなると,何かがDTCを邪魔しているかもしれません。または,ノイズが影響している?
  • まゆみ さん、こんにちは。チョコさんも、こんにちは。NoMaYです。

    > そうなると,何かがDTCを邪魔しているかもしれません。または,ノイズが影響している?

    デバイスの設定はひとまず問題なさそう、ということなったら、次に気になるのは、デバッガの影響でしょうか、、、 ブレークポイントでブレークさせたことで、割り込み関連のプログラムの動作がおかしくなることは、良くありますので、、、(今まであまり意識していませんでしたが、DTC/DMAも転送を1つずつ進めていく要因はDTC/DMAに入力されている割り込み要求信号ですので、動作がおかしくなることがあっても不思議では無いような気がしてきています、、、)

    それで、「CS+のウオッチで変換データbuffer3~9を見ている」というのは、どのようにして見ているのでしょうか?

    (1) プログラムのどこかにブレークポイントを設定してGo/Breakを繰り返している?
    ⇒ そのブレークポイントでブレークすることでA/D変換終了割り込み要求をDTCが受け付け損ねる状況になる可能性はないですか?

    (2) プログラムを実行させたままリアルタイムRAMモニタ機能でウォッチしている?
    ⇒ デバッガのプロパティでリアルタイムRAMモニタ機能を無効にすると問題の起きる/起きないに変化がありますか?
    ⇒⇒ ただ、アルタイムRAMモニタ機能を無効にするとそもそもプログラムを実行させたままウォッチすることが出来なくなりますので、例えば以下のようにするなどして現象が発生するかどうかを確認してみて頂けませんか?

    ・ AN3-AN6にそれぞれ1V,2V,3V,4Vを入力する (デバイスの動作電圧は5Vだとしていますので3.3Vなら電圧を調整して下さい)
    ・ r_adc_interrupt()で変換値を読み出す時に以下のようなチェックルーチンを入れてNGならそこでブレークするようにする
    (例)

    static void __near r_adc_interrupt(void)
    {
    /* Start user code. Do not edit comment generated here */

        。。。途中省略。。。

        if(ad_ch_fg == 0){
            buffer3 = (g_ad_value[0U] & 0xFFC0U) >> 6U;
            buffer4 = (g_ad_value[1U] & 0xFFC0U) >> 6U;
            buffer5 = (g_ad_value[2U] & 0xFFC0U) >> 6U;
            buffer6 = (g_ad_value[3U] & 0xFFC0U) >> 6U;

            if (buffer3の値が1V前後でない || buffer4の値が2V前後でない || buffer5の値が3V前後でない || buffer6の値が4V前後でない)
            {
                NOP(); /* 読み出し値が異常である */ /* ブレークポイントを設定する */
            }

            。。。途中省略。。。
        }

        。。。途中省略。。。

    /* End user code. Do not edit comment generated here */
    }

    それで、すみません、チョコさんの以下のアドバイスには対処した状態(R_DTCD0_Start();が先でR_ADC_Start();が後)で試して欲しいと考えています。

    > R_ADC_Start();とR_DTCD0_Start();の順番が気になりますね。