2017年7月
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          

Amazonウィジェット

  • miniPC
  • 最近買った本
  • Raspberry Pi
  • クアッドコプター
  • 書籍ランキング

AdSense

  • 広告
無料ブログはココログ

« 2016年12月 | トップページ

2017年7月

2017年7月15日 (土)

PIC32MX220のADコンバータで、複数chをスキャンモードで使う

PIC32MX220は、秋月電子で売っている32bitのPICマイコン。
このPICのADコンバータは、1Mspsというとても高速な(PIC16Fシリーズから入った自分からみて)ものを搭載している。これを使ってアナログ入力数本を、自動で順番にAD変換できるようにしてみた。

とりあえずADCが動いているかを確認する手段を用意するため、シリアルの送信から手をつけた。
ここのブログを参考にさせてもらった。
http://miu-robo.blogspot.jp/2012/09/pic32mx220f032buartprintf.html

ソースを見ていると、
ペリフェラルのヘッダファイルの使い方がなんとなくわかる。

PIC32インストールフォルダを見て、ペリフェラルのヘッダファイルを探す。
adc10.hというのがADC用のファイルになっている。



適宜MicrochipJapanにある日本語リファレンスを見る。
シングルエンド入力で、スキャンモード(chを順番に自動で変換していく)を使うときは、
MUXのAだけを使うようにする。



<ちょっとマイコン知識>
マイコンのCコンパイラでビットをセットしたいときは、大抵ヘッダファイルにビットやレジスタ名を#defineしたものが記述されているのでそれらを使う。

ビットを立ててほしい#define定数をOR演算子でつなげて書いて、それを何か新しい#define定数に入れる。すると、セットしたいビットだけが1になった定数が完成する。

下記の例で行くと、ADC_MODULE_OFF,ADC_FORMAT_INTG16, ・・・ ADC_SAMP_ONのビットを立てて、PARAM1というのに入れたことになる。

#define PARAM1 ADC_MODULE_OFF | ADC_FORMAT_INTG16 | ADC_CLK_MANUAL | ADC_AUTO_SAMPLING_ON |ADC_SAMP_ON

そしてOpenADC10に、それぞれのレジスタに入れるべきビット列を書いた#defineの定数を渡すと、あとはヘッダファイルに書かれたマクロがPICの持つレジスタ、ビットに直して書き込んでくれるという仕組み。

OpenADC10(AD1CON1R, AD1CON2R, AD1CON3R, AD1PCFGR, AD1CSSLR);

ヘッダファイルを読むのが面倒だからとPICの仕様書に書いてあるレジスタ名を使って、

AD1CON1 = 0x020F;
などのように直に書いても構わないのだが、それだと各ビットが何を意味していたか後でわからなくなるというデメリットがある。
<ちょっとマイコン知識 おわり>


ピンは4,5,6ピンが空いているので、AN2,3,4を使うことにした。

SetChanADC10( ADC_CH0_NEG_SAMPLEA_NVREF | ADC_CH0_POS_SAMPLEA_AN2 | ADC_CH0_POS_SAMPLEA_AN3 | ADC_CH0_POS_SAMPLEA_AN4 );

あとは変換開始してループするだけ。
    while(1)
    {
        ConvertADC10();                // 変換開始
        while(BusyADC10());            // 変換完了待ち(1チャネル分)

        int i;
        for(i=0;i<3;i++){
            Result[i] = ReadADC10(i);            // 変換結果読み出し
            printf("%4u", Result[i]);

        }
        printf("\r\n");
    }

ReadADC10(int offset)
この関数にバッファ0からのオフセットを入れれば、

chごとの変換結果が読める。バッファは16個あり、指定した変換モードによってバッファの使われ方が変化する。同じchを3回と指定したら、バッファには3回測定した結果が順番に入るし、5chをスキャンするように指定すれば、バッファ0から4まで順番に各AN入力の変換結果が入る。
#define AD1CSSLR (0xFFFF ^ (SKIP_SCAN_AN2 | SKIP_SCAN_AN3 | SKIP_SCAN_AN4))
スキャンするときにスキップするchの指定をするレジスタ。
SKIPに指定したポートはスキャンするときに読まなくなる。
上記ソースの例では、XOR演算子を使っているので、AN2,3,4だけがスキップ対象から除外される。



最初に動かしたときは、全chの変換結果が2とか3しか出力されず、入力信号としてつないだ半固定抵抗をいくら動かしても変化しなかった。
ANピンを一個ずつ読ませているときはなんとも無かったのだが、スキャンモードにするとちっとも動かない。

#define AD1CON3_REG ADC_SAMPLE_TIME_3 | ADC_CONV_CLK_SYSTEM | ADC_CONV_CLK_6Tcy

原因は、
AD1CON3に設定している、ADC_SAMPLE_TIME_NとかADC_CONV_CLK_NTcyだった。
これらはchの切り替えタイミングやらを制御していて、スキャンモードで時間を短く設定しすぎると、AD変換している途中のピンの信号を放置して次のchに切り替えてしまう。
つまり切り替えタイミングが速すぎになっていたのだ。

ch1個だけなら、ADCの切り替えタイミングがどれだけ短くても、
変換スタートまでにprintfやらなにやらを挟んでいれば問題なく変換できる。
このため、変換タイミングの設定の間違いはわからないまま動作してしまう。
ch1個が動いた設定がそのままマルチchにしたときも動くとは限らない。

<想>
しばらくPICを触らない間に、Cコンパイラも標準で使えるようになった。アセンブラから入門した自分としてはちょっと寂しいけれど、その分面白い機能がモリモリと搭載されるようになった。

やはりPICはユーザーが多いし、日本語の情報も多いし、詳しい本も出ているので割ととっつきやすい。

« 2016年12月 | トップページ