« 78Kマイコンによる7セグLED温度計(1/2) | メイン | 78Kマイコンによる7セグLED温度計(2/2) »

HC08マイコンの使い方QY4A編 -
《45》QY4A内蔵A-D変換器(2)


 ADSCR, ADRH, ADRL 各レジスタの説明をしました。 今回は ADCLK の説明をした後、HC08スターター・ボードを使って A-D変換の実験を行います。
 A-D変換モジュールのブロック図を再掲します。 説明し忘れていましたが、このモジュールの名称は ADC10 といいます(QC16 に内蔵されているものと同じ)。 なお、Aの付かない初期型 QY4 の A-D変換モジュールはこれとは別物で 8ビット・モード専用です。 ややこしいことに、QY8 には A が付かないのですが QB8 の仲間なので、この ADC10 モジュールを内蔵しています。
 

block_adc10.gif

A-D変換モジュールのブロック図(クリックで拡大)
黄色で示した部分がソフトウェアで読み書きするレジスタ

 
・ ADHWT(A-D外部ハードウェア・トリガ) は QY4A や QC16 には存在しない。
・ AD0 から ADn は、QY4A の場合 AD0 から AD5 の 6本。
・ 基準電圧 VREFH は VDD に内部接続済み。 VREFL は VSS に内部接続済み。
SAR(successive approximation register)コンバータは逐次比較型変換器のこと。
・ バス・クロックは CPUコアに与えられるクロックと同一(3.2MHz など)。
・ 代替クロック源はバス・クロックの 4倍の周波数のクロック(12.8MHz など)。
 

ADC10クロック・レジスタ(ADCLK)
 

qy4a_register_adclk.gif  このレジスタは、A-D変換モジュールのクロック周波数と動作モードを設定します。
 
・ ADLPC ADC10低電力設定ビット ADC10 Low-Power Configuration Bit
ADLPC は逐次比較変換器の速度と消費電力を制御するビットで、高速変換が不要な場合に消費電力を低減するために使います。
 1 = 最大クロック速度を抑えて消費電力を低減 (*1)
 0 = 高速設定

・ ADIV1~ADIV0 ADC10クロック分周ビット ADC10 Clock Divider Bits
 ブロック図の 「クロック分周」 は 分周器 と呼ばれるものです。 右側の台形で示されたセレクタの出力が、分周器の入力になっています。 分周器は通常、入力された信号の何分の一かの周波数の信号を出力します。 その出力が A-D変換モジュールの内部クロック(ADCK) になっています。 ADIV1 と ADIV0 は分周器の分周比を選択します。 下表にクロック分周の設定を示します。
例として入力クロックが 3.2MHz であれば、00b のとき 3.2MHz、 10b のとき 0.8MHz が出力されます。

qy4a_table_adiv.gif

 CodeWarrior の C言語のヘッダでは、この二つのビットを別個にでもまとめてでも扱えるように配慮されています。 例として書き方を示しておきます。 まず一つ目は、
  ADCLK_ADIV1 = 1;
  ADCLK_ADIV0 = 0;
 これで Input clock ÷ 4 が選択されます。 もう一つの方法は、
  ADCLK_ADIV = 2;
 これでも Input clock ÷ 4 が選択されます。 設定値が Divide Ratio の欄とごっちゃにならないよう気を付けてください。

・ ADICLK 入力クロック選択ビット Input Clock Select Bit
このビットは ACLKEN が 0 のときのみ意味を持ちます。 ADICLK は分周器の入力クロック源として、バス・クロックまたは代替クロック源のどちらかを選択します。
 1 = バス・クロックを選択
 0 = 代替クロック源を選択

・ MODE1~MODE0 10ビット/ 8ビット・モード選択 10- or 8-Bit Mode Selection
 これらのビットは、10ビットまたは8ビットの処理を選択します。 逐次比較変換の結果は、この選択に基づいて8ビット値または10ビット値になります。
  00b = 8ビット・モード
  01b = 10ビット・モード
  10b = 予約済み
  11b = 禁止(ハードウェア・トリガがないため)

 「10ビット/ 8ビット・モード選択」 も ADIV と同様の書き方ができます。
  ADCLK_MODE1 = 0;
  ADCLK_MODE0 = 1;
 または、
  ADCLK_MODE = 1;
 この場合はどちらも 10ビット・モードになります。

・ ADLSMP 長期サンプリング時間設定 Long Sample Time Configuration
 ADLSMP は、A-D変換器の入力電圧取り込み時間を ADCK クロックの何サイクルぶんにするかを決定します。 外部に接続された回路のインピーダンス(抵抗のようなもの)が大きいときは、取り込み時間を長くすることによってより正確にサンプリングすることができます。 また、外部回路のインピーダンスが小さいときは、取り込み時間を短くすることで A-D変換を高速に実行することができます。 連続変換モードを使うとき、高速な変換が必要ない場合は長期サンプリング時間を選択して全体の消費電力を低減することができます。
 1 = 長期サンプリング時間(23.5サイクル)
 0 = 短期サンプリング時間(3.5サイクル)

・ ACLKEN 非同期クロック源イネーブル Asynchronous Clock Source Enable
 ACLKEN を 1にすると、ブロック図の 「ASYNCクロック・ジェネレータ(非同期クロック源)」 が有効になります(実際は非同期クロック源は変換の間だけ動作して、変換完了時には停止する)。 非同期クロック源はマイコンがストップ・モードのときも動作することができます。
 ACLKEN を 1 にすると、分周器の入力として自動的に非同期クロック信号(ACLK)が選択されます。
 1 = 非同期クロック源を有効にし、入力クロック源として ACLK を選択する
 0 = 非同期クロック源を無効にし、入力クロック源を ADICLK で指定する

【 注意事項 】
・ 選択された入力クロックを分周した内部クロック(ADCK)の周波数は、下記の範囲に納まるように設定してください。

    0.4 MHz ~ 2 MHz (ADLPC = 0 のとき)
    0.4 MHz ~ 1 MHz (ADLPC = 1 のとき)

なお、非同期クロック源は ADLPC が 0 のとき 1MHz ~ 2MHz の範囲で発振し、ADLPC が 1 のとき 0.5MHz ~ 1MHz の範囲で発振します。

・ ADLSMP = 0 のとき、バス・クロック周波数が ADCK 周波数より低い場合は、連続変換モードを選択すると正確なサンプリングのための時間が確保できません。 ADLSMP = 1 のとき、バス・クロック周波数が ADCK 周波数の 1/11 より低い場合は、連続変換モードを選択すると正確なサンプリングのための時間が確保できません。

・ 初期化の際は ADCLK, ADSCR の順に設定することを推奨します。

 アナログ・ディジタル・コンバータに関するレジスタの説明は以上です。 変換時間の計算や変換性能に関することはここでは取り上げませんので、必要に応じてデータシートを参照してください。

 
◆ HC08スタータ・ボードで A-D変換器を 使ってみる
 HC08スタータ・ボードだけで手軽にできる A-D変換器の実験を紹介します。

【動作仕様】
VR1 を回して A-D変換値を変化させる。
PUSH SW を押すと、そのときのA-D変換値を記憶値に記憶する。
A-D変換値が記憶値より大きいとき LED を点灯させる。
A-D変換値が記憶値より小さいとき LED を消灯させる。

(補足仕様)
記憶値の初期値は実効フルスケールの半分とする。
A-D変換値のバラつきを抑えるため、平均処理を施す。
チラつきを抑えるため点灯⇔消灯切り替えにはヒステリシスをもたせる。
VR1 を左いっぱいに回したときは LED を消灯させる。
VR1 を右いっぱいに回したときは LED を点灯させる。

 入出力の端子としては、下記を利用します。 HC08スタータ・ボードの回路図は 第18回 に掲載しています。

  PUSH SW ・・・・・ PTA3
  LED     ・・・・・ PTA1
  VR1     ・・・・・ AD2(PTA4)

 A-D変換器に関する初期設定は、次のようにしました。

    ADCLK = 0x36;       // 3.2÷2=1.6MHz、10ビット、長期
    ADSCR = 0x1F;       // 単独変換、停止中

 もちろん 8ビット・モード、短期サンプリングでもよかったのですが、それ以外の設定も簡単にできますよ、というところをお見せする意図があります。

 長くなりますが、メイン関数をお見せします。

#define PORT_SW         ( PTA_PTA3 )
#define PORT_LED        ( PTA_PTA1 )
#define ADCH_VR         ( 2 )       // AD2(PTA4)
#define SW_ON           ( 0 )
#define SW_OFF          ( 1 )
#define LED_ON          ( 0 )
#define LED_OFF         ( 1 )
#define ADR_MAX         ( 0x3FF )
#define AVERAGE_NUM     ( 64 )      // 64以下にすること
#define DEADBAND        ( 32 )      // DEADBAND > HYSTERESIS
#define HYSTERESIS      ( 16 )

void main( void ){
    unsigned char cnt;
    unsigned int work, memory = ( ADR_MAX / 2 );
   
    init_hardware( );
    init_PORT( );
    init_ADC( );

    for( ; ; ){
        work = 0;
        for ( cnt = 0 ; cnt < AVERAGE_NUM ; cnt++ ){
            ADSCR_ADCH = ADCH_VR;   // A-D開始
            while ( !ADSCR_COCO );  // A-D完了待ち
            work += ADR;            // 取り込み
        }
        work /= AVERAGE_NUM;
       
        if ( PORT_LED == LED_OFF ){
            if ( ( memory + HYSTERESIS ) <= work ){
                PORT_LED = LED_ON;
            }
        } else {
            if ( ( memory - HYSTERESIS ) >= work ){
                PORT_LED = LED_OFF;
            }
        }
       
        if ( PORT_SW == SW_ON ){
            if ( work > ( ADR_MAX - DEADBAND ) ){
                memory = ( ADR_MAX - DEADBAND );
            } else if ( work < DEADBAND ){
                memory = DEADBAND;
            } else {
                memory = work;
            }
        }
    }
}

 A-D変換のところだけ説明しておきます。

・ A-D変換の開始は ADSCR_ADCH に変換したい番号を書き込むことによって指示します (ただし 0x1F を書き込むと低電力状態になる)。
  ADSCR_ADCH = ADCH_VR;
 この書き方は、ADSCR レジスタに含まれる ADCH4~ADCH0 の 5ビットをまとめた ADCH というビット・フィールドに書き込みを行う方法です。 同じレジスタに含まれるほかのビットには影響がありません(正確には現在の読み出し値が上書きされる)。

・ A-D変換の完了は  ADSCR_COCO が 1 になるのを待ちます。
  while ( !ADSCR_COCO );
 これは while 文をうまく使っています。  ADSCR_COCO が 0 の間ずっと待ちたいので、否定の ! を付けて ( !ADSCR_COCO ) が の間は待つようにしています。 なお、while 文などの制御文はカッコ付きで条件を示したあと、直後の文を制御対象とします。 ここでは ; だけの空文が対象となっているので、条件が になるまで何もしないで待ち続けることになります。

・ 変換結果の取り込みは、10ビット・モードなら ADR を、8ビット・モードなら ADRL を読み出すことで行います。
  work += ADR;
C言語に不慣れな方はとまどってしまうかもしれませんが、これは、
  work = work + ADR;
と同じことです。 つまり ADR を読み出して、work という名前の変数の内容と加算を行い、それをまた work に書き戻しています。 なぜこんなことをしているかは前後の処理を見ていただくとわかるのですが、平均処理のために一定回数分の変換結果を足しているところなのです。 平均処理が不要でただ単に読み出すだけなら加算は必要ありません。

 前回 も説明しましたが、ADR というのは ADRHADRL を連結して 2バイト・サイズのレジスタとして扱えるように定義したものです。

 プログラムをプロジェクトごと圧縮したものを qy4a_adc00.zip においておきます。
 

qy4a_adc_sample.jpg  プログラムをマイコンに書き込んだら、スタンド・アロンのセッティング(JP1 ショート。JP2 はジャンパリンクなし。JP3 は 1-2間をショート。JP4 は 1-2間をショート。) にして電源スイッチをオンしてください。 上の 【動作仕様】 で書いた 4行は、動作の順番を示したものではありません。 VR1 を回したり、PUSH SW を押したりして動きを確認してみてください。
 VR1 を回す実験をした後は、デフォルトのセッティングに戻すときに VR1 を左いっぱいに回すのを忘れないようにしてください。

 
 次回は A-D変換器活用例の予定です。
 

 『参考文献』
「試しながら学ぶHC08マイコン入門」 (CQ出版)
  第1章  マイコン電子工作を始めよう
  第10章 統合開発環境CodeWarriorを使ってみる
  Appendix F KMC908QY4Aユーザ・モード・モニタ入りマイコンの知識
筆者のホームページ 『マイコン工作の実験室』

組み込みエンジニア KAWANO


2009/05/06 10:38 (*1) ADLPC ADC10低電力設定ビットの説明を修正しました。
 1 = 低電力設定: 最大クロック速度での消費電力を低減
 ↓
(変更)
 1 = 低電力設定: 最大クロック速度を抑えて消費電力を低減

カテゴリ:

トラックバック

このエントリーのトラックバックURL:
http://www.eleki-jack.com/mt/mt-tb.cgi/2853

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)

カテゴリ

会社案内
情報セキュリティおよび個人情報の取り扱いについて

コメントとトラックバックは、spamを予防するために、編集担当が公開の作業をするまで非公開になっています。
コメントはそれぞれ投稿した人のものです。

Powered by
Movable Type 4.1