目次>5章 第2ステップ(色々な実験)>フルカラーLEDを使う(イルミネーション)>ソース

フルカラーLEDを使う(ソース)
− イルミネーション −
更新日2006.11.25

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

; ========================== ここから ==============================
;
;	clock:20MHz
;
;	フルカラーLEDの実験(色々な色を表現)
;
;	RB0-2:3色LED RB0 RED ,RB1 GREEN ,RB2 BLUE
;
;	TMR0割込み
;		TMR0		0(フリーラン)
;		プリスケーラ	1
;		TMR0割込み間隔	0.2uS×256×1=51.2uS
;
;
       LIST    P=PIC16F84A  ; LIST宣言で使用するPICを16F84Aと定義する。
       INCLUDE P16F84A.INC  ; 設定ファイルp16f84a.incを読み込む。
       __CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF


	CBLOCK	0Ch
	timer		; bit0:51.2uS
	cycle		; PWM周期
	wid_R		; PWM幅(赤)カウンタ
	wid_B		; PWM幅(青)カウンタ
	wid_G		; PWM幅(緑)カウンタ
	wid_R_old	; PWM幅(赤)カウンタ(前回)
	wid_G_old	; PWM幅(赤)カウンタ(前回)
	wid_B_old	; PWM幅(赤)カウンタ(前回)
	wid_R_i		; PWM幅(赤)カウンタ初期値
	wid_B_i		; PWM幅(青)カウンタ初期値
	wid_G_i		; PWM幅(緑)カウンタ初期値
	wid_ch		; PWM幅変更間隔(nサイクル毎に幅を変える)
	add_R		; PWM幅(赤)への加算値(±n)
	add_B		; PWM幅(青)への加算値(±n)
	add_G		; PWM幅(緑)への加算値(±n)
	addflag		; 加算(1)か減算(0)か 2:R ,1:G ,0:B
	ENDC

f51uS	EQU	0	; 51.2uSフラグ
cyclei	EQU	d'255'	; PWM周期
wid_chi	EQU	d'15'	; パルス幅変更間隔(サイクル数)

flag_R	EQU	2	; addflagのビット位置
flag_G	EQU	1	; addflagのビット位置
flag_B	EQU	0	; addflagのビット位置


	ORG	0
	GOTO	init

; =================== TMR0割込み処理 =========================
	ORG	4		;割込みの入口

	BCF	INTCON,T0IF	;割込みフラグクリア
	BSF	timer,f51uS	;51.2uSフラグセット

	RETFIE			;割込み許可リターン


; ===================== 初期処理 ==================================
init
	BSF	STATUS,RP0	; ■バンク1
	MOVLW	0F8h
	MOVWF	TRISB		; PORTB設定(RB0-2:出力,RB3-7:入力)
	MOVLW	088h		; TMR0プリスケーラ:無し(0.2μS*1=0.2μS)
	MOVWF	OPTION_REG	; 
	BCF	STATUS,RP0	; ■バンク0
	MOVLW	0A0h		; INTCONの設定
	MOVWF	INTCON		; GIE:1 ,T0IE:1 (TMR0割込み有効)
	CLRF	TMR0		; TMR0をクリア

	MOVLW	00h
	MOVWF	PORTB		; 赤・青・緑のLEDをON(白)

	MOVLW	cyclei
	MOVWF	cycle

	MOVLW	01h
	MOVWF	wid_R_i		; パルス幅の初期値
	MOVWF	wid_B_i
	MOVWF	wid_G_i

	MOVWF	wid_R		; パルス幅の現在値
	MOVWF	wid_B
	MOVWF	wid_G

	MOVLW	01h		; パルス幅加算値
	MOVWF	add_R
	MOVLW	02h
	MOVWF	add_B
	MOVLW	03h
	MOVWF	add_G

	MOVLW	wid_chi		; パルス幅変更間隔
	MOVWF	wid_ch

	MOVLW	07h
	MOVWF	addflag		; 加減算フラグ(最初は全て加算)

; ===================== メイン処理 ================================
main
	BTFSC	timer,f51uS	;51.2uSフラグセット?
	CALL	rgb_pwm
	GOTO	main

; ===================== 3色LED設定処理(PWM) ===============
;			1サイクル終了までパルス幅を制御
rgb_pwm
	BCF	timer,f51uS	;51.2uSフラグクリア

	DECFSZ	cycle,F		;1サイクル終了?
	GOTO	rgb_pwm_R	;No
				;Yes
	CALL	rgb_set

	; 次のサイクル開始処理
	MOVLW	cyclei
	MOVWF	cycle		;1サイクルのカウンタ初期化
	BCF	PORTB,0		;赤ON (PORTはOFF)
	BCF	PORTB,1		;緑ON (PORTはOFF)
	BCF	PORTB,2		;青ON (PORTはOFF)
	GOTO	rgb_pwm_E


	; 各LEDのPWM幅が設定値になったらLEDをOFF(PORTはON)
rgb_pwm_R
	DECFSZ	wid_R,F
	GOTO	rgb_pwm_G
	BSF	PORTB,0		;赤OFF
rgb_pwm_G
	DECFSZ	wid_G,F
	GOTO	rgb_pwm_B
	BSF	PORTB,1		;緑OFF
rgb_pwm_B
	DECFSZ	wid_B,F
	GOTO	rgb_pwm_E
	BSF	PORTB,2		;青OFF
rgb_pwm_E
	RETURN



; ===================== パルス幅算出 ============================
;			1サイクル終了ごとにRGBのパルス幅を変更
rgb_set
	DECFSZ	wid_ch,F	; パルス幅変更?
	GOTO	rgb_set9	; No
	MOVLW	wid_chi		; パルス幅変更間隔
	MOVWF	wid_ch		; 初期化

	; 各色のPWM幅変更
	CALL	wid_set_R
	CALL	wid_set_G
	CALL	wid_set_B

rgb_set9
	; PWM幅設定
	MOVF	wid_R_i,W
	MOVWF	wid_R
	MOVF	wid_G_i,W
	MOVWF	wid_G
	MOVF	wid_B_i,W
	MOVWF	wid_B

	RETURN

; ===================== 赤のパルス幅算出 ============================
wid_set_R
	MOVF	wid_R_i,W
	MOVWF	wid_R_old	;前回のパルス幅を保存

	BTFSS	addflag,flag_R	;加減算は"+" ?
	GOTO	wid_set_R1	; No

	MOVF	add_R,W
	ADDWF	wid_R_i,F
	BTFSS	STATUS,C	;最大値になった?
	GOTO	wid_set_R9	;No

	MOVF	wid_R_old,W
	MOVWF	wid_R_i		;前回のパルス幅を復元
	BCF	addflag,flag_R	;加減算を"−"に変更
	MOVF	addflag,W
	MOVWF	add_R
	INCF	add_R,F
	GOTO	wid_set_R9

wid_set_R1
	MOVF	add_R,W
	SUBWF	wid_R_i,F
	BTFSC	STATUS,C	;最小値になった?
	BTFSC	STATUS,Z	;最小値になった?
	GOTO	wid_set_R2	;Yes
	GOTO	wid_set_R9	;No

wid_set_R2
	MOVF	wid_R_old,W
	MOVWF	wid_R_i		;前回のパルス幅を復元
	BSF	addflag,flag_R	;加減算を"+"に変更
	MOVF	addflag,W
	MOVWF	add_R
	GOTO	wid_set_R9

wid_set_R9
	RETURN


; ===================== 緑のパルス幅算出 ============================
wid_set_G
			;緑1回終了?
	MOVF	wid_G_i,W
	MOVWF	wid_G_old	;前回のパルス幅を保存

	BTFSS	addflag,flag_G	;加減算は"+" ?
	GOTO	wid_set_G1	; No

	MOVF	add_G,W
	ADDWF	wid_G_i,F
	BTFSS	STATUS,C	;最大値になった?
	GOTO	wid_set_G9	;No

	MOVF	wid_G_old,W
	MOVWF	wid_G_i		;前回のパルス幅を復元
	BCF	addflag,flag_G	;加減算を"−"に変更
	MOVF	addflag,W
	MOVWF	add_G
	INCF	add_G,F
	GOTO	wid_set_G9

wid_set_G1
	MOVF	add_G,W
	SUBWF	wid_G_i,F
	BTFSC	STATUS,C	;最小値になった?
	BTFSC	STATUS,Z	;最小値になった?
	GOTO	wid_set_G2	;Yes
	GOTO	wid_set_G9	;No

wid_set_G2
	MOVF	wid_G_old,W
	MOVWF	wid_G_i		;前回のパルス幅を復元
	BSF	addflag,flag_G	;加減算を"+"に変更
	MOVF	addflag,W
	MOVWF	add_G
	GOTO	wid_set_G9

wid_set_G9
	RETURN


; ===================== 青のパルス幅算出 ============================
wid_set_B
			;青1回終了?
	MOVF	wid_B_i,W
	MOVWF	wid_B_old	;前回のパルス幅を保存

	BTFSS	addflag,flag_B	;加減算は"+" ?
	GOTO	wid_set_B1	; No

	MOVF	add_B,W
	ADDWF	wid_B_i,F
	BTFSS	STATUS,C	;最大値になった?
	GOTO	wid_set_B9	;No

	MOVF	wid_B_old,W
	MOVWF	wid_B_i		;前回のパルス幅を復元
	BCF	addflag,flag_B	;加減算を"−"に変更
	MOVF	addflag,W
	MOVWF	add_B
	INCF	add_B,F
	GOTO	wid_set_B9

wid_set_B1
	MOVF	add_B,W
	SUBWF	wid_B_i,F
	BTFSC	STATUS,C	;最小値になった?
	BTFSC	STATUS,Z	;最小値になった?
	GOTO	wid_set_B2	;Yes
	GOTO	wid_set_B9	;No

wid_set_B2
	MOVF	wid_B_old,W
	MOVWF	wid_B_i		;前回のパルス幅を復元
	BSF	addflag,flag_B	;加減算を"+"に変更
	MOVF	addflag,W
	MOVWF	add_B
	GOTO	wid_set_B9

wid_set_B9
	RETURN


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