TOPMPLAB XC8編(PIC12F675)> (04)可変抵抗でLEDの明るさを制御(A/D変換,PIC12F675,XC8)

可変抵抗でLEDの明るさを制御

 − A/D変換とPWM制御 −
(PIC12F675 XC8)

更新日2012.5.20
作成日2008.10.19


可変抵抗によりLEDの明るさを変える実験を行います。
可変抵抗の状態はA/D変換により読み込み、LEDの明るさ制御はPWM方式を使用します。

実験回路
今回の実験回路です。
クロックは内部クロックを使い4MHzとしました。

LEDと直列の抵抗は、300〜800Ω程度の範囲であれば明るさが変わるだけで点灯は確認できます。

ブレッドボードに組んだ状態
右下の6ピンヘッダ周りは、回路図には有りませんがICSP(In-Circuit Serial Programming)用です。秋月のPICライタなどを使う場合は不要です。

仕様
可変抵抗の出力電圧をGP0でA/D変換し、その結果でGP5のLEDの明るさを変えます。
LEDの明るさ制御はPWM方式を使いますが、PIC12F675には機能がありませんのでプログラムで制御します。
PWM制御のための基準時間はTMR0割込みを使いました。

また、GP4のLEDはパイロットランプ代わりに1秒毎に点滅させます。


A/D変換について
A/D変換とは、アナログ信号(電圧)をデジタルデータに変換することです。

PIC12F675では、アナログポート(AN0〜AN3)の電圧を10ビットの数値に変換する事ができます。
変換は、基準電圧を1024として測定電圧を表現します。

ADres=Vin/(Vref/1024)

ただし、ADresの最大値は1023です。(16進表現で、'3FF'まで)

例えば、基準電圧が5Vで測定電圧が2.5Vの場合、AD変換の結果(ADres)は512になります。

ADres=Vin/(Vref/1024)
=2.5/(5/1024)
=512

A/D変換の手順

A/D変換を行う手順は以下の通りです。

(1)A/D変換機能の初期設定
以下の3つのレジスタ設定を行います。
ANSELA/D変換のクロック設定と、A/D変換の入力ピンを指定
TRISIOA/D変換で使うピンを入力モードに設定
ADCON0基準電圧の選択,A/D変換結果の格納方法指定,A/D変換の入力ピン選択を行い、A/D変換を有効に設定

(2)A/D変換準備完了を待つ
PIC内蔵のコンデンサ充電完了を待ちます。
この時間をアクィジション時間と言い、入力抵抗が10KΩの時、約20μ秒です。

(3)A/D変換を開始する
ADCON0レジスタのGOビットをONにしてA/D変換を開始します。

(4)A/D変換完了を待つ
ADCON0レジスタのGOビットがOFF(A/D変換完了)になるのを待ちます。

(5)A/D変換結果を使う
A/D変換結果が、ADRESH,ADRESLレジスタに格納されていますので、目的に応じて使用します。

(6)繰り返す
繰り返す場合は、(2)に戻ります。

【参考】
A/D変換完了を待つ方法として、上ではADCON0レジスタのGOビットがOFFになるのを待っていますが、A/D変換完了割込みを使う方法もあります。
A/D変換完了割込みを使う場合、以下のレジスタ操作が必要です。
 INTCON,PIR1,PIE1


基準電圧

基準電圧は、以下のいずれかを選択します。

・電源電圧Vdd
・GP1/Vref(6番ピンに与える電圧)
どちらにするかは、ADCON0レジスタのVCFGビットで設定します。

今回は、精度は要求されませんので、電源電圧を基準電圧にしました。

入力ポートの選択

A/D変換で使えるポートは、AN0〜AN3の4ポートがあります。1つだけをA/D変換で使い、他はデジタルI/Oにすることもできますし、4つ共A/D変換で使うこともできます。
この選択は、ANSELレジスタのANS0〜ANS3で指定します。

ただし、1回のA/D変換動作では、1つのポートだけを対象とする必要があり、このポート選択は、ADCON0レジスタのCHS0,CHS1で設定します。

A/D変換のクロック選択(TAD

A/D変換のクロックは、下の表の水色の範囲を指定します。
これは、PICを動作させるオシレータ(クロック)の周波数により、ANSELレジスタのADCS2〜0の設定値で選択します。
今回は、オシレータを4MHzにしましたので、8Toscを選択し2.0μ秒にしました。(下表の赤字)

A/Dクロック設定オシレータ周波数
動作ADCS2-020MHz5MHz4MHz1.25MHz
2Tosc000100nS400nS500nS1.6μS
4Tosc100200nS800nS1.0μS3.2μS
8Tosc001400nS1.6μS2.0μS6.4μS
16Tosc101800nS3.2μS4.0μS12.8μS
32Tosc0101.6μS6.4μS8.0μS25.6μS
64Tosc1103.2μS12.8μS16.0μS51.2μS
A/D RCx112-6μS2-6μS2-6μS2-6μS
表の水色の範囲を使用します。
A/D変換のクロックは、最低が1.6μSですので、表の青の部分は使用できません。
また、赤の部分は変換時間が必要以上に長くなります。
【ToscとFosc】
Toscはオシレータの1クロック(1サイクル)の時間であり、8Toscは1クロックの時間の8倍という意味です。
Foscはオシレータの周波数で、Fosc/8はオシレータの周波数の1/8という意味です。


A/D変換結果の格納

A/D変換結果は10ビットです。一方、PICのレジスタは8ビットです。
そのままでは格納できませんので、ADRESHレジスタとADRESLレジスタの2つを連結した16ビットに格納されます。
16ビット幅に10ビットを格納しますが、以下の2パターンから選択できます。
 ・左詰めで下位の6ビットを0にする
 ・右詰めで上位の6ビットを0にする
この選択は、ADCON0レジスタのADFMビットで指定します。

今回は左詰めとし、ADRESHレジスタだけを使いました。

A/D変換のレジスタ初期化例

今までの説明を元に作った、今回のプログラムでのレジスタ初期化例です。

CMCON = 0x07;// コンパレータ未使用
ANSEL = 0x11;// 8Tosc,AN0
ADCON0 = 0x01;// Left,Vdd,AN0,ADON
TRISIO = 0x0F;// GP0-4:in,GP4,5:out
GPIO = 0;

PWM方式(LEDの明るさ制御)

PWM方式によるLEDの明るさ制御については、こちらを参考にして下さい。

今回のプログラムでは、以下のように制御します。

PWM周期TMR0割込み32回をPWMの周期とします。
PWMパルス幅A/D変換結果の上位5ビットの値(0〜31)だけ、TMR0割込みをカウントしパルス幅とします。

TMR0割込みは、0.256mS毎に発生するよう設定します。

TMR00(フリーラン)
プリスケーラなし

プログラム

今回のプログラムはこちらです。

プログラムの各ブロックで行っている処理は以下通りです。

CONFIG設定
CONFIGは以下のように設定しています。

__CONFIG(FOSC_INTRCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF);

クロック内部クロックでGP4,5はデジタルI/Oで使用
WDT未使用
パワーアップタイマ有効
MCLRピンMCLRは無効で、GP3をデジタル入力で使用
main
まずPICの初期化(pic_init)を行います。
その後、ループの中でA/D変換を行い上位5ビットをPWMのパルス幅として保存します。保存した値はTMR0割込みの中で使用します。
また、GPIO4のLEDを0.5秒毎に点滅させます。
0.5秒の時間は、TMR0割込み処理で設定する500mSフラグにより判断します。
pic_init
PICの初期化処理を行います。
使わないコンパレータを無効にして、GPIO4,5を出力に設定し、A/D変換とTMR0割込みの初期設定を行います。
intr(割込み処理)
TMR0割込みの処理を行います。
割込みをカウントし、PWMのパルス幅に達したらGPIO5に0をセットします。カウントが32になったらGPIO5に1をセットします。
割込み毎に500mSカウンタを+1し、61になったら500mSフラグを立てます。
wait_50uS
プログラムループにより50μ秒待ちます。
この時間は、A/D変換のアクィジション時間として使います。


電源を投入すると、緑のLEDが0.5秒間隔で点滅します。
ボリュームを回すと、赤のLEDの明るさが変わります。

正しく動作しましたか?