【发布时间】:2020-05-24 14:19:12
【问题描述】:
我一直在为学校做一个项目。它涉及 PIC 汇编编程。我使用 44 针演示板,PIC16F887。
我必须做一个红外接收器,它的输出可以改变 LED 的亮度。到目前为止,我知道我必须为此进行 PWM 控制。但是我仍在努力解码按钮。 我正在使用具有 NEC 编码的发射器。我的输入设置是数字的,通过内部电阻 PORTB 上拉,0。我正在尝试使用 TMR0 中断轮询输入。
系统设置为 4MHz 振荡器,TMR0 每 Osc/4 递增一次。预分频比为 1:2,因此定时器每 2μs 递增 1。Timer0 预载为 D'206',因此中断 50*2μs = 100μs。根据 NEC 协议,逻辑 0 有 562,5μs 低电平,逻辑 1 有 1687,5μs 低电平信号,经过 562,5 高电平信号。
所以 1687.5μs /100μs = 16,562.5μs / 100 μs = 5。我试图从 8 中减去它们。所以我可以检查什么是 STATUS,ZERO 位是活动的还是低的。
我不知道我错在哪一部分。我将把我的代码留在下面。此代码有一个 LED 闪烁,如果按下音量+按钮,它应该设置 PORTD,0 LED 亮起。所以通过这种方式我会知道我是否可以检测到按钮,并在 PWM 上工作。
感谢每一个答案。
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
【问题讨论】:
-
贴出的代码有bug。 --首先-- 它不是一个可以使用Microchip工具构建的完整程序文件。要解决这个问题,至少需要对所有配置字位进行初始化。 --第二-- 中断向量处理实现错误。这将导致程序失败。 --第三-- 您需要更好地理解 NEC 红外协议。请参阅:Vishay IR protocols 和 NEC IR protocol WB_IRRC。
标签: assembly project pic receiver infrared