● 実験テーマ65

「PIC18F14K50による、AD9834 DDSモジュールの実験その2」
 (ロータリエンコーダ+Step SWによる周波数可変ソフトを作成し実験してみました。)

・以下、この実験の顛末記です。

■ 2015.2.24
  ・実験テーマ64で、ロータリディップSWでの、DDSモジュールの実験は上手く行った。
   そこで、今度は、最小1Hz単位で任意の周波数を設定出来るように、ロータリディップSWを、
   ロータリエンコーダ(RE)に置換えて、同じトレーニング基板で実験をしてみる。

   その可変ステップも、タクトSWを押す毎に、1,10,100,1000,10000,100000,1000000Hz
       の、7種類のステップ周波数を選べるようにした。

   また、REの読込には、PIC18Fの、状態変化割込みを使ってみることにした。
   尚、Step SWは、簡単に、メインループで読込む方法にした。

  ・出力周波数の最大は、10MHzにした。
   サイン出力だけなら、30MHz位までは出せそうなのだが、方形波も同時出力したいので
   10MHzまでとした。
   というのは、どうも、AD9834の、方形波出力(SINROMデータのMSB出力)は、20MHzでは
   そのduty比が、50%一定にはならず、部分的に変化するようである。
   このことは高速オシロを持合せてない自分では確認しようがないが、
   CQ出版のトライアルシリーズ「ディジタル周波数シンセサイザー基板」の本に、波形写真
   と記事が載っていた。

  ・PIC18Fの割込み記述は、今迄の16bit,32bitのとは異なるので、その辺を学習しないといけない。


■ 2015.3.1
  ・ちょとその辺を学習して自分なりにまとめてみた。(ポイントのみ下記しました。)

 ● PIC18に於ける状態変化割込み設定について
   @ I/Oポート設定
     ・RAポート
      RAの全てのピンは、個別に状態割込みピンとして設定できる。
      <マイシステムの例では>
      → IOCA= 0;
         // PORTA(bit5:RA5, bit4:RA4, bit3:RA3, bit1:RA1, bit0:RA0←これらのビットをIOCAビットと呼ぶ)は
         // 状態変化割込ピンとして使わない(禁止) 
         // デフォルトで、0になっているので特に何もしなくてよい。

                 RAポートを割込みに使う場合は、
                 割込みに使うピンの対応する、IOCAビットを、'1'にセットした後に
         INTCONbits.RABIE= 1; を実行する。
        これで初めて、IOCAビット=1のピン状態変化割込みが許可される。
        そして最後に、
        /// 全体の割込みの許可
        INTCONbits.GIE=1;
                      でピン状態が変化すると割込みが掛る。

      ・RBポート
       RBの全てのピンは、個別に状態割込みピンとして設定できる。
      <マイシステムの例ではREを割込みに使うとして>
      → IOCB= 0b00110000;
         // PORTB(bit7:RB7, bit6:RB6, bit5:RB5, bit4:RB4←これらのビットをIOCBビットと呼ぶ)の内、
         // RB4、5のみ状態変化割込ピンとして使う(許可)
                            この後の手順は、RAポートと共通部分になる。

   A 割込み関数の記述
     ・今回は、優先レベルを設定しないで、1レベル割込みで使うので、その例で説明
      (後閑氏のHPから一部抜粋させて頂きました。)

      ///****** 割込み宣言(優先順位を使わない)
      // #pragma interruptは高位割込み処理関数であることを定義
      // 高位割込み処理では、レジスタの退避/復旧にshadow registerを自動的に選択
      // WREG、BSR、STATUSの各レジスタの退避復旧は自動的に行われる。
      // さらに追加レジスタを退避したいときには、save= で指定すれば追加される。
      #pragma interrupt isr // 今回は、save指定は必要ない。

      //***** 割込みベクタへジャンプ命令セット
      #pragma code isrcode = 0x0008
      void isr_direct(void) {
         _asm
                              goto isr
                             _endasm
            }

            //***** 割込み処理関数
            /// 上記定義と同じ名前の関数を用意します。この関数の展開後の最後に自動挿入される
            /// RETFIE命令はFirst Return となり、WREGとBSR、STATUSレジスタは自動復旧される
      /// 関数の直前に #pragma code を置いてメモリエリアを戻しておく
      #pragma code
      void isr(void) // 割り込み関数
      {
         // 割込み処理記述

         INTCONbits.RABIF = 0; // 割込みフラグリセット(これは今回の状態変化割込みフラグ)
      }

  ・REでの割込みで周波数可変する前に、単純に、SW2とSW3を使ったSW割込みのテストプログラムを
   考えてみた。
   SW2(RB7)を、1回押すと、LED点灯
   SW3(RB6)を、1回押すと、LED消灯
   のモーメンタリ(セット・リセット)動作をさせてみる。
   単純な動作なので、SWのチャタリング対策はしてませんが、問題なく動きました。
   チャタリングで割込みが再度入っても、同じ動作をするだけなので、この場合は必要ないです。
   ここにそのテストプログラムをアップします。→ PinChange_Int_TEST.c


■ 2015.3.4
  ・さて本題の、RE+Step SWによる、DDS出力周波数可変プログラムの方だが、
   一応書き上げて、チェックを行った。
   大方、動いてはいるのだが、電源ON時に、Frq表示(出力)が、いきなり、1ステップ動いいてしまう
   ことがある。
   つまりは、REを回してないのに、電源ON時に、状態変化割込みが入ってしまっている。

   どうも今回、試しに、ノンクリックタイプの、REを使ったせいか?
   電源ON前に、A相、B相の接点がどの位置(状態)になっているかで、この問題が起きているよう
   である。
   その位置によっては、全く問題なくなる。

  <調査>
   ※ 電源ON時の、RE接点状態によって駄目になることが判明!!
      電源ON時、OKな時の、A,B信号レベルをテスターで確認すると、0VのLoレベル(両接点共クローズ)
      NGな時は、約5VのHiレベル(両接点共オープン)
      現状、A相の立上り検知で割込みが掛るようにプログラムは書かれているので、
      電源ON前に、両接点共オープン状態から電源を立ち上げると当然、A相が立上るので、それで
      割込みが入ってしまうわけだ!!

  <対策>
   ※ A相の立上りでなく、A相の立下りを基準に、B相のレベルを読込んで回転方向を判断するよう
      にプログラムを修正すれば、この問題は解決するはずである。
      このように修正したら、問題は解決した!!


<最終回路図>
 ・こちらから、どうぞ→ 「PIC18F_DDSモジュール実験回路」

<最終ソース>
 ・こちらから、どうぞ→ 「AD9834_Test_2.c」


← 実験テーマ1に戻る   TOP PAGEに戻る   実験テーマ66へ →