PIC 端口模拟 红外通讯 38K调制 1200bps 偶校验 半双工
最近写了个小程序,贴出来大家分享
考虑到有些场合同时需要232(485),和红外,PIC16F87x系列单片机只有一个UART模块,因而用端口模拟红外通讯有它的用武之地。当然,如果仅仅是红外通讯那完全可以用
UART模块,38K调制载波可用PWM生成,这样可简化设计。
PIC 端口模拟 红外通讯 38K调制 1200bps 偶校验 半双工 适用于16F7X 16F87X
INT_Serv ;单片机自动清GIE
movwf W_Temp ;save W
swapf STATUS,W ;save STATUS
movwf STATUS_Temp
swapf FSR,W ;save FSR
movwf FSR_Temp
;红外接收中断
banksel INTCON ;RB0 interrupt
btfsc INTCON,INTF
call INT_Serv_IR_RX
swapf FSR_Temp,W ;restore FSR
movwf FSR
swapf STATUS_Temp,W ;restore STATUS
movwf STATUS
swapf W_Temp,F ;restore W
swapf W_Temp,W
retfie
;-----------------------------------------------------
;函数名:INT_Serv_IR_RX()
;函数功能:RB0红外数据中断接收子程序(0唤醒)
;函数入口参数:IR_Data_ADD,IR_Data_Length,注意中断中间变量INT_Loop_Temp3,INT_Loop_Temp4,IR_Data_Temp INT_Loop_Temp2
;函数出口参数:无
;-----------------------------------------------------
INT_Serv_IR_RX
banksel INTCON
;bcf INTCON,INTE ;Disable RB0 interrupt
bcf INTCON,INTF ;clear interrutpt flag
;-----------------------------------
movlw D'59' ;wait start
movwf INT_Loop_Temp3
IR_RX_Start_Wait1
nop
nop
nop
nop
decfsz INT_Loop_Temp3,F
goto IR_RX_Start_Wait1
btfsc PORTB,IR_RX ;再一次检测起始位 数据中间采样,有待于改进 59*7+4+59*7+3=833us ---> 1200bps
goto IR_RX_END
movlw D'59' ;wait start
movwf INT_Loop_Temp3
IR_RX_Start_Wait2
nop
nop
nop
nop
decfsz INT_Loop_Temp3,F
goto IR_RX_Start_Wait2
;-----------------------------------
movlw D'8' ;8位数据
movwf INT_Loop_Temp4
clrf INT_Loop_Temp2
IR_RX_lp1
movlw D'58' ;数据中间采样,有待于改进 58*7+7+4+59*7+3=833us ---> 1200bps
movwf INT_Loop_Temp3
IR_RX_Data_Wait1
nop
nop
nop
nop
decfsz INT_Loop_Temp3,F
goto IR_RX_Data_Wait1
incf INT_Loop_Temp2,F ;1的个数,为校验准备 (9月9号)
btfss PORTB,IR_RX
decf INT_Loop_Temp2,F
nop
nop
nop
nop
bcf STATUS,C
btfsc PORTB,IR_RX
bsf STATUS,C
rrf IR_Data_Temp,F ;先收低位!!!!!!!!!!
movlw D'59'
movwf INT_Loop_Temp3
IR_RX_Data_Wait2
nop
nop
nop
nop
decfsz INT_Loop_Temp3,F
goto IR_RX_Data_Wait2
decfsz INT_Loop_Temp4,F
goto IR_RX_lp1 ;一字节完毕
;----------------------------
movlw D'59' ;接收校验位,数据中间采样,有待于改进 59*7+4+59*7+3=833us ---> 1200bps (9月9号)
movwf INT_Loop_Temp3
IR_RX_E_Wait1
nop
nop
nop
nop
decfsz INT_Loop_Temp3,F
goto IR_RX_E_Wait1
incf INT_Loop_Temp2,F
btfss PORTB,IR_RX
decf INT_Loop_Temp2,F
nop
movlw D'59'
movwf INT_Loop_Temp3
IR_RX_E_Wait2
nop
nop
nop
nop
decfsz INT_Loop_Temp3,F
goto IR_RX_E_Wait2
;-------------------------------
movlw D'109' ;等待停止位,并给出10*7个周期用于处理下面的指令,方便接收连续数据.但规约规定,byte之间至少间隔12ms
movwf INT_Loop_Temp3
IR_RX_Stop_Wait
nop
nop
nop
nop
decfsz INT_Loop_Temp3,F
goto IR_RX_Stop_Wait
;------------------------------
btfsc Flags,Flag_Receive_Frame ;存在没有被处理过的数据帧,拒绝新帧。 (9月2号)
goto IR_RX_END
btfsc INT_Loop_Temp2,0 ;如有奇偶校验加在这里,C保留了校验位。(9月9号)
goto IR_ECheck_Error ;1个数为奇,丢帧
;如果接收的数据过长要加出错处理,否则可能影响RAM其他区域的寄存器数据!(待完善)
movf IR_Data_Temp,W
xorlw 0xFE
btfsc STATUS,Z
goto IR_Receive_FEH
btfss Flags,Flag_FEH ;Flag_FEH=0 end
goto IR_RX_END
xorlw 0x16^0xFE
btfsc STATUS,Z
goto IR_Receive_END
goto IR_Save_Data
IR_Receive_FEH ;数据中间出现FEH如何?
bsf Flags,Flag_FEH
clrf IR_Data_Length
goto IR_RX_END
IR_Receive_END
bsf Flags,Flag_Receive_Frame ;数据中间出现16H如何?
bcf Flags,Flag_FEH
bsf Flags,Flag_IR_Frame ;IR Received frame
;goto INT_Serv_485_END ;also save end
IR_Save_Data
movlw IR_Data_ADD
movwf FSR
movf IR_Data_Length,W
addwf FSR,F
movf IR_Data_Temp,W
movwf INDF
incf IR_Data_Length,F ;增加接收数据个数
IR_RX_END
bsf INTCON,INTE ;enable RB0 interrupt
return
IR_ECheck_Error
bcf Flags,Flag_FEH
bsf INTCON,INTE ;enable RB0 interrupt
return
;-----------------------------------------------------
;函数名:Delay_20ms()
;函数功能:485字节间发送延时
;函数入口参数:Delay2
;函数出口参数:无
;-----------------------------------------------------
Delay
banksel Delay1
clrf Delay1
Delay_lp1
decfsz Delay1,F
goto Delay_lp1 ;(256*3+3)*25
decfsz Delay2,F
goto Delay_lp1
return
;-----------------------------------------------------
;函数名:Initial_IR()
;函数功能:初始化红外
;函数入口参数:无
;函数出口参数:无
;-----------------------------------------------------
Initial_IR
bsf STATUS,RP0
bcf TRISC,IR_TX ;output
bsf TRISB,IR_RX ;input
bcf STATUS,RP0
bcf PORTC,IR_TX ;no TX
bcf Flags,Flag_Receive_Frame
clrf IR_Data_Length ;clear Data_Number
bsf INTCON,INTE ;enable RB0(IR_RX) interrupt !!!!!!
bsf STATUS,RP0 ;bank1
bcf OPTION_REG,INTEDG ;down endage
bcf STATUS,RP0 ;bank0
return
;-----------------------------------------------------
;函数名:IR_Send_Byte()
;函数功能:红外字节发送
;函数入口参数:IR_Data_Temp(待发送数据)
;函数出口参数:无
;-----------------------------------------------------
IR_Send_Byte
movlw D'9'
movwf Loop_Temp1
clrf Loop_Temp4 ;保存1的个数
goto IR_Send_0 ;起始位
IR_Send_Data_lp1
rrf IR_Data_Temp,F ;先发低位!!!!!!!!1
btfss STATUS,C
goto IR_Send_0
goto IR_Send_1
IR_Send_0
movlw D'32' ;32*26us=1200Hz
movwf Loop_Temp2
IR_38K ;26uS=38K
bsf PORTC,IR_TX ;7+1=8
nop
nop
nop
nop
nop
nop
nop
bcf PORTC,IR_TX ;14+1+2+1=18
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
decfsz Loop_Temp2,F
goto IR_38K
goto IR_Send_Next
IR_Send_1
bcf PORTC,IR_TX ;~ 119*(4+1+2)=833us=1200Hz
movlw D'119'
movwf Loop_Temp2
incf Loop_Temp4,F
IR_Send_1_Delay
nop
nop
nop
nop
decfsz Loop_Temp2,F
goto IR_Send_1_Delay
IR_Send_Next
decfsz Loop_Temp1,F
goto IR_Send_Data_lp1
;----------------------------------
;发送校验位
btfsc Loop_Temp4,0
goto IR_Send_E1
IR_Send_E0
movlw D'32' ;32*26us=1200Hz
movwf Loop_Temp2
IR_E38K ;26uS=38K
bsf PORTC,IR_TX ;7+1=8
nop
nop
nop
nop
nop
nop
nop
bcf PORTC,IR_TX ;14+1+2+1=18
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
decfsz Loop_Temp2,F
goto IR_E38K
goto IR_Stop
IR_Send_E1
bcf PORTC,IR_TX ;~ 119*(4+1+2)=833us=1200Hz
movlw D'119'
movwf Loop_Temp2
IR_Send_E1_Delay
nop
nop
nop
nop
decfsz Loop_Temp2,F
goto IR_Send_E1_Delay
;----------------------------------
IR_Stop
bcf PORTC,IR_TX ;~ 119*(4+1+2)=833us=1200Hz
movlw D'119'
movwf Loop_Temp2
IR_Send_Stop
nop
nop
nop
nop
decfsz Loop_Temp2,F
goto IR_Send_Stop
return
;-----------------------------------------------------
;函数名:IR_Send_Data()
;函数功能:IR发送数据
;函数入口参数:IR_Data_ADD(发送数据首地址),IR_Data_Length(发送数据长度)
;函数出口参数:无
;-----------------------------------------------------
IR_Send_Data
banksel INTCON
bcf INTCON,INTE ;disable IR_RX interrupt
banksel IR_Data_ADD
movlw IR_Data_ADD ;Data begining address
movwf FSR
movlw 3 ;3个FEH唤醒字节
movwf Loop_Temp3
Send_Data_IR_lp0
movlw 0xFE ;FE 唤醒接收,视通讯协议定
movwf IR_Data_Temp
call IR_Send_Byte
movlw Delay_20ms
movwf Delay2
call Delay ;字节之间的延时 20ms
decfsz Loop_Temp3,F
goto Send_Data_IR_lp0
movf IR_Data_Length,F ;产生Z标志
btfsc STATUS,Z ;Length=0 return
goto Send_Data_IR_END
movf IR_Data_Length,W ;Data length
movwf Loop_Temp3
Send_Data_IR_lp1
movf INDF,W
;addlw 0x33 ;
movwf IR_Data_Temp
call IR_Send_Byte
movlw Delay_20ms
movwf Delay2
call Delay ; 12ms <20ms <300ms
incf FSR,F ;point to next data
decfsz Loop_Temp3,F ;all data sended?
goto Send_Data_IR_lp1
Send_Data_IR_END
banksel INTCON
bsf INTCON,INTE ;enable IR_RX interrupt
return
发表时间:2004年9月14日12:13:03