Телесистемы
 Разработка, производство и продажа радиоэлектронной аппаратуры
На главную   | Карта сайта | Пишите нам | В избранное
Требуется программист в Зеленограде
- обработка данных с датчиков; ColdFire; 40 тыс.
e-mail:jobsmp@pochta.ru

Телесистемы | Электроника | Конференция «Микроконтроллеры и их применение»

Ответ: готовая программа

Отправлено djn 01 августа 2007 г. 20:21
В ответ на: Приходилось ли кому-нибудь сталкиваться с декодированием сигналов с пультов дистанционного управления по протоколу NEC? Может, есть уже готовые решения? отправлено <font color=gray>Sergey_B</font> 01 августа 2007 г. 16:07

.LF PIC-NEC.LST
;-----------------------------------------------------------------------------
; PIC-NEC.ASM
;
; PIC NEC IR Receiver
;
; Program and hardware made by: San Bergmans Oisterwijk
; October 2004
; www.sbprojects.com
; Using the free SB-Assembler
;-----------------------------------------------------------------------------

.CR 16CXXX Use the PIC 16CXXX cross (16F84)
.TF PIC-NEC.HEX,INT

;-----------------------------------------------------------------------------
; Special function file register definition
;-----------------------------------------------------------------------------

INDF .EQ $00 Indirect register
TMR0 .EQ $01 Timer 0 value
PCL .EQ $02 Lower order 8 bits of PC
STATUS .EQ $03 Status flag register
FSR .EQ $04 File select register
PORTA .EQ $05 I/O port A
PORTB .EQ $06 I/O port B
EEDATA .EQ $08 EEPROM data register
EEADR .EQ $09 EEPROM address register
PCLATCH .EQ $0A Upper 5 bits of PC
INTCON .EQ $0B Interrupt control

OPTION .EQ $81 Option flag register
TRISA .EQ $85 Output direction register A
TRISB .EQ $86 Output direction register B
EECON1 .EQ $88 EEPROM control register 1
EECON2 .EQ $89 EEPROM control register 2

;-----------------------------------------------------------------------------
; Special function bit location definition
;-----------------------------------------------------------------------------

; STATUS register
CARRY .EQ 0 Carry flag
DCARRY .EQ 1 Decimal carry flag
ZERO .EQ 2 Zero flag
PD .EQ 3 Inverted power down bit
TO .EQ 4 Inverted time out bit
RP0 .EQ 5 Register bank pointer 0
RP1 .EQ 6 Register bank pointer 1
IRP .EQ 7 Indirect register bank pointer

; OPTION register
PS0 .EQ 0 Pre-scaler value 0
PS1 .EQ 1 Pre-scaler value 1
PS2 .EQ 2 Pre-scaler value 2
PSA .EQ 3 Pre-scaler assign bit
T0SE .EQ 4 Timer 0 source edge select bit
T0CS .EQ 5 Timer 0 clock source select bit
INTEDG .EQ 6 Interrupt edge select bit
RBPU .EQ 7 Port B pull up enable bit

; INTCON register
RBIF .EQ 0 RB port change interrupt flag bit
INTF .EQ 1 External interrupt flag bit
T0IF .EQ 2 Timer 0 overflow interrupt flag bit
RBIE .EQ 3 RB port change interrupt enable bit
INTE .EQ 4 INT interrupt enable bit
T0IE .EQ 5 Timer 0 interrupt enable bit
EEIE .EQ 6 EE write complete interrupt enable bit
GIE .EQ 7 Global interrupt enable bit

;-----------------------------------------------------------------------------
; File register declarations
;-----------------------------------------------------------------------------

SCAN_STATE .EQ $0C Scan state pointer
DIGIT1 .EQ $0D Pattern of left most digit
DIGIT2 .EQ $0E
DIGIT3 .EQ $0F
DIGIT4 .EQ $10 Pattern of right most digit
SCAN_DELAY .EQ $11 Scan delay counter (5ms pace)
CLR_DELAY .EQ $12 Display clear delay counter
DP_DELAY .EQ $13 Decimal point delay counter
IR_STATE .EQ $14 IR receiver state machine
BIT_TIMER .EQ $15 Bit timer
IR_SHIFT .EQ $16,$17,$18,$19 IR shift register

;-----------------------------------------------------------------------------
; Constants
;-----------------------------------------------------------------------------

TIMER_UPDATE .EQ -50+3 Timer update value (2 dead cycles)
MS5_COUNT .EQ 100 Number of counts to 5ms
CLR_TIME .EQ 100 Display clear timeout (20ms/count)
DP_TIME .EQ 3 Decimal point timeout (20ms/count)

BIT_TIME .EQ 1100/50 Basic bit time in 50us units
PULSE_MAX .EQ 650/50 Maximum pulse width

;-----------------------------------------------------------------------------
; Reset vector
;-----------------------------------------------------------------------------

RESET GOTO INIT Get the system going

;-----------------------------------------------------------------------------
; Segment patterns
;-----------------------------------------------------------------------------

HEX2SEGMENTS ANDLW %0000.1111 Use only lower nibble
ADDWF PCL,F Add offset to current PC

SEGMENTS RETLW %1100.0000 0
RETLW %1111.1001 1
RETLW %1010.0100 2
RETLW %1011.0000 3
RETLW %1001.1001 4
RETLW %1001.0010 5
RETLW %1000.0010 6
RETLW %1111.1000 7
RETLW %1000.0000 8
RETLW %1001.0000 9
RETLW %1000.1000 A
RETLW %1000.0011 B
RETLW %1100.0110 C
RETLW %1010.0001 D
RETLW %1000.0110 E
RETLW %1000.1110 F

;-----------------------------------------------------------------------------
; Scan display routine
;-----------------------------------------------------------------------------

SCAN_DISP MOVLW MS5_COUNT Reload scan delay
MOVWF SCAN_DELAY
MOVLW %1111.1111 Switch off all Anode drivers
MOVWF PORTA during the switch
MOVF SCAN_STATE,W Jump to next display's routine
MOVWF PCL

;-------------------------------------------------------------SCAN DISPLAY 1--

SCAN_DISP1 MOVF DIGIT1,W Get pattern of left most digit
MOVWF PORTB and send it out
MOVLW %1111.1110 Switch left most digit on
MOVWF PORTA
MOVLW #SCAN_DISP2 Next time do SCAN_DISP2
MOVWF SCAN_STATE
RETURN

;-------------------------------------------------------------SCAN DISPLAY 2--

SCAN_DISP2 MOVF DIGIT2,W Get pattern of 2nd left digit
MOVWF PORTB and send it out
MOVLW %1111.1101 Switch 2nd left digit on
MOVWF PORTA
MOVLW #SCAN_DISP3 Next time do SCAN_DISP3
MOVWF SCAN_STATE

DECF DP_DELAY,F Decrement DP_DELAY every 20ms
BTFSS STATUS,ZERO
RETURN We're done if counter <> 0 !

BSF DIGIT2,7 Clear Digit 2's decimal point now
RETURN

;-------------------------------------------------------------SCAN DISPLAY 3--

SCAN_DISP3 MOVF DIGIT3,W Get pattern of 2nd right digit
MOVWF PORTB and send it out
MOVLW %1111.1011 Switch 2nd right digit on
MOVWF PORTA
MOVLW #SCAN_DISP4 Next time do SCAN_DISP3
MOVWF SCAN_STATE
RETURN

;-------------------------------------------------------------SCAN DISPLAY 4--

SCAN_DISP4 MOVF DIGIT4,W Get pattern of right most digit
MOVWF PORTB and send it out
MOVLW %1111.0111 Switch right most digit on
MOVWF PORTA
MOVLW #SCAN_DISP1 Next time do SCAN_DISP1 again
MOVWF SCAN_STATE

DECF CLR_DELAY,F Decrement CLR_DELAY every 20ms
BTFSS STATUS,ZERO
RETURN We're done if counter <> 0 !

MOVLW %1011.1111 Only display 4 dashes
MOVWF DIGIT1
MOVWF DIGIT2
MOVWF DIGIT3
MOVWF DIGIT4
RETURN

;-----------------------------------------------------------------------------
; IR receiver state machine
;-----------------------------------------------------------------------------

IR_MACHINE MOVF IR_STATE,W Jump to present state
MOVWF PCL

;---------------------------------------STATE 0, WAIT FOR FIRST FALLING EDGE--

IR_STATE_0 BTFSC PORTA,4 Input still high?
RETURN Yes! Nothing to do here

CLRF IR_SHIFT Prepare shift register
CLRF IR_SHIFT+1
CLRF IR_SHIFT+2
MOVLW %1000.0000
MOVWF IR_SHIFT+3
CLRF BIT_TIMER Clear bit timer
MOVLW IR_STATE_1 Next stop is state 1
MOVWF IR_STATE
RETURN

;-------------------------IR STATE 1, LET'S SEE IF THIS IS THE 9MS PRE-PULSE--

IR_STATE_1 INCF BIT_TIMER Increment bit timer
BTFSC PORTA,4 Input still low?
GOTO .HIGH Nope!

MOVLW 9900/50*-1 Longer than 9ms + 10% low?
ADDWF BIT_TIMER,W
BTFSS STATUS,ZERO
RETURN No, OK!

MOVLW IR_ERROR_0 Wait until input returns high
MOVWF IR_STATE and then start all over again
RETURN

.HIGH MOVLW 8100/50*-1 See if length was at least 9ms - 10%
ADDWF BIT_TIMER,W
BTFSS STATUS,CARRY Carry will be set if it was
GOTO IR_ERROR_1 Exit with error if it wasn't

MOVLW IR_STATE_2 Next stop measure the length of the
MOVWF IR_STATE gap between pre-pulse & message
CLRF BIT_TIMER
RETURN

;--------------------------STATE 2, PRE-PULSE DETECTED, NOW MEASURE GAP TIME--

IR_STATE_2 INCF BIT_TIMER Increment bit timer
BTFSS PORTA,4 Input still high?
GOTO .LOW Nope!

MOVLW 4950/50*-1 Longer than 4.5ms + 10% high?
ADDWF BIT_TIMER,W
BTFSS STATUS,ZERO
RETURN No, OK!

GOTO IR_ERROR_1 We give up!
RETURN

.LOW MOVLW 3350/50*-1 See if it was a long or short pause
ADDWF BIT_TIMER,W

MOVLW IR_STATE_4 Let's get the message if it was a long
BTFSS STATUS,CARRY one (if Carry is set)
MOVLW IR_STATE_3 It was a short one! It's a repetition!

MOVWF IR_STATE
CLRF BIT_TIMER
RETURN

;----------STATE 3, REPETITION DETECTED, LET'S SEE IF DISPLAY IS STILL VALID--

IR_STATE_3 MOVLW IR_STATE_8 Next state will be 8 anyway, so let's
MOVWF IR_STATE set it now

MOVLW %1011.1111 See if display time still valid
XORWF DIGIT1,W
BTFSC STATUS,ZERO
RETURN No! Forget about the repetition then

MOVLW CLR_TIME Restart display stimer
MOVWF CLR_DELAY
MOVLW DP_TIME And also flash the DP
MOVWF DP_DELAY
BCF DIGIT2,7

RETURN

;--------------------------------STATE 4, INPUT IS LOW, MUST BE A PULSE THEN--

IR_STATE_4 INCF BIT_TIMER Increment bit timer
BTFSC PORTA,4 Input still low?
GOTO .HIGH No! Pulse is over now.

MOVLW PULSE_MAX See if max pulse width reached
XORWF BIT_TIMER,W
BTFSS STATUS,ZERO
RETURN Not yet!

MOVLW IR_ERROR_0 Wait until pulse goes high again
MOVWF IR_STATE before accepting new command
RETURN

.HIGH MOVLW IR_STATE_5 Input is now high
MOVWF IR_STATE Next stop is state 2
RETURN

;-------------STATE 5, WAIT FOR PULSE TO GO LOW AGAIN, THEN MEASURE INTERVAL--

IR_STATE_5 INCF BIT_TIMER Increment bit timer
MOVLW BIT_TIME*3 Should we keep waiting?
XORWF BIT_TIMER,W
BTFSC STATUS,ZERO
GOTO IR_ERROR_1 No, we've waited 3 bit times already!

BTFSC PORTA,4
RETURN Keep waiting while input remains high

MOVLW BIT_TIME/2+BIT_TIME*-1 Use 1.5 bit time as threshold
ADDWF BIT_TIMER,W Carry is 1 if more than 1.5 times

RRF IR_SHIFT+3,F Roll carry into result
RRF IR_SHIFT+2,F
RRF IR_SHIFT+1,F
RRF IR_SHIFT,F

CLRF BIT_TIMER Restart bit timer
MOVLW IR_STATE_4 Return to state 1 if not done yet
MOVWF IR_STATE

BTFSS STATUS,CARRY See if we're done
RETURN Not done yet, continue with state 1

MOVLW IR_STATE_6 Message received, but wait 3ms longer
MOVWF IR_STATE to see if nothing follows.
CLRF BIT_TIMER
RETURN

;-------------------STATE 6, RECEIVED MESSAGE, WAIT 3MS TO ENSURE IT WAS NEC--

IR_STATE_6 INCF BIT_TIMER Increment bit timer
BTFSC PORTA,4 Input still low?
GOTO .HIGH No! Pulse is over now.

MOVLW PULSE_MAX See if max pulse width reached
XORWF BIT_TIMER,W
BTFSS STATUS,ZERO
RETURN Not yet!

MOVLW IR_ERROR_0 Wait until pulse goes high again
MOVWF IR_STATE before accepting new command
RETURN

.HIGH MOVLW IR_STATE_7 Input is now high
MOVWF IR_STATE Continue with 3ms delay
RETURN

;---------------------------STATE 7, INPUT MUST REMAIN HIGH FOR AT LEAST 3MS--

IR_STATE_7 INCF BIT_TIMER Increment bit timer

BTFSS PORTA,4 Has the input gone low now?
GOTO .ERROR Yes! This is not good!

MOVLW BIT_TIME*3 Have we waited long enough now?
XORWF BIT_TIMER,W
BTFSS STATUS,ZERO
RETURN Not yet!

MOVLW CLR_TIME Set display clear timer
MOVWF CLR_DELAY


MOVLW DP_TIME Flash receive LED
MOVWF DP_DELAY

SWAPF IR_SHIFT,W Work from left to right
CALL HEX2SEGMENTS
MOVWF DIGIT1

MOVF IR_SHIFT,W Do the same with 2nd digit
CALL HEX2SEGMENTS
ANDLW %0111.1111 Flash dot of this digit
MOVWF DIGIT2

SWAPF IR_SHIFT+2,W And with the 3d digit
CALL HEX2SEGMENTS
MOVWF DIGIT3

MOVF IR_SHIFT+2,W And finally with the last digit
CALL HEX2SEGMENTS
MOVWF DIGIT4

MOVF IR_SHIFT,W Compare normal and inserted codes
ADDWF IR_SHIFT+1,F
INCF IR_SHIFT+1,F
MOVF IR_SHIFT+2,W
INCF IR_SHIFT+3,F
ADDWF IR_SHIFT+3,W
IORWF IR_SHIFT+1,W Result should be 0 now!

BTFSS STATUS,ZERO Did the checksum match?
BCF DIGIT4,7 Light right DP if it didn't

MOVLW IR_STATE_0 We're done! Let's get some rest
MOVWF IR_STATE
RETURN

.ERROR MOVLW IR_ERROR_0 Wait until input gets high again
MOVWF IR_STATE before returning to state 0
RETURN

;-------------------------------------STATE 8, WAIT FOR INPUT TO RETURN HIGH--

IR_STATE_8
IR_ERROR_0 MOVLW IR_STATE_0 Reset state machine only if input is
BTFSC PORTA,4 high
MOVWF IR_STATE
RETURN

;-----------------------------------------------------------IR ERROR STATE 1--

IR_ERROR_1 MOVLW IR_STATE_0 Return to IR state 0
MOVWF IR_STATE

RETURN

;-----------------------------------------------------------------------------
; Get started
;-----------------------------------------------------------------------------

INIT MOVLW #$0D Clear memory
MOVWF FSR
MOVLW #35 Clear a total of 36 RAM addresses
MOVWF $0C
.CLRMEM CLRF INDF Clear this address
INCF FSR Increment pointer
DECFSZ $0C Decrement counter
GOTO .CLRMEM Repeat until done

BSF STATUS,RP0 Select bank 1 of register file
MOVLW #%1101.1111 Timer mode without pre-scaler
MOVWF OPTION
MOVLW #%0001.0000 Only PA4 is an input
MOVWF TRISA
MOVLW #%0000.0000 All Port B are outputs
MOVWF TRISB
BCF STATUS,RP0 Select bank 0 of register file

MOVLW #%0000.0000 Disable all interrupts
MOVWF INTCON

MOVLW IR_STATE_0 Init IR receiver state machine
MOVWF IR_STATE

MOVLW #SCAN_DISP1 Init display scan state
MOVWF SCAN_STATE

CLRF PCLATCH All indirect jumps are on page 0!

MOVLW TIMER_UPDATE Get the timer started
MOVWF TMR0
MOVLW MS5_COUNT Start 5ms counter for display scan
MOVWF SCAN_DELAY

MOVLW %1010.1011 Show NEC on display
MOVWF DIGIT1
MOVLW %1000.0110
MOVWF DIGIT2
MOVLW %1010.0111
MOVWF DIGIT3
MOVLW %1111.1111
MOVWF DIGIT4
MOVLW 200 Set clear time-out to 4 seconds
MOVWF CLR_DELAY

;-----------------------------------------------------------------------------
; Main program loop
;-----------------------------------------------------------------------------

MAIN

;-----------------------------------------CALL THE IR RECEIVER STATE MACHINE--

CALL IR_MACHINE Call the IR receiver state machine

;-----------------------------------------------------SCAN DISPLAY EVERY 5MS--

DECF SCAN_DELAY,F Decrement scan delay counter
BTFSC STATUS,ZERO Only scan display if counter = 0
CALL SCAN_DISP

;-------------------------------------------------------SYNC MAIN WITH TIMER--

.SYNC BTFSC TMR0,7 Wait until bit 7 of TMR = 0
GOTO .SYNC Not 0 yet!
MOVLW TIMER_UPDATE Reload timer again
ADDWF TMR0,F

GOTO MAIN

;-----------------------------------------------------------------------------
; Configuration word
;-----------------------------------------------------------------------------

.OR $2007
.CW XT
; .LI OFF



Составить ответ | Вернуться на конференцию

Ответы


Отправка ответа
Имя*: 
Пароль: 
E-mail: 
Тема*:

Сообщение:

Ссылка на URL: 
URL изображения: 

если вы незарегистрированный на форуме пользователь, то
для успешного добавления сообщения заполните поле, как указано ниже:
умножьте 2 на три:

Перейти к списку ответов | Конференция | Раздел "Электроника" | Главная страница | Карта сайта

Rambler's Top100 Рейтинг@Mail.ru
 
Web telesys.ru