;************************************************************************ ;功能实现:通过DS18B20来读取温度,显示在2位LED上,精确到1度 ;硬件连接:(1)RC0-RC7接共阳数码管的段码A-H ;RA0-RA3接共阳数码管的位码DIG0-DIG3 ;*********************************************************************** ;*********************************************************************** ;定义单片机型号为PIC16F877A ;程序包含文件:P16F877A.INC ;定义配置字 ;*********************************************************************** LISTP=16F877A;定义本程序所使用的芯片为PIC16F877A #INCLUDE "P16F877A.INC";定义本程序包含该文件 __CONFIG3F72H;晶振配置HS,看门狗禁止,上电延时使能,掉电复位使能 ;低电压编程禁止,代码不保护 #DEFINEDQPORTB,2 #DEFINEDIRTRISB,2 CBLOCK20H Y1 Y2 COUNT1 COUNT2 COMD DATE BIN_L;要进行转换的字节 GE;转换后的个位 SHI;转换后的十位 DATE_L DATE_H ENDC ;*********************************************************************** ;复位矢量定义(对于16F877A) ;*********************************************************************** ORG0000H;复位矢量地址 GOTOMAIN;程序跳转到MAIN主程序 ;---------------------------------------------------------------------- ;*********************************************************************** ;主程序区 ;*********************************************************************** ORG0005H MAIN NOP CALLINTIAL STARTBTFSSDQ;数据线空闲状态为高电平 GOTO$-1 CALLRESET;复位DS18B20 MOVLW0CCH;跳过读ROM命令 CALLWR18B20 MOVLW44H;温度转换 CALLWR18B20 CALLDELAY_750US;延时750us CALLRESET;复位DS18B20 MOVLW0CCH;跳过读ROM命令 CALLWR18B20 MOVLW0BEH;读内部RAM中的9字节内容 CALLWR18B20 NOP CALLRE18B20;读数据 MOVFDATE,W MOVWFDATE_L;读低8位 CALLRE18B20;读数据 MOVFDATE,W MOVWFDATE_H;读高8位 MOVFDATE_L,W ;------------------------显示处理-------------------------------------- RRFDATE_H,F RRFDATE_L,F RRFDATE_H,F RRFDATE_L,F RRFDATE_H,F RRFDATE_L,F RRFDATE_H,F RRFDATE_L,F MOVFDATE_L,W MOVWFBIN_L;把高8位的低4位和低8位的高4位组合起来 CALLDISPLAY;调用数码管显示程序 GOTOSTART ;======================================================================= ;*********************************************************************** ;初始化和消影 ;*********************************************************************** INTIALBSFSTATUS,RP0;定义当前体为体1,对方向寄存器进行修改 MOVLW07H MOVWFADCON1;关闭A口的模拟通道 MOVLW00H MOVWFTRISC;段码显示口为输出口 MOVLW0F0H ANDWFTRISA,1;使位码(RA0-RA3)为输出口 BSFDIR;使数据线为输入 BCFSTATUS,RP0;使当前体为体0 MOVLW0FFH;关闭段码 MOVWFPORTC MOVLW0FFH;关闭位码 MOVWFPORTA BTFSSDQ;数据线空闲状态为高电平 GOTO$-1 CALLRESET;复位DS18B20 MOVLW0CCH;跳过读ROM命令 CALLWR18B20 MOVLW44H;温度转换 CALLWR18B20 CALLDELAY_750US;延时750us CALLRESET;复位DS18B20 MOVLW0CCH;跳过读ROM命令 CALLWR18B20 MOVLW0BEH;读内部RAM中的9字节内容 CALLWR18B20 NOP NOP CALLRE18B20;读数据 CALLRE18B20;读数据 CALLDELAY_MAX;延时600ms CALLDELAY_MAX CALLDELAY_MAX RETLW00H ;======================================================================= ;*********************************************************************** ;显示所测得的温度子程序 ;*********************************************************************** DISPLAY CALL_BCD MOVFSHI,W ANDLW0FH CALLTABLE;调用查表指令 MOVWFPORTC;显示十位段码 BCFPORTA,0;选通十位显示位码 CALLDELAY BSFPORTA,0;关闭十位显示位码 MOVFGE,W ANDLW0FH CALLTABLE;调用查表指令 MOVWFPORTC;显示个位段码 BCFPORTA,1;选通个位显示位码 CALLDELAY BSFPORTA,1;关闭个位显示位码 RETLW00H ;======================================================================= ;*********************************************************************** ;二进制转BCD码 ;*********************************************************************** _BCDCLRFSHI;保存地址清零 CLRFGE MOVFBIN_L,F;组合码自己给自己赋值,测试是否为0 SKPNZ;不为0则跳到下一步 RETLW00H SHI_MOVLWD'10' SUBWFBIN_L,W;BIN_L减10,结果存到W寄存器 BTFSSSTATUS,C;执行减法后,如果无借位 GOTOGE_ MOVWFBIN_L INCFSHI GOTOSHI_ GE_MOVFBIN_L,W MOVWFGE RETLW00H ;======================================================================= ;*********************************************************************** ;延时200ms ;*********************************************************************** DELAY_MAX MOVLW0FFH MOVWFY1 MOVLW0FFH MOVWFY2 DECFSZY2 GOTO$-1 DECFSZY1 GOTO$-5 RETLW00H ;======================================================================= ;*********************************************************************** ;延时6ms ;*********************************************************************** DELAY MOVLW03FH MOVWFY1 MOVLW020H MOVWFY2 DECFSZY2 GOTO$-1 DECFSZY1 GOTO$-5 RETLW00H ;======================================================================= ;*********************************************************************** ;延时750us子程序 ;*********************************************************************** DELAY_750US MOVLW09H MOVWFY1 MOVLW01AH MOVWFY2 DECFSZY2 GOTO$-1 DECFSZY1 GOTO$-5 RETLW00H ;======================================================================= ;*********************************************************************** ;查表子程序,用于显示段码数字 ;数码管为共阳数码管 ;*********************************************************************** TABLE ADDWFPCL,F RETLW0C0H;"0" RETLW0F9H;"1" RETLW0A4H;"2" RETLW0B0H;"3" RETLW99H;"4" RETLW92H;"5" RETLW82H;"6" RETLW0F8H;"7" RETLW80H;"8" RETLW90H;"9" ;======================================================================= ;*********************************************************************** ;DS18B20复位和应答子程序 ;*********************************************************************** RESETBSFSTATUS,RP0;使当前体为体1 BCFDIR;使数据位为输出 BCFSTATUS,RP0;使当前体为体0 BSFDQ;拉高数据位 NOP;空循环 BCFDQ;拉低数据位 MOVLWD'200';延时600us MOVWFY1 DECFSZY1 GOTO$-1 BSFSTATUS,RP0;使当前体为体1 BSFDIR;使数据位为输入 BCFSTATUS,RP0;使当前体为体0 MOVLWD'30';延时90us MOVWFY1 DECFSZY1 GOTO$-1 BTFSCDQ;主机接收到低电平应答脉冲,跳转到下一句 GOTORESET MOVLWD'80';延时240us MOVWFY1 DECFSZY1 GOTO$-1 BTFSSDQ;主机接收到高电平应答脉冲,跳转到下一句 GOTORESET RETLW00H;返回00H,复位应答结束 ;======================================================================== ;*********************************************************************** ;写DS18B20子程序 ;*********************************************************************** WR18B20 MOVWFCOMD;把要写的数据写到COMD内 MOVLWD'8' MOVWFCOUNT2;大循环8次 WR0BSFSTATUS,RP0;使当前体为体1 BCFDIR;使数据位为输出 BCFSTATUS,RP0;使当前体为体0 BCFDQ;拉低数据线 NOP NOP MOVLWD'2' MOVWFCOUNT1;延时9us WR1DECFSZCOUNT1,1 GOTOWR1 BTFSCCOMD,0;COMD最低位为0则跳转到下一句 BSFDQ;拉高数据线 BTFSCCOMD,0;COMD最低位为0则跳转到下一句 NOP BCFSTATUS,C;进位位置0 RRFCOMD,1;带进位位,COMD向右移一位 MOVLWD'20';延时60us MOVWFCOUNT1 WR2DECFSZCOUNT1,1 GOTOWR2 BSFDQ;拉高数据线,空闲状态 BSFSTATUS,RP0;使当前体为体1 BSFDIR;使数据位为输入 BCFSTATUS,RP0;使当前体为体0 DECFSZCOUNT2,1;8次循环到了则跳出 GOTOWR0 RETLW00H ;======================================================================= ;*********************************************************************** ;读18B20子程序 ;*********************************************************************** RE18B20 MOVLW8 MOVWFCOUNT2 RE0BSFSTATUS,RP0;使当前体为体1 BCFDIR;使数据位为输出 BCFSTATUS,RP0;使当前体为体0 BCFDQ MOVLW2 MOVWFCOUNT1 RE1DECFSZCOUNT1,1 GOTORE1 BSFSTATUS,RP0;使当前体为体1 BSFDIR;使数据位为输入 BCFSTATUS,RP0;使当前体为体0 NOP BTFSSDQ;如果数据线为高电平,则C=1 BCFSTATUS,C BTFSCDQ;如果数据线为低电平,则C=0 BSFSTATUS,C RRFDATE,1;数据依次存在DATE上 MOVLWD'20';延时60us MOVWFCOUNT1 RE2DECFSZCOUNT1,1 GOTORE2 DECFSZCOUNT2,1 GOTORE0 BSFDQ RETLW00H ;======================================================================= ;======================================================================= END;程序结束