PIC16F873/876 (28ピン)、PIC16F874/877 (40ピン) などには A/D 変換モジュールが付いています。 28 ピンモジュールには 5 入力、40 ピンモジュールには 8 入力あります。 5 入力全部使えば、3 軸加速度センサと 2 軸ジャイロセンサの出力を 1 つの PIC で A/D 変換することができます(入力が多いほど A/D 変換に時間はかかります)。
A/D 変換モジュールには次の 4 つのレジスタがあります。
ADCON0 レジスタ (1Fh : Bank0) は、クロック、チャンネルの指定、A/D 変換開始などに使用します。
ADCS1 (7) |
ADCS0 (6) |
CHS2 (5) |
CHS1 (4) |
CHS0 (3) |
GO/DONE (2) |
─ (1) |
ADON (0) |
A/D 変換は 1 度に 1 つのポートからの入力に対してしか行なえないので、この 3 bit でどのポートからの入力を変換するか切り替えます。
A/D 変換の設定が終わったら、このビットをセットすることによって実際に A/D を開始します。 A/D が終了すると、このビットは自動的にクリアされます。 割り込みを使わなくても、このフラグをループで監視することで、A/D 変換が終了したことを知ることができます(A/D 変換にはほとんど時間がかからないので、割り込みを使う必要はないかも)。
このビットは常に 「0」 とリードされます。
A/D 変換器モジュールを動作させるかを指定します(実際に A/D 変換を開始する時は GO/DONE(2) をセットします)。 A/D 変換を行なう必要のない場合は、電力の消費を抑えるために停止しておくとよいです。
ADCON1 レジスタ (9Fh : Bank1) では、アナログ入力用ポートの指定を行います。
ADFM (7) |
─ (6) |
─ (5) |
─ (4) |
PCFG3 (3) |
PCFG2 (2) |
PCFG1 (1) |
PCFG0 (0) |
左詰の場合 右詰の場合
+--------+--------+ +--------+--------+
+xxxxxxxx|xx000000| +000000xx|xxxxxxxx|
+--------+--------+ +--------+--------+
ADRESH ADRESL ADRESH ADRESL
PIC16F87x では、A/D 変換後の値が 10bit で得られるので、ADRESH、ADRESL の計 16bit に右詰か左詰どちらで結果を格納するか指定します。 あまり細かい精度まで求める必要がない場合は、左詰めにして ADRESH の 8bit だけ参照すればよいでしょう。
常に 「0」 とリードされます。
省略。
以降の変換は、変換に使用したいアナログチャネルをセレクト (CHS2:CHS0) して繰り返します。
AN0 からの入力を A/D 変換した結果を、USART を使ってシリアルで PC に送信するプログラムの例です。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; AN0 からの入力を A/D 変換した結果を、
; USART を使ってシリアルで PC に送信するサンプルプログラム
;
; デバイス : PIC16F873
; 通信スピード : 9600bps
; データ長 : 8bit
; ストップビット: 1bit
; フロー制御 : なし
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LIST P=PIC16F873
INCLUDE "P16F873.INC"
;==============================================================================
; Variable Definition
;==============================================================================
TEMP EQU 020H
TCNT EQU 021H ; 遅延サブルーチン用の変数
ORG 0
;==============================================================================
; 初期設定
;==============================================================================
INIT
BSF STATUS, RP0 ; Bank1 に切り替え
;**** 入出力ポートの設定 (TRISA) ****
MOVLW B'00000001' ; RA0 は入力(センサから)
MOVWF TRISA ;
;**** アナログ入力にするポート、左詰右詰を決定 (ADCON1) ****
MOVLW B'00000010' ; 左詰、AN0~AN4 全部アナログ入力
MOVWF ADCON1
;**** USART 用入出力ポートの設定 (TRISC) ****
BCF TRISC, 6 ; PortC<6> (TX) is an output
; BSF TRISC, 7 ; PortC<7> (RX) is an input
;**** USART 送信ステータスの設定 (TXSTA) ****
MOVLW B'00100000' ; Async mode
MOVWF TXSTA ;
;**** USART ボーレートの設定 (SPBRG) ****
MOVLW 0FH ;9600bps 10MHz BRGH=0(低速)
MOVWF SPBRG
BCF STATUS, RP0 ; Bank0 に戻す
;**** USART 受信ステータスの設定 (RCSTA) ****
MOVLW B'10010000' ;
MOVWF RCSTA ;
;**** AD 変換クロックを指定。AD 変換を有効に (ADCON0) ****
MOVLW B'10000001' ; Fosc/32, CH0, ADON=1
MOVWF ADCON0
;==============================================================================
; A/D 変換を行うアナログ入力ポートを選択
;==============================================================================
SELECT_AD_CHANNEL
;今回は AN0 からの入力だけを変換するの切り替える必要なし
;==============================================================================
; セレクトしたポートに対して A/D 変換を実行
; チャンネルをセレクトしてからCholdに電圧を蓄積するまで待機する必要がある
; 8bit 変換の時 … 12μsec
; 10bit 変換の時 … 20μsec
;==============================================================================
AD_CONVERT
CALL WAIT20_10MHZ ;コンデンサの充電まち (20μsec, 10MHz)
BSF ADCON0, GO ;A/D 変換スタート
WAIT_AD_FINISH
BTFSC ADCON0, GO ;GO ビットがクリアされたら A/D 変換終了
GOTO WAIT_AD_FINISH
MOVF ADRESH, W ;A/D 変換の結果を取得 (上位8bit)
;==============================================================================
; A/D 変換結果をシリアルで送信
;==============================================================================
CALL SEND_USART
; 1 を送ってみる(テスト用)
; MOVLW 1
; CALL SEND_USART
;**** チャンネルセレクトへもどる ****
GOTO SELECT_AD_CHANNEL
;==============================================================================
; シリアル送信サブルーチン
; TXSTA<TRMT(1)> を監視し、W レジスタのデータ (8 bit) をシリアルで送信します。
; (TEMP を Bank0 の汎用レジスタに指定してあることを前提とします。
; このルーチンを呼び出す時は Bank0 に切り替えてから呼び出すこと)
;==============================================================================
SEND_USART
MOVWF TEMP ;W レジスタを保存
BSF STATUS, RP0 ;Bank1 に切り替え
SEND_USART_LOOP
BTFSS TXSTA, TRMT ;TXSTA<TRMT(1)> が 1 になるまで待機
GOTO SEND_USART_LOOP
BCF STATUS, RP0 ;Bank0 に戻す
MOVF TEMP, W ;W レジスタの復旧
MOVWF TXREG ;TXREG レジスタにセット (実際の送信開始)
RETURN
;==============================================================================
; 20μsec の遅延時間 ─ 10MHz (周期 0.4μsec) の時
;==============================================================================
WAIT20_10MHZ
MOVLW D'14' ; 20 / 0.4 = 50
MOVWF TCNT ; (50 - 6) / 3 = 14 余り 2
WAIT20_10MHZ_LOOP
DECFSZ TCNT, F ;
GOTO WAIT20_10MHZ_LOOP
NOP ; 余り 2 だから NOP は 2 つ
NOP ;
RETURN ;
;==============================================================================
; End Program
;==============================================================================
END