📄 红外线通信.txt
字号:
;Nigel Goodwin 2002
LIST p=16F628 ;tell assembler what chip we are using
include "P16F628.inc" ;include the defaults for the chip
ERRORLEVEL 0, -302 ;suppress bank selection messages
__config 0x3D18 ;sets the configuration settings (oscillator type etc.)
cblock 0x20 ;start of general purpose registers
count ;used in looping routines
count1 ;used in delay routine
counta ;used in delay routine
countb ;used in delay routine
LoX
Bit_Cntr
Cmd_Byte
Dev_Byte
Flags
Flags2
tmp1 ;temporary storage
tmp2
tmp3
lastdev
lastkey
endc
LED_PORT Equ PORTB
LED_TRIS Equ TRISB
IR_PORT Equ PORTA
IR_TRIS Equ TRISA
IR_In Equ 0x02 ;input assignment for IR data
OUT_PORT Equ PORTB
LED0 Equ 0x00
LED1 Equ 0x01
LED2 Equ 0x02
LED3 Equ 0x03
LED4 Equ 0x04
LED5 Equ 0x05
LED6 Equ 0x06
LED7 Equ 0x07
EEPROM_Addr Equ 0x00 ;address of EEPROM byte used
ErrFlag Equ 0x00
StartFlag Equ 0x01 ;flags used for received bit
One Equ 0x02
Zero Equ 0x03
New Equ 0x07 ;flag used to show key released
TV_ID Equ 0x01 ;TV device ID
But1 Equ 0x00 ;numeric button ID's
But2 Equ 0x01
But3 Equ 0x02
But4 Equ 0x03
But5 Equ 0x04
But6 Equ 0x05
But7 Equ 0x06
But8 Equ 0x07
But9 Equ 0x08
org 0x0000
goto Start
org 0x0004
retfie
Start movlw 0x07
movwf CMCON ;turn comparators off (make it like a 16F84)
Initialise clrf count
clrf PORTA
clrf PORTB
clrf Flags
clrf Dev_Byte
clrf Cmd_Byte
SetPorts bsf STATUS, RP0 ;select bank 1
movlw 0x00 ;make all LED pins outputs
movwf LED_TRIS
movlw b'11111111' ;make all IR port pins inputs
movwf IR_TRIS
bcf STATUS, RP0 ;select bank 0
call EE_Read ;restore previous settings
Main
call ReadIR ;read IR signal
call ProcKeys ;do something with commands received
goto Main ;loop for ever
ProcKeys
btfss Flags2, New
retlw 0x00 ;return if not new keypress
movlw TV_ID ;check for TV ID code
subwf Dev_Byte, w
btfss STATUS , Z
retlw 0x00 ;return if not correct code
movlw But1 ;test for button 1
subwf Cmd_Byte, w
btfss STATUS , Z
goto Key1 ;try next key if not correct code
movf LED_PORT, w ;read PORTB (for LED status)
movwf tmp3 ;and store in temp register
btfss tmp3, LED0 ;and test LED bit for toggling
bsf LED_PORT, LED0 ;turn on LED
btfsc tmp3, LED0
bcf LED_PORT, LED0 ;turn off LED
bcf Flags2, New ;and cancel new flag
call EE_Write ;save the settings
retlw 0x00
Key1 movlw But2 ;test for button 1
subwf Cmd_Byte, w
btfss STATUS , Z
goto Key2 ;try next key if not correct code
movf LED_PORT, w ;read PORTB (for LED status)
movwf tmp3 ;and store in temp register
btfss tmp3, LED1 ;and test LED bit for toggling
bsf LED_PORT, LED1 ;turn on LED
btfsc tmp3, LED1
bcf LED_PORT, LED1 ;turn off LED
bcf Flags2, New ;and cancel new flag
call EE_Write ;save the settings
retlw 0x00
Key2 movlw But3 ;test for button 1
subwf Cmd_Byte, w
btfss STATUS , Z
goto Key3 ;try next key if not correct code
movf LED_PORT, w ;read PORTB (for LED status)
movwf tmp3 ;and store in temp register
btfss tmp3, LED2 ;and test LED bit for toggling
bsf LED_PORT, LED2 ;turn on LED
btfsc tmp3, LED2
bcf LED_PORT, LED2 ;turn off LED
bcf Flags2, New ;and cancel new flag
call EE_Write ;save the settings
retlw 0x00
Key3 movlw But4 ;test for button 1
subwf Cmd_Byte, w
btfss STATUS , Z
goto Key4 ;try next key if not correct code
movf LED_PORT, w ;read PORTB (for LED status)
movwf tmp3 ;and store in temp register
btfss tmp3, LED3 ;and test LED bit for toggling
bsf LED_PORT, LED3 ;turn on LED
btfsc tmp3, LED3
bcf LED_PORT, LED3 ;turn off LED
bcf Flags2, New ;and cancel new flag
call EE_Write ;save the settings
retlw 0x00
Key4 movlw But5 ;test for button 1
subwf Cmd_Byte, w
btfss STATUS , Z
goto Key5 ;try next key if not correct code
movf LED_PORT, w ;read PORTB (for LED status)
movwf tmp3 ;and store in temp register
btfss tmp3, LED4 ;and test LED bit for toggling
bsf LED_PORT, LED4 ;turn on LED
btfsc tmp3, LED4
bcf LED_PORT, LED4 ;turn off LED
bcf Flags2, New ;and cancel new flag
call EE_Write ;save the settings
retlw 0x00
Key5 movlw But6 ;test for button 1
subwf Cmd_Byte, w
btfss STATUS , Z
goto Key6 ;try next key if not correct code
movf LED_PORT, w ;read PORTB (for LED status)
movwf tmp3 ;and store in temp register
btfss tmp3, LED5 ;and test LED bit for toggling
bsf LED_PORT, LED5 ;turn on LED
btfsc tmp3, LED5
bcf LED_PORT, LED5 ;turn off LED
bcf Flags2, New ;and cancel new flag
call EE_Write ;save the settings
retlw 0x00
Key6 movlw But7 ;test for button 1
subwf Cmd_Byte, w
btfss STATUS , Z
goto Key7 ;try next key if not correct code
movf LED_PORT, w ;read PORTB (for LED status)
movwf tmp3 ;and store in temp register
btfss tmp3, LED6 ;and test LED bit for toggling
bsf LED_PORT, LED6 ;turn on LED
btfsc tmp3, LED6
bcf LED_PORT, LED6 ;turn off LED
bcf Flags2, New ;and cancel new flag
call EE_Write ;save the settings
retlw 0x00
Key7 movlw But8 ;test for button 1
subwf Cmd_Byte, w
btfss STATUS , Z
retlw 0X00
movf LED_PORT, w ;read PORTB (for LED status)
movwf tmp3 ;and store in temp register
btfss tmp3, LED7 ;and test LED bit for toggling
bsf LED_PORT, LED7 ;turn on LED
btfsc tmp3, LED7
bcf LED_PORT, LED7 ;turn off LED
bcf Flags2, New ;and cancel new flag
call EE_Write ;save the settings
retlw 0x00
EE_Read bsf STATUS, RP0 ; Bank 1
movlw EEPROM_Addr
movwf EEADR ; Address to read
bsf EECON1, RD ; EE Read
movf EEDATA, W ; W = EEDATA
bcf STATUS, RP0 ; Bank 0
movwf LED_PORT ; restore previous value
retlw 0x00
EE_Write movf LED_PORT, w ; read current value
bsf STATUS, RP0 ; Bank 1
bsf EECON1, WREN ; Enable write
movwf EEDATA ; set EEPROM data
movlw EEPROM_Addr
movwf EEADR ; set EEPROM address
movlw 0x55
movwf EECON2 ; Write 55h
movlw 0xAA
movwf EECON2 ; Write AAh
bsf EECON1, WR ; Set WR bit
; begin write
bcf STATUS, RP0 ; Bank 0
btfss PIR1, EEIF ; wait for write to complete.
goto $-1
bcf PIR1, EEIF ; and clear the 'write complete' flag
bsf STATUS, RP0 ; Bank 1
bcf EECON1, WREN ; Disable write
bcf STATUS, RP0 ; Bank 0
retlw 0x00
;IR routines
ReadIR call Read_Pulse
btfss Flags, StartFlag
goto ReadIR ;wait for start pulse (2.4mS)
Get_Data movlw 0x07 ;set up to read 7 bits
movwf Bit_Cntr
clrf Cmd_Byte
Next_RcvBit2 call Read_Pulse
btfsc Flags, StartFlag ;abort if another Start bit
goto ReadIR
btfsc Flags, ErrFlag ;abort if error
goto ReadIR
bcf STATUS , C
btfss Flags, Zero
bsf STATUS , C
rrf Cmd_Byte , f
decfsz Bit_Cntr , f
goto Next_RcvBit2
rrf Cmd_Byte , f ;correct bit alignment for 7 bits
Get_Cmd movlw 0x05 ;set up to read 5 bits
movwf Bit_Cntr
clrf Dev_Byte
Next_RcvBit call Read_Pulse
btfsc Flags, StartFlag ;abort if another Start bit
goto ReadIR
btfsc Flags, ErrFlag ;abort if error
goto ReadIR
bcf STATUS , C
btfss Flags, Zero
bsf STATUS , C
rrf Dev_Byte , f
decfsz Bit_Cntr , f
goto Next_RcvBit
rrf Dev_Byte , f ;correct bit alignment for 5 bits
rrf Dev_Byte , f
rrf Dev_Byte , f
retlw 0x00
;end of ReadIR
;read pulse width, return flag for StartFlag, One, Zero, or ErrFlag
;output from IR receiver is normally high, and goes low when signal received
Read_Pulse clrf LoX
btfss IR_PORT, IR_In ;wait until high
goto $-1
clrf tmp1
movlw 0xC0 ;delay to decide new keypress
movwf tmp2 ;for keys that need to toggle
Still_High btfss IR_PORT, IR_In ;and wait until goes low
goto Next
incfsz tmp1,f
goto Still_High
incfsz tmp2,f
goto Still_High
bsf Flags2, New ;set New flag if no button pressed
goto Still_High
Next nop
nop
nop
nop
nop ;waste time to scale pulse
nop ;width to 8 bits
nop
nop
nop
nop
nop
nop
incf LoX, f
btfss IR_PORT, IR_In
goto Next ;loop until input high again
; test if Zero, One, or Start (or error)
Chk_Pulse clrf Flags
TryError movf LoX, w ; check if pulse too small
addlw d'255' - d'20' ; if LoX <= 20
btfsc STATUS , C
goto TryZero
bsf Flags, ErrFlag ; Error found, set flag
retlw 0x00
TryZero movf LoX, w ; check if zero
addlw d'255' - d'60' ; if LoX <= 60
btfsc STATUS , C
goto TryOne
bsf Flags, Zero ; Zero found, set flag
retlw 0x00
TryOne movf LoX, w ; check if one
addlw d'255' - d'112' ; if LoX <= 112
btfsc STATUS , C
goto TryStart
bsf Flags, One ; One found, set flag
retlw 0x00
TryStart movf LoX, w ; check if start
addlw d'255' - d'180' ; if LoX <= 180
btfsc STATUS , C
goto NoMatch
bsf Flags, StartFlag ; Start pulse found
retlw 0x00
NoMatch ; pulse too long
bsf Flags, ErrFlag ; Error found, set flag
retlw 0x00
;end of pulse measuring routines
;Delay routines
Delay255 movlw 0xff ;delay 255 mS
goto d0
Delay100 movlw d'100' ;delay 100mS
goto d0
Delay50 movlw d'50' ;delay 50mS
goto d0
Delay20 movlw d'20' ;delay 20mS
goto d0
Delay5 movlw 0x05 ;delay 5.000 ms (4 MHz clock)
d0 movwf count1
d1 movlw 0xC7
movwf counta
movlw 0x01
movwf countb
Delay_0 decfsz counta, f
goto $+2
decfsz countb, f
goto Delay_0
decfsz count1 ,f
goto d1
retlw 0x00
;end of Delay routines
end
The EEPROM data is accessed by two new routines, EE_Read and EE_Write, the EE_Read routine is called as the program powers up, before we enter the main loop, and the EE_Write routine is called after every LED change. The EE_Read routine is very straightforward, we simply set the address we wish to read in the EEADR register, set the RD flag in the EECON1 register, and then read the data from the EEDATA register. Writing is somewhat more complicated, for a couple of reasons:
Microchip have taken great care to prevent accidental or spurious writes to the data EEPROM. In order to write to it we first have to set the 'Write Enable' bit in the EECON1 register, and then make two specific writes (0x55 and 0xAA) to the EECON2 register, only then can we set the WR bit in EECON1 and start the actual writing. One of the most common problems in domestic electronics today is data EEPROM corruption, hopefully the efforts of Microchip will prevent similar problems with the 16F628.
Writing to EEPROM takes time, so we have to wait until the 'Write Complete' flag is set, it doesn't really matter in this application as the time spent waiting for the next IR command gives more than enough time to write to the data EEPROM, but it's good practice to do it anyway.
The extra work involved makes the EE_Write routine a lot longer than the EE_Read routine, it also doesn't help that we need to access registers in different banks, so we do a fair bit of bank switching.
--------------------------------------------------------------------------------
http://www.winpicprog.co.uk/pic_tutorial5.htm
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -