; pwm_a.asm								2018.08.02
; pwm.asm								2018.06.20
;									2006.07.07
;									by M.Yanaka
;	Puls Width Moduration
;	
	LIST	P=16F877	; マイコンはPIC16F877
	INCLUDE	P16F877.INC	; インクルードファイルを指定
;*******************************
;	コンフィギュレーションビットの設定
;*******************************
	__CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BODEN_OFF &  _WRT_ENABLE_ON & _LVP_OFF & _DEBUG_OFF & _CPD_OFF
				; 	_HS_OSC		HS高速発振
				; 	_WDT_OFF	ウォッチドッグタイマはOFF
				; 	_PWRTE_ON	パワーアップタイマはON
				; 	_CP_OFF		コードプロテクトはOFF
				; 	_MCLRE_ON 	マスタクリアはON
				; 	_BODEN_OFF	低電圧リセットはOFF
				; 	_WRT_ENABLE_ON	プログラムメモリ書き込みはON
				; 	_LVP_OFF	低電圧書き込みはOFF
				; 	_DEBUG_OFF	オンボードデバッグはOFF
				; 	_CPD_OFF	EEPRROMプロテクトはOFF
;--------------------------------
Reg_20	EQU	H'20'		; ソフトウェアタイマー用
AD_DATA	EQU	H'21'		; A/D変換結果格納用
;--------------------------------
	ORG	0		; リセットベクタ(プログラムアドレス0番地)
	GOTO	START		; STARTへ跳ぶ
;--------------------------------
	ORG	4		; 割り込みベクタ(プログラムアドレス4番地)
	GOTO	START		; （今回は割り込みを使用しない）
;--------------------------------
	ORG	8
;*******************************
;	start（初期設定）
;*******************************
START:
	CALL	INIT_PORT	; 初期設定１（ポート入出力設定）をコール
	CALL	INIT_PWM	; 初期設定２（PWM設定）をコール
	CALL	INIT_AD		; 初期設定３（ＡＤ変換設定）をコール
;*******************************
;	main loop
;*******************************
LOOP:
	CALL	AD_CONV		; ＡＤ変換実行
	BTFSS	AD_DATA,7	; 回転方向の識別
	GOTO	LEFT		; 	AD_DATA < 80h ならば、左回転
RIGHT:				; そうでなければ、右回転
	CLRF	CCPR2L		; CCP2のPWMデューティーサイクルを最小(0)にする
	RLF	AD_DATA,W
	MOVWF	CCPR1L		; CCP1のPWMデューティーサイクルを設定
	GOTO	LOOP
LEFT:
	CLRF	CCPR1L		; CCP1のPWMデューティーサイクルを最小(0)にする
	COMF	AD_DATA,F
	RLF	AD_DATA,W
	MOVWF	CCPR2L		; CCP1のPWMデューティーサイクルを設定
	GOTO	LOOP

;*******************************
;	初期設定１（ポート入出力設定）
;*******************************
INIT_PORT:
	BSF	STATUS,RP0	; バンク1へ切り替えて、
	MOVLW	H'FF'		; ポートAは、
	MOVWF	TRISA		; 	すべて入力ピンにする
	MOVLW	H'FF'		; ポートBは、
	MOVWF	TRISB		; 	すべて入力ピンにする
	CLRF	TRISC		; ポートCはすべて出力ピンにする
	MOVLW	H'FF'		; ポートDは、
	MOVWF	TRISD		; 	すべて入力ピンにする
	CLRF	TRISE		; ポートEはすべて出力ピンにする
	BCF	STATUS,RP0	; バンク0へ切り替える
	RETURN		
;*******************************
;	初期設定２（PWM設定）
;*******************************
INIT_PWM:
	BSF	STATUS,RP0	; バンク1へ切り替えて、
	MOVLW	H'FF'		; タイマー２（PWM用）の周期を、
	MOVWF	PR2		;	最大(100h)にセットする
	BCF	STATUS,RP0	; バンク0へ切り替える
	MOVLW	H'0C'
	MOVWF	CCP1CON		; CCP1をPWMモードにセットする
	MOVWF	CCP2CON		; CCP2をPWMモードにセットする
	CLRF	CCPR1L		; CCP1のPWMデューティーサイクルを最小(0)にする
	CLRF	CCPR2L		; CCP2のPWMデューティーサイクルを最小(0)にする
	MOVLW	H'06'		; タイマー2のプリスケーラを、
	MOVWF	T2CON		;	16にセットし、タイマーをオンにする
	RETURN		
;*******************************
;	初期設定３（ＡＤ変換設定）
;*******************************
INIT_AD:			; A/D 変換器の設定１(AN0)
	BSF	STATUS,RP0	; バンク1へ切り替えて、
	MOVLW	H'02'		; ADCON1(Reg_09F) <- 2
	MOVWF	ADCON1		;	変換結果左詰、RE:Degital, RA:Analog
	BCF	STATUS,RP0	; バンク0へ切り替える
	MOVLW	H'80'		; ADCON0(Reg_01F) <- 80h
	MOVWF	ADCON0		;	RA0/AN0 をアナログ入力に用いる
	RETURN			;	変換クロック <- システムクロック / 32
;*******************************
;	ＡＤ変換
;*******************************
AD_CONV:			; A/D 変換実行１(AN0)
	MOVLW	H'81'		; ADCON0(Reg_01F) <- 81h
	MOVWF	ADCON0		;	A/D 変換モジュールオン(ADON(ADCON0.0) <- 1)
	CALL	WAIT_20		; アクィジション時間待ち（ソフトウェアタイマー ：20.0μs)
	BSF	ADCON0,GO	; A/D 変換開始(GO/DONE(ADCON0.2) <- 1)
WAIT:
	BTFSC	ADCON0,GO	; A/D 変換終了(GO/DONE(ADCON0.2) = 0)を
	GOTO	WAIT		; 	待つ
	MOVF	ADRESH,W	; A/D 変換結果を取り込む(W_reg <- ADRESH(Reg_01E))
	MOVWF	AD_DATA		; 	結果を AD_DATA へ格納する
	RETURN		
;*******************************
;	ソフトウェアタイマー
;*******************************
; Reg_20 はソフトウェアタイマー用作業レジスタ
WAIT_20:			; ソフトウェアタイマー (20.0μs)
	MOVLW	H'20'		; (0.2μs * 3 * 32) + (0.2μs * 4)
	MOVWF	Reg_20
	NOP		
W_20:
	DECFSZ	Reg_20
	GOTO	W_20
	RETURN		
;--------------------------------
	END			; プログラムの終わり
