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

 

Parents
  • まゆみ さん、こんにちは。チョコさんも、こんにちは。NoMaYです。

    RL78/G14で似た感じのプロジェクトを作ってGo/Break/Stepとかさせていて思い浮かんだのですが、A/Dとタイマの割り込み以外にも割り込みは動いているとは思っているのですが、他の割り込みの影響で、「A/Dスキャン変換のDTC転送リピートモード割り込み要求」のCPU受け付けタイミングがミリ秒オーダー(かつ、不運にも、絶妙なタイミング)で遅延したりしていないでしょうか?例えば、試しに以下のようなソースにするとどうなるでしょうか?(他にも気になる点を2つほどコメントに書き込んでいます。)

        timer_2msec = 0;
        ad_fin_fg = 0;
        ad_ch_fg = 0;
        while (1U)
        {
            // タイマ割り込み周期は ちゃんと 1m sec か?
            // 以下の判定処理は 200usec に 1回 程度は確実に行われるか?
            if(timer_2msec == 0) /****** 2m sec 周期 *****/
            {
                if (ad_fin_fg == 0) // A/Dスキャン変換完了済み
                {
                    timer_2msec = 2;
                    ad_fin_fg = 1;

                    NOP();
                    R_DTCD0_Start(); // DTC enabled
                    R_ADC_Start(); // A/Dコンバータスタート
                }
                else // 未完(DTC転送リピートモード割り込みが m sec オーダーで保留された?)
                {
                    timer_2msec = 1; // もう 1m sec 待つ(それでも未完なら更に待つ)
                }
            }
        }

    気になったのは、その様な状況ですと、以下のR_ADC_Stop();が何か悪影響を与えるのではないかと思ったのです。(メインでR_ADC_Start()したA/Dスキャン変換を、途中で、受け付けが遅延した割り込み内でR_ADC_Stop()してしまっていないだろうか?)

    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_DTCD0_Start(); //DTCスタート
            R_ADC_Start(); //ADCS = 1U
        }
        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 */
    }

    また、この話は、以下の話とも関係があるかも知れません。

    > ・メインルーチンの2msタイマのところ(DTCスタート、ADCスタートの前)にブレークポイントを設定してGo/Breakを繰り返すと、 AN3-AN6にそれぞれ100、1023、200、300を入力した状態 で、異常な数値は表示されないことを確認しました。
    > (下位の数ビットは振れているので、データは更新されていると思います、例えばAN3が、100とか101が表示される)

    [追記]

    すみません、1つ書き忘れました。AN3~AN10のA/Dスキャン変換では、AN3-AN6の組とAN7-AN10の組とで、合計2回の「A/Dスキャン変換のDTC転送リピートモード割り込み要求」が発生しますが、シミュレータで試していると、各組のA/Dスキャン変換には150usecほどの時間が掛かるようで、1回目の割り込みと2回目の割り込みの間には少なくとも150usecほどの間が開くのですが、1回目の割り込みの受け付けが2msec弱ほど遅延した後、2回目の割り込みの受け付けが2msecをごくわずかオーバーしてしまった、というような状況が頭に思い浮かびました。

  • NoMaYさん、こんにちは。チョコさんも、こんにちは。ご回答ありがとうございます。

    下記のソースで確認してみました。

      if(timer_2msec == 0) /****** 2m sec 周期 *****/
    {
    NOP();
    P9_bit.no0 ^= 1;
    if (ad_fin_fg == 0)    // A/Dスキャン変換完了済み
    {
       timer_2msec = 2;
       ad_fin_fg = 1;
       NOP();
       R_DTCD0_Start();  // DTC enabled
       R_ADC_Start();   // A/Dコンバータスタート
    test16++;
    }
     else // 未完(DTC転送リピートモード割り込みが m sec オーダーで保留された?)
      {
      timer_2msec = 1; // もう 1m sec 待つ
    }

    この場合、ad_fin_fgが0にならなくなり、AD変換が止まってしまいました。
    test16というカウンタ値が30とかの数値で止まって(毎回同じカウントではない)しまいます。
    ブレークしているわけではなく、メインループの他の処理は走ってます。

    タイマ割り込み周期については、2msタイマのところでポートP90を反転して、オシロで波形を確認し、
    2msであることを確認しました。他の割り込みの影響?で数10μsは、ずれたりします。

    if (ad_fin_fg == 0)    // A/Dスキャン変換完了済み
    {・・・・・
    の条件を追加すると、なぜかad_fin_fg が0にならないことがあるので、
    割り込み処理の最初、R_ADC_Stop();が影響しているのでしょうか・・?
    もう少し確認してみます。
Reply
  • NoMaYさん、こんにちは。チョコさんも、こんにちは。ご回答ありがとうございます。

    下記のソースで確認してみました。

      if(timer_2msec == 0) /****** 2m sec 周期 *****/
    {
    NOP();
    P9_bit.no0 ^= 1;
    if (ad_fin_fg == 0)    // A/Dスキャン変換完了済み
    {
       timer_2msec = 2;
       ad_fin_fg = 1;
       NOP();
       R_DTCD0_Start();  // DTC enabled
       R_ADC_Start();   // A/Dコンバータスタート
    test16++;
    }
     else // 未完(DTC転送リピートモード割り込みが m sec オーダーで保留された?)
      {
      timer_2msec = 1; // もう 1m sec 待つ
    }

    この場合、ad_fin_fgが0にならなくなり、AD変換が止まってしまいました。
    test16というカウンタ値が30とかの数値で止まって(毎回同じカウントではない)しまいます。
    ブレークしているわけではなく、メインループの他の処理は走ってます。

    タイマ割り込み周期については、2msタイマのところでポートP90を反転して、オシロで波形を確認し、
    2msであることを確認しました。他の割り込みの影響?で数10μsは、ずれたりします。

    if (ad_fin_fg == 0)    // A/Dスキャン変換完了済み
    {・・・・・
    の条件を追加すると、なぜかad_fin_fg が0にならないことがあるので、
    割り込み処理の最初、R_ADC_Stop();が影響しているのでしょうか・・?
    もう少し確認してみます。
Children
No Data