⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ir_controller.asm

📁 pic单片机对红外设备控制得一个源程序
💻 ASM
📖 第 1 页 / 共 2 页
字号:

pgm_mode
	movlw	d'4'
	movwf	COUNT

rg_flash
	LED_red			; flash bicolor LED alternately green/red
	call	delay_t6	; (either for 250 ms) 4 times to indicate
	LED_grn                 ; that the program mode has been entered
	call	delay_t6
	decfsz	COUNT
	goto	rg_flash
	LED_off			; now ready to learn codes (LED off)

learn_1
	call	ir_chk1		; wait for high level at IR_C_out, timeout if idle for > 5s
	call	rc5_rx		; call rc5_rx subroutinee
	btfsc	RC5_Flag	; RC5 code OK?
	goto	learn_1		; no, try again

	movfw	RC5_CMD		; copy RC5_CMD to w and
	andlw	b'01111111'	; clear toggle bit
	movwf	TMP1		; copy to TMP1 and TMP2
	movwf	TMP2		;
	bsf	status,c	; check if command is 0...9
	sublw	d'9'
	btfss	status,c
	goto	learn_1		; no, try again

	LED_grn			; turn on green LED for 250ms if a
	call	delay_t6	; valid code has been received
	LED_off

	movfw	RC5_CMD		; copy RC5_CMD to temporary register
	movwf	RC5_CMD_TMP	; for the next toggle bit comparison

	bcf	status,c	; multiply TMP1 by 10
	rlf	TMP1,f		; for 10's of PWR_ON_DELAY
	rlf	TMP1,f
	rlf	TMP1,f
	movfw	TMP2
	addwf	TMP1,f
	addwf	TMP1,f

learn_2
	call	ir_chk1		; wait for high level at IR_C_out, timeout if idle for > 5s
	call	rc5_rx		; call rc5_rx subroutine
	btfsc	RC5_Flag	; RC5 code OK?
	goto	learn_2		; no, try again

	movfw	RC5_CMD		; check if toggle bit has changed
	subwf	RC5_CMD_TMP,w	;
	btfsc	status,z	;
	goto	learn_2		; no, try again

	movfw	RC5_CMD		; copy RC5_CMD to w and
	andlw	b'01111111'	; clear toggle bit
	movwf	TMP2		; copy to TMP2
	bsf	status,c	; check if command is 0...9
	sublw	d'9' 		;
	btfss	status,c	;
	goto	learn_2		; no, try again

	movfw	TMP1		; add 10's and 1's
	addwf	TMP2,w		;

	movwf	EEDATA_TMP	; copy to EEDATA_TMP

	movlw	h'00'		; set EEADR_TMP to h'00'
	movwf	EEADR_TMP	;
	call	write_ee	; and write to EEPROM

	LED_grn			; turn on green LED for 250ms if a
	call	delay_t6	; valid code has been received
	LED_off

	movfw	RC5_CMD		; copy RC5_CMD to temporary register
	movwf	RC5_CMD_TMP	; for the next toggle bit comparison

learn_3
	call	ir_chk1		; wait for high level at IR_C_out, timeout if idle for > 5s
	call	rc5_rx		; call rc5_rx subroutine
	btfsc	RC5_Flag	; RC5 code OK?
	goto	learn_3		; no, try again

	movfw	RC5_CMD		; check if toggle bit has changed
	subwf	RC5_CMD_TMP,w	;
	btfsc	status,z	;
	goto	learn_3		; no, try again

	movfw	RC5_CMD		; copy RC5_CMD to w and
	andlw	b'01111111'	; clear toggle bit
	bcf	status,c	; check if command is 0...9
	sublw	d'9' 		; which can not be assigned
	btfsc	status,c	; as pwr_key
	goto	learn_3		; yes, try again

	movfw	RC5_ADR
	movwf	EEDATA_TMP	; copy to EEDATA_TMP
	movlw	h'01'		; set EEADR_TMP to h'01'
	movwf	EEADR_TMP	;
	call	write_ee	; and write to EEPROM

	movfw	RC5_CMD		; copy RC5_CMD to w and
	andlw	b'01111111'	; clear toggle bit
	movwf	EEDATA_TMP	; copy to EEDATA_TMP
	movlw	h'02'		; set EEADR_TMP to h'02'
	movwf	EEADR_TMP	;
	call	write_ee	; and write to EEPROM

	call	copy_ee		; copy new values to RAM

	LED_grn			; turn on green LED for 250ms to indicate
	call	delay_t6	; that a valid code has been received
	LED_off

	clrf	KEYCOUNT_1	; clear KEYCOUNT_1 to reset zero key detection delay
	goto	main_loop

ir_chk1				; wait for high level at IR_C_out, timeout if idle for > 5s
	clrf	tmr1h		; clear timer1 registers
	clrf	tmr1l
	movlw	d'19'           ; set COUNT to d'19', this makes 19 x 262ms = approx. 5 seconds
	movwf	COUNT

ir_chk2
	btfsc	IR_C_out	; wait for high level at IR_C_out
	return			; and return

	btfsc	tmr1h,7		; check timer1 h register bit 7 (set after 262ms)
	goto	dec_cnt
	goto	ir_chk2

dec_cnt
	clrf	tmr1h		; clear timer1 registers
	clrf	tmr1l
	decfsz	COUNT,f
	goto	ir_chk2		; not yet 5s, loop
	clrf	KEYCOUNT_1	; clear KEYCOUNT_1 to reset zero key detection delay
	goto	main_loop	; timeout after approx. 5s


;**************************************************************************************************
; RC5 transmit subroutine
;**************************************************************************************************

rc5_tx				; we have: RC5 address '000AAAAA' and command '0CCCCCCC'
	bsf	RC5_TX_2,7	; set 1st start bit
	btfss	RC5_TX_1,6	; check command bit #6 and
	bsf	RC5_TX_2,6	; set 2nd start bit if necessary
	bcf	status,c	; clear carry bit
	rlf	RC5_TX_1	; left shift RC5_TX_1 twice to bring command MSB to
	bcf	status,c	; left-most position
	rlf	RC5_TX_1	; now the 16-bit shift register is ready for
				; shifting out: RC5_TX_2 1S0AAAAA   RC5_TX_1 CCCCCC00

	bsf	IRin		; set port register bit IRin high before setting to output
	Bank_1			; to avoid a 1祍 spike
	bcf	IRinTris	; set IRin as output
	Bank_0			;

	call	delay_t6	; 250ms delay for time decoupling (LIRC might still be busy with
				; processing IR codes from the receiver and would not react to the
                                ; the code generated below)

	movlw	d'14'		; set BITCOUNT to 14
	movwf	BITCOUNT	;

bit_test
	btfss	RC5_TX_2,7	; test all bits
	goto	out_low_high	; remember that we have to invert them

out_high_low
	bsf	IRin		; output a high-low sequence at IRin
	call	delay_t5	; either state is 889祍
	bcf	IRin		;
	call	delay_t5	;
	goto	next_bit	; goto next_bit

out_low_high
	bcf	IRin		; output a low-high sequence at IRin
	call	delay_t5	; either state is 889祍
	bsf	IRin		;
	call	delay_t5	;

next_bit
	rlf	RC5_TX_1	; left shift the 16-bit register
	rlf	RC5_TX_2	;
	decfsz	BITCOUNT	; until all 14 bits are out
	goto	bit_test	;

	btfss	IRin            ; if the last bit was a high-low sequence, immediately set IRin
	bsf	IRin            ; high to terminate the RC5 code after the correct time

	call	delay_t6	; 250ms delay for time decoupling (IR codes from the receiver chip
				; occuring directly after the code generated above would destroy
				; the integrity of this code)
	Bank_1
	bsf	IRinTris	; set IRin to input again
	Bank_0

	return


;**************************************************************************************************
; RC5 receive routine
;**************************************************************************************************
;
; in:  14 bit data from IRin resp. DTRin
;
; out: RC5_ADR (8 bit, 000AAAAA)
;      RC5_CMD (8 bit, TCCCCCCC)
;      RC5_Flag (1 bit) 0: RC5 code valid, 1: RC5 code invalid
;
; Self-synchronizing code which tolerates inaccurate RC5 timings.
; Tolerance is achieved by polling +/- approx. 250祍 around each expected level change. To mark the
; received code as valid, the level before and after the edges must be opposite, no timer0 overflow
; (512祍) occurred, and two samples taken at 1200祍 and 1500祍 after each edge must be equal.

rc5_rx
	clrf	DATA_1		; clear input shift register
	clrf	DATA_2		;
	movlw	d'13'		; set BITCOUNT to 13
	movwf	BITCOUNT	;
	test			; 1祍 mark
	call	delay_t1a	; 1520祍 delay until approx. 256 祍 before next expected slope
	call	delay_t1b

pre_slope
	test			; 1祍 mark

	clrf	tmr0	        ; clear	timer0 register
        bcf   	intcon,t0if     ; clear timer0 interrupt flag

	btfss	IR_C_out	; IR_C_out high?
	goto	poll_lo_hi	;

poll_hi_lo
	btfsc	intcon,t0if	; check for timer0 overflow (after 512祍)
	goto	set_flag        ; and set 'invalid' flag

	btfsc	IR_C_out
	goto	poll_hi_lo
	goto	next_bit1

poll_lo_hi
	bsf	DATA_1,0	; set lsb in DATA_1

	btfsc	intcon,t0if	; check for timer0 overflow (after 512祍)
	goto	set_flag	; and set 'invalid' flag

	btfss	IR_C_out
	goto	poll_lo_hi

next_bit1
	decfsz	BITCOUNT,1	; if 0: all 14 bits received (1st was used for
	goto	shift		; trigger and has not been recorded); do not
	goto	cleanup		; shift any further and go on with cleanup

shift
	bcf	status,c	; clear carry bit
	rlf	DATA_1,1	; left shift the 16-bit register DATA_2/DATA_1
	rlf	DATA_2,1	;

	call	delay_t1a	; aquire sample #1
	clrf	DATA_TMP1	; clear temporary register
	btfss	IR_C_out	; IR_C_out low?
	bsf	DATA_TMP1,0	; then set lsb in DATA_TMP1

	call	delay_t1b       ; aquire sample #2
	clrf	DATA_TMP2	; clear temporary register
	btfss	IR_C_out	; IR_C_out low?
	bsf	DATA_TMP2,0	; then set lsb in DATA_TMP2

check                           ; check if samples are equal
	movfw	DATA_TMP1	; copy DATA_1 to w,
	andlw	b'00000001'	; keep only lsb in w,
	xorwf	DATA_TMP2,0	; xor LSBs of DATA_TMP2 and w,
	btfss	status,z	; if not equal discard data and
	goto	set_flag	; goto set_flag -- no valid code has been received

	goto	pre_slope	; and loop

cleanup				; collected so far: DATA_2 000STAAA   DATA_1 AACCCCCC
	movfw	DATA_1		; copy DATA_1 to w
	andlw	b'00111111'	; clear bits 6 and 7
	movwf	RC5_CMD		; copy w to RC5_CMD

	btfsc	DATA_2,3	; toggle bit is 0?
	bsf	RC5_CMD,7	; if not, set bit 7 of RC5_CMD
	btfss	DATA_2,4	; 2nd start bit is 1?
	bsf	RC5_CMD,6	; if not, set bit 6 of RC5_CMD (extended RC5)

	rlf	DATA_2		; left shift two times
	rlf	DATA_2		;
	movfw	DATA_2		; copy DATA_2 to w
	andlw	b'00011100'	; clear 3 MSB and 2 LSB
	movwf	RC5_ADR		; and copy to RC5_ADR
	btfsc	DATA_1,6	; address bit 0 is 0?
	bsf	RC5_ADR,0	; if not, set bit 0 of RC5_ADR
	btfsc	DATA_1,7	; address bit 1 is 0?
	bsf	RC5_ADR,1	; if not, set bit 1 of RC5_ADR
				; now we have: RC5_ADR 000AAAAA    RC5_CMD TCCCCCCC
	bcf	RC5_Flag	; clear RC5_Flag -- valid code has been received

	return

set_flag
	bsf	RC5_Flag	; set RC5_Flag -- no valid code has been received
	return


;**************************************************************************************************
; EEPROM read/write subroutines
;**************************************************************************************************

write_ee
	Bank_0
	movfw	EEADR_TMP	; copy EEADR_TMP to eeadr
	Bank_1
	movwf	eeadr
	Bank_0
	movfw	EEDATA_TMP	; copy EEDATA_TMP to eedata
	Bank_1
	movwf	eedata
	bsf	eecon1,wren	; enable write
	movlw	h'55'		; eeprom write unlock sequence
	movwf	eecon2		;
	movlw	h'aa'		;
	movwf	eecon2		;
	bsf	eecon1,wr	; write

w_ready
	btfsc	eecon1,wr	; write completed?
	goto	w_ready		;
	Bank_0

	return

;--------------------------------------------------------------------------------------------------

copy_ee				; reads address and command for assigned remote power key
				; and turn on delay value from EEPROM and copies them to
				; the RAM registers PWR_KEY_ADR, PWR_KEY_CMD, and PWR_ON_DELAY
	Bank_1
	movlw	h'00'
	movwf	eeadr
	bsf	eecon1, rd
	movfw	eedata
	Bank_0
	movwf	PWR_ON_DELAY

	Bank_1
	movlw	h'01'
	movwf	eeadr
	bsf	eecon1, rd
	movfw	eedata
	Bank_0
	movwf	PWR_KEY_ADR

	Bank_1
	movlw	h'02'
	movwf	eeadr
	bsf	eecon1, rd
	movfw	eedata
	Bank_0
	movwf	PWR_KEY_CMD

	return

;**************************************************************************************************
; Delay routines (1 cycle equals 1祍 @ 4MC oscillator frequency)
;**************************************************************************************************

delay_t1a			; total: 1200 cycles
	movlw	0xEE		; 1193 cycles
	movwf	d1
	movlw	0x01
	movwf	d2
delay_t1a_0
	decfsz	d1, f
	goto	$+2
	decfsz	d2, f
	goto	delay_t1a_0

	goto	$+1		; 3 cycles
	nop
	return 			; 4 cycles (including call)

;----------------------------------------------------------

delay_t1b			; total: 320 cycles
	movlw	0x69            ; 316 cycles
	movwf	d1
delay_t1b_0
	decfsz	d1, f
	goto	delay_t1b_0

	return			; 4 cycles (including call)

;----------------------------------------------------------

delay_t2			; total: 500 cycles
	movlw	h'A5'		; 496 cycles
	movwf	D1
delay_5
	decfsz	D1,f
	goto	delay_5
	return			; 4 cycles (including call)

;----------------------------------------------------------

delay_t3			; total: 1255 cycles
	movlw	h'F9'		; 1248 cycles
	movwf	D1
	movlw	h'01'
	movwf	D2
delay_6
	decfsz	D1,f
	goto	$+2
	decfsz	D2,f
	goto	delay_6
	goto	$+1		; 3 cycles
	nop
	return			; 4 cycles (including call)

;----------------------------------------------------------

delay_t4			; total: 50000 cycles
				; 49993 cycles
	movlw	h'0E'
	movwf	D1
	movlw	h'28'
	movwf	D2
delay_7
	decfsz	D1,f
	goto	$+2
	decfsz	D2,f
	goto	delay_7
	goto	$+1		; 3 cycles
	nop
	return			; 4 cycles (including call)

;----------------------------------------------------------

delay_t5			; total: 886 cycles
	movlw	h'AF'		; 878 cycles
	movwf	D1
	movlw	h'01'
	movwf	D2
delay_8
	decfsz	D1,f
	goto	$+2
	decfsz	D2, f
	goto	delay_8
	goto	$+1		; 4 cycles
	goto	$+1
	return			; 4 cycles (including call)

;----------------------------------------------------------

delay_t6			; total: 250000 cycles
	movlw	h'4E'		; 249993 cycles
	movwf	D1
	movlw	h'C4'
	movwf	D2
delay_9
	decfsz	D1,f
	goto	$+2
	decfsz	D2, f
	goto	delay_9
	goto	$+1		; 3 cycles
	nop
	return			; 4 cycles (including call)

;----------------------------------------------------------
	end

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -