; 以下是用该设备完成的1BUS的简单练习。
#INCLUDE P16F877A.INC
DAT_D EQU PORTA
DAT_T EQU TRISA
TMP0 EQU 30H
PDBYTE EQU TMP0+1
COUNT EQU TMP0+2
IOBYTE EQU TMP0+3
WENDUH EQU TMP0+4
WENDUL EQU TMP0+5
DQ EQU 2
ORG 00H
NOP
NOP
SETUP:
BCF STATUS,RP0
BCF STATUS,GIE
CLRF PORTC
CLRF PORTA
BSF STATUS,RP0
MOVLW H'07'
MOVWF ADCON1
CLRF TRISC
MOVLW H'0FF'
MOVWF TRISA
BCF STATUS,RP0
GOTO START
START:
BTFSS PORTA,DQ
GOTO START
CALL OW_RESET ;初始化DS18B20
BTFSS PDBYTE,0
GOTO ERROR_1
MOVLW H'0CC' ;直访ROM指令
CALL DSTXBYTE
MOVLW H'44' ;转换温度指令
CALL DSTXBYTE
WAIT1:
CALL DELAY
CALL DELAY
CALL OW_RESET ;初始化DS18B20
MOVLW H'0CC'
CALL DSTXBYTE ;直访ROM指令
MOVLW H'0BE'
CALL DSTXBYTE ;读取温度命令
CALL DSRXBYTE
NOP
MOVF IOBYTE,W
MOVWF PORTC ;显示温度低字节(二进制)
GOTO START
ERROR_1:
NOP
GOTO START
;************************************************************************************
OW_HIZ MACRO
;强制DQ变为高组态
BSF STATUS,RP0 ;选择数据存储器BANK1
BSF DAT_T,DQ ;使DQ引脚变为高阻态
BCF STATUS,RP0 ;选择数据存储器的BANK0
ENDM
;--------------------------------------------------------------------
OW_LO MACRO
;强制DQ变为逻辑低电平
BCF STATUS,RP0 ;选择数据存储器的BANK0
BCF DAT_D,DQ ;清除DQ位
BSF STATUS,RP0 ;选择数据存储器的BANK1
BCF DAT_T,DQ ;把DQ引脚作为输出
BCF STATUS,RP0 ;选择数据存储器的BANK0
ENDM
;--------------------------------------------------------------------
WAIT MACRO TIME
;延时TIMEUS
;时间必须是5US的整数
MOVLW (TIME/5)-1 ;处理时间:1US
MOVWF TMP0 ;处理时间:1US
CALL WAIT5U ;处理时间:2US
ENDM
;************************************************************************************
WAIT5U:
;需要5US来完成
NOP ;处理时间为1US
NOP ;处理时间为1US
DECFSZ TMP0,F ;如果不为零,处理时间为1US,如果为零,处理时间为2US
GOTO WAIT5U ;处理时间为2US
RETLW 0 ;处理时间为2US
;************************************************************************************
OW_RESET:
OW_HIZ ;以口线为高电平开始
CLRF PDBYTE ;清除PD字节
OW_LO ;
WAIT D'500' ;驱动器输出低电平500US
OW_HIZ ;
WAIT D'70' ;释放口线,等待PD脉冲70US
BTFSS DAT_D,DQ ;读PD脉冲
INCF PDBYTE,F ;如果检测到了PD脉冲,就把PDBYTE置位1
WAIT D'430' ;在PD脉冲后等待430US
RETLW 0 ;
;--------------------------------------------------------------------
DSTXBYTE:
MOVWF IOBYTE ;要发送的字节从W开始
MOVLW D'8' ;从IOBYTE开始发送
MOVWF COUNT ;置COUNT为8,表示要发送的比特数
DSTXLP:
OW_LO ;
NOP ;
NOP
NOP ;口线变低电平5US
NOP
NOP
RRF IOBYTE,F ;数据字节
BTFSC STATUS,C ;检查IOBYTE的LSB是1还是0
BSF DAT_D,DQ ;如果LSB是1,线路为高电平
WAIT D'60' ;连续驱动线路60US
OW_HIZ ;为了上拉,释放口线
NOP
NOP ;2US的恢复时间
DECFSZ COUNT,F ;位计数器减1
GOTO DSTXLP ;
RETLW 0 ;
;--------------------------------------------------------------------
DSRXBYTE:
MOVLW D'8' ;读入的字节保存入IOBYTE
MOVWF COUNT ;把COUNT设为8,来进行位数计数
DSRXLP:
OW_LO ;
NOP
NOP
NOP ;把DQ变低6US
NOP
NOP
NOP ;
OW_HIZ ;变为HIZ,等待4US
NOP
NOP
NOP
NOP ;
MOVF DAT_D,W ;读DQ
ANDLW B'00000100' ;屏蔽DQ位
ADDLW D'255' ;如果DQ=1,则C=1;如果DQ=0则C=0
RRF IOBYTE,F ;把C移位至IOBYTE
WAIT D'50' ;等50US直到时隙末
DECFSZ COUNT,F ;位计数器减1
GOTO DSRXLP ;
RETLW 0
;************************************************************************************
DELAY
;子程序名,也是子程序入口地址
movlw 0Ffh ;将外层循环参数值FFH经过W
movwf H'20' ;送入用作外循环变量的20H单元
lp0 movlw 0Ffh ;将内层循环参数值FFH经过W
movwf 21h ;送入用作内循环变量的21H单元
lp1 decfsz 21h,F ;变量21H内容递减,若为0跳跃
goto lp1 ;跳转到LP1处
decfsz 20h,F ;变量20H内容递减,若为0跳跃
goto lp0 ;跳跃到LP0处
return ;返回主程序
END
你可以通过这个链接引用该篇文章:http://fnjxf.bokee.com/tb.b?diaryId=12735166