目次8章.機能が豊富なPICを使う(PIC12F683)A/D変換を使う>ソース

A/D変換を使う(PIC12F683)(ソース)

更新日2006.10.14

以下のソースを取り込んで、アセンブル→PIC書き込み→実行して下さい。

; ========================== ここから ==============================
;
;	PIC12F683
;	clock:INTOSCIO 4MHz
;
;	A/D変換とPWMの動作確認
;	A/D変換結果で音の高さ(PWM周期)を変える
;
;	GP2(CCP1:PWM) : スピーカ
;	GP4(AN3)      : 可変抵抗
;	GP5           : LED(0.5秒毎に点滅)
;
;	TMR0割込み
;	TMR0:0(フリーラン)
;	割込み周期:(1/4MHz)*4*256 = 256uS
;
;
	LIST	P=12f683
	#INCLUDE <p12f683.inc>

	__CONFIG _CP_OFF & _CPD_OFF & _WDT_OFF & _BOD_ON & _IESO_OFF& _PWRTE_ON & _INTOSCIO & _MCLRE_OFF


save_st	EQU	020h		; STATUSのセーブ領域
save_w	EQU	021h		; W-regのセーブ領域
CNT10mS	EQU	022h		; TMR0割り込み(256uS)を39回カウントするカウンタ=9.984mS
CNT01S	EQU	023h		; 9.984mSを10回カウントするカウンタ=99.84mS
CNT05S	EQU	024h		; 99.84mSを5回カウントするカウンタ=499.2mS
acq	EQU	025h		; アクィジション時間用カウンタ
AD_save	EQU	026h		; A/D変換結果格納領域
timer	EQU	027h		; タイマフラグ(0:256uS,1:10mS,2:100mS,3:500mS)
T256uS	EQU	00h			; TMR0割込み
T10mS	EQU	01h			; 10mS
T100mS	EQU	02h			; 100mS
T500mS	EQU	03h			; 500mS


	ORG	0
	GOTO	INIT

; ==============================================================
	ORG	4
;	TMR0割込み
INTR
	BCF	INTCON,T0IF	;割込みフラグクリア
	MOVWF	save_w		;W-regセーブ
	SWAPF	STATUS,W
	MOVWF	save_st		;STATUSレジスタセーブ

	BSF	timer,T256uS	;256uSフラグセット

	DECFSZ	CNT10mS,F
	GOTO	INTR90
	MOVLW	d'39'
	MOVWF	CNT10mS		;10mSカウンタ初期化
	BSF	timer,T10mS	;10mSフラグセット

	DECFSZ	CNT01S,F
	GOTO	INTR90
	BSF	timer,T100mS	;100mSフラグセット
	MOVLW	d'10'
	MOVWF	CNT01S		;100mSカウンタ初期化

	DECFSZ	CNT05S,F
	GOTO	INTR90
	BSF	timer,T500mS	;500mSフラグセット
	MOVLW	d'5'
	MOVWF	CNT05S		;500mSカウンタ初期化

INTR90
	SWAPF	save_st,W
	MOVWF	STATUS		;STATUSレジスタロード
	SWAPF	save_w,F
	SWAPF	save_w,W	;W-regロード
	RETFIE			;割込み許可リターン

; ==============================================================
;	PICの初期化
INIT
    ; GPIO(GP2-0)をデジタルI/Oに設定
	MOVLW	07h  
	MOVWF	CMCON0		;GP2-0はデジタルIO  
	BSF	STATUS,RP0	;■バンク1

    ; A/D変換の設定
	MOVLW	018h
	MOVWF	ANSEL		;GP4/AN3(3番ピン)のみアナログ入力,8Tosc(2.0uS)
	MOVLW	010h
	MOVWF	TRISIO		;GP0-3,5は出力,GP4(AN3)は入力
	BCF	STATUS,RP0	;■バンク0
	MOVLW	0Dh
	MOVWF	ADCON0		;A/D結果:左詰め,基準電圧:Vdd,チャネル:AN3,A/D有効

    ; 内部クロックを4MHzに設定
	BSF	STATUS,RP0	;■バンク1
	MOVLW	060h
	MOVWF	OSCCON		;CLOCK=4MHz

    ; PWMの設定
	MOVLW	D'239'
	MOVWF	PR2		;PWM周期
	BCF	STATUS,RP0	;■バンク0
	MOVLW	D'118'		;
	MOVWF	CCPR1L		;PWMデューティーサイクル
	MOVLW	0Ch
	MOVWF	CCP1CON		;PWMモード
	MOVLW	07h
	MOVWF	T2CON		;Timer2 ON ,プリスケーラ:16
	CLRF	TMR2

    ; タイマ用カウンタの設定
	MOVLW	d'39'
	MOVWF	CNT10mS		; TMR0割り込み(256uS)を39回カウントするカウンタ=9.984mS
	MOVLW	d'10'
	MOVWF	CNT01S		; 9.984mSを10回カウントするカウンタ=99.84mS
	MOVLW	d'5'
	MOVWF	CNT05S		; 99.84mSを5回カウントするカウンタ=499.2mS
	CLRF	timer

    ; TMR0割込みの設定
	BSF	STATUS,RP0	;■バンク1
	MOVLW	08h		;プリスケーラ:使用しない(WDTに割り当て)
	MOVWF	OPTION_REG
	BCF	STATUS,RP0	;■バンク0
	CLRF	TMR0		;TMR0セット
	MOVLW	0A0h		;TMR0割り込みを使用する
	MOVWF	INTCON


; ==============================================================
;    メイン処理
	CALL	acquisition
	BSF	ADCON0,GO	;A/D変換開始
MAIN
	BTFSS	ADCON0,GO	;A/D変換完了?
	CALL	ADread
;	BTFSC	timer,T500mS	;500mSフラグセット?
;	CALL	S500mS
	BTFSC	timer,T10mS	;10mSフラグセット?
	CALL	S10mS

	GOTO	MAIN



;  ===== A/D変換完了 =====
ADread
	MOVF	ADRESH,W	;A/D変換結果読み出し
	MOVWF	AD_save
	CALL	acquisition
	BSF	ADCON0,GO	;A/D変換開始

	RETURN


;  ===== ホールド用コンデンサの充電を待つ時間(20u秒) =====
acquisition
	MOVLW	d'5'
	MOVWF	acq
acq_loop
	DECFSZ	acq,F
	GOTO	acq_loop
	RETURN


;  ===== 10mS経過処理(PWMの周期にA/D変換結果をセット) =====
S10mS
	BCF	timer,T10mS	;10mSフラグクリア

	MOVF	AD_save,W
	BSF	STATUS,RP0	;■バンク1
	MOVWF	PR2		;A/D変換結果をPWM周期にセット
	BCF	STATUS,RP0	;■バンク0

	MOVWF	CCPR1L		;PWMデューティーサイクル
	BCF	STATUS,C	;デューティを
	RRF	CCPR1L,F	;周期の1/2にする

;	CLRF	TMR2

	RETURN


;  ===== 500mS経過処理(LEDを0.5秒毎に点滅) =====
S500mS
	BCF	timer,T500mS	;500mSフラグクリア

	MOVLW	020h		;GP5を
	XORWF	GPIO,F		;前回ONならOFFに、OFFならONに

	RETURN

        END
; =========================== ここまで ===============================