PICを使った30分、60分オフタイマープログラム

私が寝室で使っているテレビのマイコンに不具合があり、リモコンで消したテレビの電源が勝手に入ったり、オフタイマーが働かなかったりしていました。テレビ自体が古いので直す気にもなれずそのままになっていました。そのアセンブラープログラムを紹介します。

完成したオフタイマー基板と周辺機器

オフタイマー基板等の写真

ほぼ完成した、PICを使った30分、60分オフタイマーの写真です。

左からDC5V用の携帯電話充電用電源アダプタ、秋月のSSRキット、PIC12F629を使ったタイマー基板です。ケースに入れる前の状態です。何度もPICのプログラムを書き換えて試せるようにICソケットを使っています。

PIC12F629で正確なタイマーを作る場合はセラロックか水晶発振子を使った方が良いのですが、内部発振でもそこそこの精度があります。また回路が非常に簡単なのも魅力です。

PIC12F629を使ったオフタイマー

PICマイコンがなんとか使えるようになったので、 PICマイコン楽天 の学習も兼ねてテレビにも使えるオフタイマーを作ってみました。うまくできましたので紹介します。PICマイコンPIC12F629と秋月電子通商のソリッドステートリレー(SSR)のキットを利用して作りました。

PICのアセンブラープログラムはフリーソフトのTera-Padエディターで作成しました。PIC開発ツールはMicrochip社のMPLAB IDE Ver.7.4、PICプログラムの書き込みは秋月のAKI-PICプログラマーVer.4を使いました。

もちろん、テレビ以外にもラジオやラジカセ、時間の変更や放熱板の変更でエアコンでも使えるようにできます。

30分、60分オフタイマープログラム

; Filename:	timer30_60.asm
; Date:2007.06.02
; File Version:	1.0
; OFF Timer 30_60 min.
; Author:		D.Ishikawa
;**********************************************************************
; Files required:
;**********************************************************************
;PICは12F629
;GPIO,1	;LED出力ポート
;GPIO,2	;タイマー出力ポート
;GPIO,3	;タイマーの時間を決める入力ポート
;GPIO,3がLの時30分オフタイマーとなります。
;GPIO,3がHの時60分オフタイマーとなります。
;60分オフタイマーで最初の30分はLEDが2秒周期で点滅
;最後の30分はLEDが1秒周期で点滅
;**********************************************************************

	list	p=12f629		;list directive to define processor
	#include	<p12f629.inc>	; processor specific variable definitions

	errorlevel	-302	;suppress message 302 from list file

	__CONFIG _CP_ON & _CPD_ON & _BODEN_ON & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT 

	__IDLOCS 0x0100 ;Ver 1.00

#define	OUT_LED	GPIO,1	;LED出力ポート
#define	OUT_TMR	GPIO,2	;タイマー出力ポート
#define	IN_P	GPIO,3	;入力ポート
#define	ON_TIME	d'30'	;最短のON期間 分で指定

;***** VARIABLE DEFINITIONS
w_temp EQU 0x20 ; variable used for context saving 
status_temp EQU 0x21 ; variable used for context saving

CNT1	EQU	0x22
CNT2	EQU	0x23
CNT3	EQU	0x24
CNT4	EQU	0x25
;**********************************************************************
;initialize eeprom locations
	ORG	0x2100
	DE	"OFF Timer_30_60min."

	ORG	0x000		; processor reset vector
	goto	main		;go to beginning of program

	ORG	0x004		;interrupt vector location
	movwf	w_temp		;save off current W register contents
	movf	STATUS,w		;move status register into W register
	movwf	status_temp	; save off contents of STATUS register

;isr code can go here or be located as a call subroutine elsewhere

	movf	status_temp,w	; retrieve copy of STATUS register
	movwf	STATUS		;restore pre-isr STATUS register contents
	swapf	w_temp,f
	swapf	w_temp,w		;restore pre-isr W register contents
	retfie			;return from interrupt

;these first 4 instructions are not required if the internal oscillator is not used

main
	call	0x3FF		;retrieve factory calibration value
	bsf	STATUS,RP0	;set file register bank to 1 
	movwf	OSCCAL		;update register with factory cal value 
	bcf	STATUS,RP0	;set file register bank to 0

;remaining code goes here

	bcf	STATUS,RP0	;set file register bank to 0
	bcf	STATUS,RP1	;set file register bank to 0

	clrf	INTCON		;割り込み禁止

	clrf	GPIO		;GPIO初期化

	bsf	STATUS,RP0	;バンク1に切替
	clrf	TRISIO		;GPIOを出力に設定
	bsf	TRISIO,3		;GP3を入力に設定

	clrf	IOC		;I/O状態変化チェック解除
	movlw	b'10000000'	;プルアップ無し、エッジ割り込み無し、タイマー0は内部クロック
	movwf	OPTION_REG	;

	bcf	STATUS,RP0	;バンク0に

	bcf	OUT_LED		;OUT_LEDを0に
	bcf	OUT_TMR		;OUT_TMRを0に

	btfsc	IN_P		;入力ポートチェック
	goto	_60MIN		;Hなら _60MIN へ

_30MIN
	bsf	OUT_TMR		;OUT_TMRを1に
	call	DLY_30
OFF_30	bcf	OUT_TMR		;OUT_TMRを0に
	goto	OFF_30

_60MIN
	bsf	OUT_TMR		;OUT_TMRを1に
	call	DLY_60_30
	call	DLY_30
OFF_60	bcf	OUT_TMR		;OUT_TMRを0に
	goto	OFF_60

;Delay Routine

DLY_30			;30分
	movlw	ON_TIME		;1*30=30min
	movwf	CNT4
DLY_6			;60S
	movlw	d'60'		;1*60=60S
	movwf	CNT3
DLY_5	;1S	;0.5*2=1S
	bsf	OUT_LED		;0.5秒ON
	call	DLY_500
	bcf	OUT_LED		;0.5秒OFF
	call	DLY_500

	decfsz	CNT3,f
	goto	DLY_5
	decfsz	CNT4,f
	goto	DLY_6
	return

DLY_60_30			;60分用の初めの30分
	movlw	ON_TIME		;1*30=30min
	movwf	CNT4
DLY_4			;60S
	movlw	d'30'		;2*30=60S
	movwf	CNT3
DLY_3			;2S ;0.5*4=2S
	bsf	OUT_LED		;1秒ON
	call	DLY_500
	call	DLY_500
	bcf	OUT_LED		;1秒OFF
	call	DLY_500
	call	DLY_500

	decfsz	CNT3,f
	goto	DLY_3
	decfsz	CNT4,f
	goto	DLY_4
	return

DLY_500			;500mS
	movlw	d'250'		;2mS*250=500mS
	movwf	CNT2
DLY_2			;2mS	DLY_2 loop	DLY_2 を一巡する時間は 6 + 8*249 + 2 = 2000μS
	movlw	d'249'	;	(1)		1cycle=1μS
	movwf	CNT1	;	(1)
	nop		;	(1)
	nop		;	(1)
	nop		;	(1)
	nop		;	(1)
DLY_1		;  DLY_1 loop
	nop	;	 1	 1
	nop	;	 1	 1
	nop	;	 1	 1
	nop	;	 1	 1
	nop	;	 1	 1
	decfsz	CNT1,f	;1	 2	(CNT1が0になると2サイクル)
	goto	DLY_1	;2		(12F629の goto は2サイクル)
	decfsz	CNT2,f	;	 1
	goto	DLY_2	;	(2)
	return

	END	;directive 'end of program'

オフタイマーのアセンブラープログラムの使い方

アセンブラープログラムファイル名をtimer30_60.asm等にしてエディタ等で保存して使ってください。