目次
前
次
積分回路利用(割込み活用)
積分回路では、電荷のキャパシタへの充放電をプログラムで計測して
います。
充放電処理の時間を計測するには、アナログコンパレータとインプット
キャプチャ処理を組み合わせて対応します。
アナログコンパレータをOPアンプを利用した回路にすると、以下。
電源電圧Vccの2/3よりも、反転端子の入力電圧Vinが上回ると
出力電圧Voutは、0V近くまで下がります。通常、VoutはVccに
近い電圧になります。
PIC16F627Aは、アナログコンパレータを内蔵しています。
アナログコンパレータによる電圧検出で、割込みを発生させ
られるので、使えるようになっておくと、ポーリングによる
指定ピンの電圧監視処理をしないで済ませられます。
スイッチを接続すると、ハードウエア上は次のようになります。
回路を見てわかることは、コンパレータの出力がHかLか
は、反転入力、非反転入力の接続で変わります。
回路の接続を指定するには、アナログコンパレータ関係の
レジスタCMCONで設定します。
レジスタのビット7、6をみると、アナログコンパレータの
出力値を参照できます。組み合わせは、以下。
C2OUT 1:Vin+ > Vin- 0:Vin+ < Vin-
C1OUT 1:Vin+ > Vin- 0:Vin+ < Vin-
レジスタのビット5、4を使うとC2OUT、C1OUTの出力を
反転できるようになっています。
C2INV 1:inverse 0:normal
C1INV 1:inverse 0:normal
ここまでで、アナログコンパレータは2個あることがわかります。
ピンアサインで確認できます。
PICは、ひとつのピンに複数の機能を割り当てているので
アナログコンパレータを使うのか、他の機能にするのか
を指定します。
CM2からCM0の組合せによる接続は、以下。
アナログコンパレータを2つ使う場合、100を設定します。
CMCON = 0x40 ;
アナログコンパレータが2つあるので、プッシュスイッチ
を2つ利用できるようにシステムを構成できます。
プッシュスイッチを押すと、比較電圧よりも小さくなり
そのときに割込みを発生するように指定します。
CMCON = (3 << 4) | 0x40 ;
プッシュスイッチSW1、SW2をスタート、ストップに役割
分担しておけば、タイマー割込みとシフトレジスタでの
判定処理よりも簡単にスイッチ状態の変化を読取れます。
割込みを使うため、アナログコンパレータ関係のレジスタ
リストを確認します。
レジスタリストから必要なビット処理を指定していきます。
周辺モジュールの該当割込み許可
PIE1.CMIE = ON ;
周辺モジュールの割込み許可
INTCON.PEIE = ON ;
ポートAの入出力方向指定
TRISA = 0xff ;
ここまでの内容を、初期化関数の中に入れます。
void usr_init(void)
{
/* port directions */
TRISA = 0xff ;
/* initialize analog comparator */
{
/* select analog comparator channel and invert */
CMCON = (3 << 4) | 0x40 ;
/* enable analog comparator interrupt */
PIE1.CMIE = ON ;
/* enable peripheral interrupt */
INTCON.PEIE = ON ;
}
/* enable global interrupt */
INTCON.GIE = ON ;
}
割込みハンドラは、アナログコンパレータの割込みを
判定し、どちらのチャネルかで該当するフラグを設定
します。
void interrupt(void)
{
/* analog comparator */
if ( INTCON.CMIF == ON ) {
/* clear flag */
INTCON.CMIF = OFF ;
/* judge */
if ( CMCON.C2OUT == ON ) { AC2FLAG = ON ; }
if ( CMCON.C1OUT == ON ) { AC1FLAG = ON ; }
}
}
イベントフラグができれば、main関数内部の該当
処理の記述は単純になります。
積分回路では、キャパシタに電荷をチャージしてから
放電により電荷がなくなるまでの時間を、タイマーで
カウントさせるようにします。
動作シーケンスは、次のようにします。
- ターゲットピンに1を出力
- ターゲットピンを出力に設定
- 時間待ち
- ターゲットピンを入力に設定
- カウンタ値をクリア
- 割込み処理のイベントフラグ待ち
- カウンタ値をリード
- カウンタ値に応じた処理実行
1から4はひとつの関数にまとめられます。
void charge(void)
{
/* impress 1 */
PORTA.F0 = ON ;
/* set RA0 as output pin */
TRISA.F0 = 0 ;
/* delay */
Delay_ms(1);
/* set RA0 as input pin */
TRISA.F0 = 1 ;
}
タイマーカウンタの値をクリアして
放電を開始するコードは、以下。
/* clear counter */
TMR1H = 0 ;
TMR1L = 0 ;
/* enable timer 1 */
T1CON.TMR1ON = ON ;
カウントを開始してしまえば、アナログコンパレータ
からの通知を待つだけになります。
if ( CM1FLAG == ON ) {
/* clear flag */
CM1FLAG = OFF ;
/* stop count */
T1CON.TMR1ON = OFF ;
/* get counter */
xcnt = TMR1H ;
xcnt <<= 8 ;
xcnt |= TMR1L ;
}
充放電時間幅を求めるには、インプットキャプチャを利用します。
2つのアナログコンパレータを利用し、開始と終了の
トリガーを受けて、各時のタイマーカウンタ値を記録
するのが、インプットキャプチャになります。
カウンタを、フリーで自動インクリメントさせておき
2つのアナログコンパレータ割込みで、カウンタ値を
保存し、その差分Nを求めると、周期xNで時間差を
計算できます。
OPアンプで構成したウィンドウコンパレータが、この
処理と等価です。
キャパシタの放電では、2つの電位でトリガーをかけて
カウンタ値を取得します。放電するには、充電が必要と
なるので、動作シーケンスを考えます。
利用する回路は、以下。
充電開始
充電開始のトリガーには、タイマー割込みを使います。
1秒ごとに、タイマー割込みでイベント通知フラグを
セットし、1ms充電します。
if ( TFLAG == ON ) {
/* clear flag */
TFLAG = OFF ;
/* disable analog comparator */
CMCON = 0x07 ;
/* stop count */
T1CON.TMR1ON = OFF ;
/* charge */
charge();
/* clear counter */
TMR1H = 0 ;
TMR1L = 0 ;
/* start count */
T1CON.TMR1ON = ON ;
/* enable analog comparator */
CMCON = 0x04 ;
/* clear state */
state = 0 ;
}
コンパレータ1割込み
コンパレータ1の割込み発生をイベント通知フラグで検出。
イベント通知フラグを利用し、カウンタ値を保存。
if ( AC1TFLAG == ON ) {
/* clear flag */
AC1TFLAG = OFF ;
/* store counter value */
cmpcnt1 = TMR1H ;
cmpcnt1 <<= 8 ;
cmpcnt1 |= TMR1L ;
/* update state */
state++ ;
}
コンパレータ2割込み
コンパレータ2の割込み発生をイベント通知フラグで検出。
イベント通知フラグを利用し、カウンタ値を保存。
if ( AC2TFLAG == ON ) {
/* clear flag */
AC2TFLAG = OFF ;
/* store counter value */
cmpcnt2 = TMR1H ;
cmpcnt2 <<= 8 ;
cmpcnt2 |= TMR1L ;
/* update state */
state++ ;
}
計算
状態変数を利用し、2カウンタ値を取得したことを
確認し、計算に入ります。
if ( state == 2 ) {
/* clear */
state = 0 ;
/* disable analog comparator */
CMCON = 0x07 ;
/* stop count */
T1CON.TMR1ON = OFF ;
/* calculate */
if ( cmpcnt2 >= cmpcnt1 ) {
cmpcnt = cmpcnt2 - cmpcnt1 ;
} else {
cmpcnt = cmpcnt1 - cmpcnt2 ;
}
}
ここまでで、状態変数と通知フラグだけを利用し
制御変数を利用した、for文でのシーケンスには
なっていないことに注意します。
組込みのファームウエアを作成する場合、タイマー割込みと
通知フラグを使ったイベント駆動処理にするのが定石です。
(under construction)
目次
前
次