I have been working on a project for school. It involves PIC assembly programming. I use 44 pin demo board, PIC16F887.
I have to do an IR receiver which has a output that changes a LED brightness. I know so far I have to make a PWM control for that. However I am still struggling with decoding the buttons. I am using an emitter that has NEC coding. My input setup is digital, pulled up with internal resistor PORTB, 0. I am trying to polling the input with TMR0 interrupts.
System setup is 4MHz oscillator, TMR0 is incrementing every Osc/4. Prescaler is 1:2, So every 2μs the timer is incrementing 1. Timer0 preload is D’206’, so it is interrupting 50*2μs = 100μs. According to the NEC protocol Logic 0 has 562,5μs low, Logic 1 has 1687,5μs low signal, after a 562,5 HIGH signal.
So 1687.5μs /100μs = 16, and 562.5μs / 100 μs = 5. I was trying to subtract them out of 8. So I can check what does STATUS, ZERO bit is active or low.
I don’t know in which part I am going wrong. I will leave my code down below. This code has a LED blinking, while it supposed to set PORTD,0 LED on if volume+ button is pressed. So in this way I would know if I can detect the buttons, and work on the PWM.
Every answer is appreciated.
ISR: ;IF ISR GLOBAL INT 0
btfss INTCON,T0IF
retfie ;if there is no interrupt
banksel 0 ;ISR occur in Bank0
movwf W_save ;save WORK register's value
movf STATUS,W
movwf STATUS_save ;save STATUS register's value
call IR ;call IR
goto ISR_EXIT
ISR_EXIT:
bcf INTCON,T0IF ;TMR0 interrupt flag clear
movlw b'01100110' ;preload 206
movwf TMR0
movf STATUS_save,W
movwf STATUS ;STATUS register original value reload
swapf W_save,f ;WORK register original value reload
swapf W_save,W
retfie ;retfie -> global int = 1
IR:
btfss PORTB,0 ;testing IR input
bsf ir_reg,0 ;button was pressed
btfss ir_reg,0 ;button was pressed?
goto NO_BUTTON
btfsc PORTB,0 ;HIGH signal?
goto HIGH_P
btfss ir_reg,1 ;previous was HIGH?
goto HIGH_TO_LOW
incf time,f ;increment time
goto ISR_EXIT
HIGH_P:
btfsc ir_reg,1 ;was previous LOW?
goto LOW_TO_HIGH
incf time,f ;increment time
goto ISR_EXIT
HIGH_TO_LOW: ;transition between HIGH to LOW pulses
bsf PORTD,3
movf time,W
movwf high_pulse ;saving HIGH pulse's time
clrf time ;time variable clear
bcf ir_reg,1 ;previous pulse was HIGH
goto CALC
CALC:
movf high_pulse,W ;high pulse's time into Work
bcf STATUS,Z ;STATUS ZERO CLEAR
sublw D'10' ;LOW_P -> 5-10 = -5,HIGH_P - > 16-10 = 6
btfsc STATUS,Z ;if subtraction = +
bsf ir_reg,3 ;subtraction ended positive -> LOGIC 1
bcf ir_reg,3 ;subtraction ended negative -> LOGIC 0
goto ADD_BITS
ADD_BITS:
bsf PORTD,2
btfsc ir_reg,3 ;if LOGIC 1
bsf STATUS,C ;carry bit 1
bcf STATUS,C ;carry bit 0
goto ROTATE
ROTATE:
bsf PORTD,1
rlf naddress ;Carry is rotated to naddress LSB
rlf address ;naddress MSB rotated to address LSB through Carry
rlf ncommand ;address MSB rotated to ncommand LSB through Carry
rlf command ;ncommand MSB rotated to command LSB through Carry
incf pulses ;every time we have a rotation increment variable
movf pulses,W
bcf STATUS,Z ;status zero clear
sublw D'32' ;33-pulses,we have a decoded signal
btfss STATUS,Z ;if Zero set
goto ISR_EXIT ;goto NO_button
goto LED_FLASH
LED_FLASH:
movf command,W
bcf STATUS,Z
sublw b'10101000' ;+ button command: b'10101000'
btfss STATUS,Z
goto NO_BUTTON
bsf PORTD,0
goto ISR_EXIT
LOW_TO_HIGH: ;transition between LOW to HIGH pulses
movf time,W
movwf low_pulse ;saving LOW pulse's time
clrf time ;time variable clear
bsf ir_reg,1 ;previous pulse was LOW
goto ISR_EXIT
NO_BUTTON:
btfsc PORTB,0
goto ISR_EXIT
clrf pulses ;clearing variables
clrf ir_reg
clrf time
clrf address
clrf naddress
clrf address
clrf ncommand
clrf command
goto ISR_EXIT
INIT:
;OSCCON INIT
banksel OSCCON
movlw b'01100000' ;4Mhz oscillator
movwf OSCCON
;OUTPUT INIT
banksel TRISD
clrf TRISD ;TRISD OUTPUT
banksel PORTD
clrf PORTD ;PORTD LOW
;INPUT INIT
banksel TRISB
bsf TRISB,RB0 ;RB0 INPUT
bsf WPUB,RB0
movlw 0x00
banksel ANSELH
movwf ANSELH ;RB0 DIGITAL
call Delay
;OPTION REG INIT / TMR0
banksel OPTION_REG
movlw b'00000000' ;TMR0 prescale 1:2 increment every 2us
movwf OPTION_REG
movlw b'01100110' ;preload 206
movwf TMR0 ;50 tick until overflow 50*2us = 100us
;INTCON INIT
banksel INTCON
bcf INTCON,T0IF ;TMR0 overflow flag clear
bsf INTCON,T0IE ;TMR0 overflow enable
bsf INTCON,GIE ;global interrupt enable
return
MAIN:
call INIT
call FLASH ;LED FLASH
goto $-1
END