这是我设计的DS18B20的温度计,用PROTUES仿真的(原谅我没焊它出来)DS18B20是个12位的慢速温度转换器件,单总线设计,本例用寄生电源供电,由于开始时没有完全按照DS18B20的读写时序写程序导致无法读取器件,单总线器件对读写时序要求较高,必须按照其读写时序操作,12位转换速度很慢才750ms,9位也要93.75ms,在对温度实时性要求不高的地方可以用,如体温计(可精确到0.0625,可通过运算精确到0.1,不过8位单片机的运算能力不敢恭维)运用在电饭煲上9位转换的时间还是可以达到要求的,且这单总线器件特别适用于环境恶劣的地方,成本较高(单买要7-10块,量买应该可以在2-3块吧),本程序是用12位转换实现精确到个位的温度计程序
写本程序时充分体会到汇编的精细要求(一条语句有点点问题都可能影响整个程序,这是细心的活,要耐心),还有DS18B20单总线的时序要求的严格性
下面将我的电路图还有汇编程序给大家
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
;----------------------------------------------
;temperature.asm
;作者:老猫
;作用:利用温度传感器测温,并显示出来,精度为个位
;日期:<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />2008-3-14
;版本:1.0
;MCU:AT89S51
;晶振频率:12MHz
;DS18B20接P3.4用寄生电源供电
;P0接阴极数码管显示位
;P2^1-4分别接数码管个十百千位
;-----------------------------------------------
DQ bit p3.4 ;定义DQ为单片机和DS18B20通讯管脚
FLAG BIT 01H ;DS18B20存在标记
TMPL data 029h ;12位温度高位
TMPH data 028h ;12位温度低位
TMP DATA 027H ;转换为8位后温度字节
org 0000h
ljmp main
main:MOV SP,#0CFH ;初始化堆栈
CLR FLAG
LCALL RESET ;初始化DS18B20
JNB FLAG,CZ ;判断DS18B20存在与否
MOV TMP,#11 ;告知DS18B20存在
LCALL DISPLAY
RE: LCALL RESET ;重复调用DS18B20和显示
MOV A,#0CCH ;跳过搜索ROM
LCALL WRITE
NOP
MOV A,#044H ;发送命令转换温度,12位最大转换时间750MS,
LCALL WRITE
MOV R5,#30
REDISPLAY: LCALL DISPLAY
DJNZ R5,REDISPLAY
LCALL RESET ;重新复位DS18B20
MOV A,#0CCH ;跳过ROM
LCALL WRITE
LCALL GET_TEMPER ;读取温度
LCALL TRANS_TEMP ;由12位温度转换为8位温度
LCALL DISPLAY ;显示
SJMP RE
CZ: MOV TMP,#99
SJMP REDISPLAY
;================温度转换===============
TRANS_TEMP: ;温度低位高4位和温度高位的低4位为我们需要的多种方法实现,此方法周期长,占用字节多,且要用到位寻址地址,资源浪费严重
MOV C,28H.3
MOV 27H.7,C
MOV C,28H.2
MOV 27H.6,C
MOV C,28H.1
MOV 27H.5,C
MOV C,28H.0
MOV 27H.4,C
MOV C,29H.7
MOV 27H.3,C
MOV C,29H.6
MOV 27H.2,C
MOV C,29H.5
MOV 27H.1,C
MOV C,29H.4
MOV 27H.0,C
mov a,27h
RET
;==============显示=====================
DISPLAY:
PUSH ACC ;现场保存
PUSH PSW
PUSH B
PUSH TMP
MOV P2,#0
MOV DPTR,#NUM
MOV A,TMP ;显示前两位tmp除以10得到高低位(对零下和高于100的温度无效)
MOV B,#10
DIV AB ;低位/10,余数是个位,商是十位
MOVC A,@A+DPTR
MOV P0,A
SETB P2.1
LCALL DELAY
MOV A,B
MOVC A,@A+DPTR
CLR P2.1
MOV P0,A
SETB P2.0
LCALL DELAY
RETURN: POP TMP ;现场恢复
POP B
POP PSW
POP ACC
RET
;==============读取温度数据================
GET_TEMPER: JNB FLAG,R_T_NO ;判断器件存在与否
MOV A,#0BEH ;发送0BE读取RAM上内容
LCALL WRITE
LCALL READ
MOV TMPL,A ;先低位后高位
LCALL READ
MOV TMPH,A
RET
R_T_NO:MOV TMPH,#0H
MOV TMPL,#0H
RET
;============初始化18B20子程序===============
;实现时序由单片机负跳转保持低电平480us然后放开总线,等待60us后由DS18B20发出存在脉冲总共480us
RESET:
SETB DQ
NOP
NOP
CLR DQ
MOV R7,#3
START_DEL1: MOV R6,#107
DJNZ R6,$
DJNZ R7,START_DEL1
SETB DQ
NOP
NOP
MOV R7,#100
START_RELAY: JNB DQ,HAVE1820
DJNZ R7,START_RELAY
CLR FLAG
SJMP START_OUT
HAVE1820:
SETB FLAG
MOV R6,117
DJNZ R6,$
START_OUT:
SETB DQ
RET
;================读字节======================
READ:;读时序单片机负跳转后等待1-2us在15us内读取高低,然后等待45us后又开始读取下一位,每字节8位
MOV R7,#8
READ_BIT: SETB DQ
CLR C
NOP
CLR DQ
NOP
NOP
SETB DQ
MOV R6,#6
DJNZ R6,$
MOV C,DQ
RRC A
MOV R6,#25
DJNZ R6,$
DJNZ R7,READ_BIT
RET
;=================写字节======================
WRITE: ;写时序,负跳转后等待15us内写入0或1,保持45us,再开始下一位写时序,每字节8位
MOV R7,#8
CLR C
WRITE_BIT:
SETB DQ
NOP
NOP
CLR DQ
MOV R6,#6
DJNZ R6,$
RRC A
MOV DQ,C
MOV R5,#23 ;由25改为6
DJNZ R5,$
SETB DQ
NOP
DJNZ R7,WRITE_BIT
SETB DQ
RET
;---------------延时6ms--------------
DELAY:PUSH PSW
SETB RS0
SETB RS1
MOV R6,#0EH ;延时6MS
DEL1: MOV R7,#0C0H
DJNZ R7,$
DJNZ R6,DEL1
POP PSW
RET
;============数码管显示==============
NUM:DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H
END
用户548416 2009-5-17 16:50
用户189089 2009-4-20 18:33
用户540903 2009-4-15 12:53
用户396057 2008-12-3 22:29
用户151534 2008-7-19 11:23
用户151534 2008-7-18 17:44
用户873489 2008-6-4 12:38