

;******************************************************************************
;*标题: 东哥单片机学习网DG-51/AVR-V1.0开发板演示程序-- DS18B20温度计
;*文件: DG005.asm
;*版本: 1.0
;*作者: 东哥开发网 - 东哥
;*邮箱: picavr@163.com QQ: 279068079
;*网站: http://www.picavr.com
;*****************************************************************************
;*: 描述:
;* J32通过连接线接到P2.3 DS18B20的读写程序,数据P2.3
; 温度传感器18B20汇编程序,采用器件默认的12位转化
; 最大转化时间750微秒,显示温度-55到+125度,显示精度
; 为0.5度,显示采用4位LED共阳显示测温值
;*:
;******************************************************************************
;* 【版权】 Copyright(C)东哥单片机学习网 www.picavr.com All Rights Reserved
;* 【声明】 此程序仅用于学习与参考,引用请注明版权和作者信息!
;******************************************************************************
; 单片机内存分配申明!
;******************************************************************************
TEMPER_L EQU 40H ;用于保存读出温度的低8位
TEMPER_H EQU 41H ;用于保存读出温度的高8位
TMROMVH EQU 42H ;报警上限
TMROMVL EQU 43H ;报警下限
FLAG1 EQU 38H ;是否检测到DS18B20标志位
TEMPL EQU 30H ;用于保存读出温度的低8位
TEMPH EQU 31H ;用于保存读出温度的高8位
TEMPHC EQU 32H ;温度转换寄存器低8位
TEMPLC EQU 33H ;温度转换寄存器高8位
BUF1 EQU 34H ;显示缓冲寄存器小数位
BUF2 EQU 35H ;显示缓冲寄存器个数位
BUF3 EQU 36H ;显示缓冲寄存器十数位
BUF4 EQU 37H ;显示缓冲寄存器百数位
T10MS EQU 29H ;
TMSETVL EQU 28H ;温度下限设定值
TMSETVH EQU 27H ;温度上限设定值
DISL_VL EQU 26H ;报警下限个位数存放内存位置
DISL_VH EQU 25H ;报警下限十位数存放内存位置
DISH_VL EQU 24H ;报警上限个位数存放内存位置
DISH_VH EQU 23H ;报警上限十位数存放内存位置
BT_VL EQU 22H ;比较当前显示数据与设定数据寄存器
;**********************************************
TEMPDIN BIT P2.3 ;数据脚定义
;**********************************************
; BIT FLAG DEFINATION
;**********************************************
TEMPCONV EQU 00H ;
TIME1SOK EQU 01H ;
TEMPONEOK EQU 02H ;
;**********************************************
ORG 0000H ;主程序入口地址
AJMP MAIN ;转主程序
ORG 0003H ;外中断0中断入口
DB 00H,00H,00H,00H,00H,00H,00H;
RETI ;跳至INTEX0执行中断服务程序
ORG 000BH ;定时器T0中断入口地址
AJMP TIMER0 ;
RETI ;跳至定时器T0执行中断服务程序
ORG 0013H ;外中断1中断入口
DB 00H,00H,00H,00H,00H,00H,00H ;
RETI ;跳至INTEX1执行中断服务程序
ORG 001BH ;定时器T1中断入口地址
DB 00H,00H,00H,00H,00H,00H,00H ;
RETI ;中断返回(不开中断)
ORG 0023H ;串行口中断入口地址
DB 00H,00H,00H,00H,00H,00H,00H ;
RETI ;中断返回(不开中断)
;**********************************************
ORG 100H ;
MAIN:
MOV SP, #60H ;
MOV P2, #0FFH ;
MOV TMOD,#01H ;
MOV TH0, #0B1H ;SET T0 VALUE 10MS
MOV TL0, #0E0H ;
MOV DISL_VL,#00H ;
MOV DISL_VH,#00H ;
MOV DISH_VL,#00H ;
MOV DISH_VH,#00H ;
MOV TMSETVL,#30H ;
MOV TMSETVH,#35H ;
CLR EA ;打开CPU总中断请求
CLR TR0 ;
CLR ET0 ;
MOV PSW, #00H ;
CLR TEMPCONV ;
CLR TEMPONEOK ;
;**************************************
LPTEMP: LCALL INIT_1820 ;先复位DS18B20
MOV A,#0CCH ;跳过ROM匹配
LCALL WRITE_1820 ;
MOV A,#0B8H ;发出读温度命令
LCALL WRITE_1820 ;
LCALL GET_TM ;调用读温度子程序
LCALL CONVTEMP ;温度BCD码计算处理子程序
LCALL DISPBCD ;显示区BCD码温度值刷新子程序
;**************************************
MOV A,TMSETVL ;调下限设置值到调整显示寄存
ANL A, #0FH ;
MOV DISL_VL,A ;
MOV A,TMSETVL ;
SWAP A ;
ANL A, #0FH ;
MOV DISL_VH,A ;
MOV A,TMSETVH ;调上限设置值到调整显示寄存
ANL A, #0FH ;
MOV DISH_VL,A ;
MOV A,TMSETVH ;
SWAP A ;
ANL A, #0FH ;
MOV DISH_VH,A ;
;*************************************
LPTEMP1:
LCALL DISPLAY ;调用数码管显示子程序
LCALL BT_WORK ;
;*************************************
MOV A,BT_VL ; 比较当前温度与设定下限温度值
CJNE A,TMSETVL,TEMP_VH1;
CLR P2.0 ;
TEMP_VH1: JNC TEMP_VH ;
CLR P2.0 ;
TEMP_VH: CJNE A,TMSETVH,TM_WORK1;比较当前温度与设定上限温度值
SETB P2.0 ;
TM_WORK1: JC TM_WORK ;
SETB P2.0 ;
;*************************************
TM_WORK:
JB TEMPONEOK,LPTEMP1;
LCALL GET_TEMPER ;调用读温度子程序
LCALL CONVTEMP ;温度BCD码计算处理子程序
LCALL DISPBCD ;显示区BCD码温度值刷新子程序
AJMP LPTEMP1 ;
;**************************************
BT_WORK:
MOV BT_VL,BUF2 ;当前显示保存是转换程序
MOV A,BUF3 ;
SWAP A ;
ORL A,BT_VL ;
MOV BT_VL,A ;
RET ;
;**************************************
;***************************************
; 读出转换后的温度值
;***************************************
GET_TEMPER:
SETB TEMPDIN ;
LCALL INIT_1820 ;先复位DS18B20
JB FLAG1,TSS2
RET ;判断DS1820是否存在?若DS18B20不存在则返回
TSS2:
CLR P2.1 ;DS18B20已经被检测到!!
MOV A,#0CCH ;跳过ROM匹配
LCALL WRITE_1820
MOV A,#44H ;发出温度转换命令
LCALL WRITE_1820
;*****************************************
;这里通过调用显示子程序实现延时一段时间,等待AD转换结束,12位的话750微秒
;*****************************************
MOV R3,#8
LPDISP: LCALL DISPLAY
DJNZ R3,LPDISP
;*****************************************
GET_TM: LCALL INIT_1820 ;准备读温度前先复位
MOV A,#0CCH ;跳过ROM匹配
LCALL WRITE_1820
MOV A,#0BEH ;发出读温度命令
LCALL WRITE_1820
LCALL READ_18200 ;将读出的温度数据保存到40H/41H
RET
;*******************************************
;写DS18B20的子程序(有具体的时序要求)
;*******************************************
WRITE_1820:
MOV R2,#8 ;一共8位数据
CLR C ;
WR1:
CLR TEMPDIN ;
MOV R3,#6
DJNZ R3,$
RRC A
MOV TEMPDIN,C ;
MOV R3,#23
DJNZ R3,$
SETB TEMPDIN ;
NOP
DJNZ R2,WR1 ;
SETB TEMPDIN ;
RET
;*************************************
; 这是DS18B20复位初始化子程序
;*************************************
INIT_1820:
SETB TEMPDIN
NOP
CLR TEMPDIN ;主机发出延时537微秒的复位低脉冲
MOV R1,#3
TSR1: MOV R0,#107
DJNZ R0,$
DJNZ R1,TSR1
SETB TEMPDIN ;然后拉高数据线
NOP
NOP
NOP
MOV R0,#25H
TSR2:
JNB TEMPDIN,TSR3 ;等待DS18B20回应
DJNZ R0,TSR2
LJMP TSR4 ;延时
TSR3:
SETB FLAG1 ;置标志位,表示DS1820存在
CLR P3.7 ;检查到DS18B20就点亮P3.7LED
LJMP TSR5
TSR4:
CLR FLAG1 ;清标志位,表示DS1820不存在
CLR P3.1
LJMP TSR7
TSR5: MOV R0,#117
TSR6: DJNZ R0,TSR6 ;时序要求延时一段时间
TSR7: SETB TEMPDIN ;
RET
;*************************************
;处理温度BCD码子程序
;*************************************
CONVTEMP: MOV A,TEMPH ;
ANL A,#80H ;
JZ TEMPC1 ; 判断温度是否在零下?
CLR C ; 温度值补码 变成原码
MOV A,TEMPL ;
CPL A
ADD A,#01H ;
MOV TEMPL,A ;
MOV A, TEMPH ; -
CPL A ;
ADDC A,#00H ;
MOV TEMPH,A ; TEMPHC HI=符号位
MOV TEMPHC,#0BH ; 置"-"标志
SJMP TEMPC11 ;
TEMPC1: MOV TEMPHC,#0AH ; 置"+"标志
;**************************************
TEMPC11: MOV A,TEMPHC ; 计算小数位温度BCD值
SWAP A
MOV TEMPHC,A ;
MOV A,TEMPL ;
ANL A,#0FH ; 乘0.0625
MOV DPTR,#TEMPDOTTAB ;
MOVC A,@A+DPTR ;
MOV TEMPLC,A ; TEMPLC LOW= 小数部分 BCD
;**************************************
MOV A,TEMPL ; 计算整数位温度BCD值
ANL A,#0F0H ;
SWAP A ;
MOV TEMPL,A ;
MOV A,TEMPH ;
ANL A,#0FH ;
SWAP A ;
ORL A,TEMPL ;
MOV TEMPER_L ,A ;
LCALL HEX2BCD1 ; 调用单字节十六进制转BCD子程序
;************************************
MOV TEMPL,A ;
ANL A,#0F0H ;
SWAP A ;
ORL A,TEMPHC ; TEMPHC LOW = 十位数 BCD
MOV TEMPHC,A ;
MOV A,TEMPL ;
ANL A,#0FH ;
SWAP A ; TEMPLC HI = 个位数 BCD
ORL A,TEMPLC ;
MOV TEMPLC,A ;
MOV A,R7 ;
JZ TEMPOUT ;
ANL A,#0FH ;
SWAP A ;
MOV R7,A ;
MOV A,TEMPHC ; TEMPHC HI = 百位数 BCD
ANL A,#0FH ;
ORL A,R7 ;
MOV TEMPHC,A ;
TEMPOUT: RET ;
;**************************************
;小数部分分码表
;**************************************
TEMPDOTTAB: DB 00H,01H,01H,02H,03H,03H,04H,04H,05H,06H
DB 06H,07H,08H,08H,09H,09H ;
;**************************************
;显示区 BCD 码温度值刷新子程序
;**************************************
DISPBCD: MOV A,TEMPLC ; 温度数据移入显示寄存器
ANL A,#0FH ;
MOV BUF1,A ; 显示小数
MOV A,TEMPLC ;
SWAP A ;
ANL A,#0FH ;
MOV BUF2,A ; 显示个位
MOV A,TEMPHC ;
ANL A,#0FH ;
MOV BUF3,A ; 显示十位
MOV A,TEMPHC ;
SWAP A ;
ANL A,#0FH ;
MOV BUF4,A ; 显示百位
MOV A,TEMPHC ;
ANL A,#0F0H ;
CJNE A,#10H,DISPBCD0 ; 百位数=0?
SJMP DISPOUT ;
DISPBCD0:
MOV A, TEMPHC ;
ANL A, #0FH ;
JNZ DISPOUT ; 十位数是0?
MOV A,TEMPHC ;
SWAP A ;
ANL A,#0FH ;
MOV BUF4,0AH ; 符号位不显示
MOV BUF3,A ; 十位数显示符号
DISPOUT: RET ; ;
;*************************************
;单字节十六进制转BCD
;*************************************
HEX2BCD1:MOV B,#64H ; 十六进制 ->BCD
DIV AB ; B=A%100
MOV R7,A ; R7=百位数
MOV A,#0AH ;
XCH A,B ;
DIV AB ; B=A%B
SWAP A ;
ORL A,B ;
RET ;
;**************************************
;DECIMAL DATA IS TRANSISTERED HEX DATA
;INPUT: A=DECIMAL DATA
;OUTPUT:A
;USED REGISTER: R1,R2,A
;**************************************
DECHEX: MOV R1, A
SWAP A
ANL A, #0FH
RL A
MOV R2, A
RL A
RL A
ADD A, R2
MOV R2, A
MOV A, #0FH
ANL A, R1
ADD A, R2
RET
;*************************************
; Calculate CRC-8 Values, Uses The
;CCITT-8 Polynomial,Expressed As
; X^8+X^5+X^4+1
;*************************************
CRC8CAL: PUSH ACC ;
MOV R7,#08H ; Number Bits Byte
CRC8LOOP1:
XRL A,B ; Calculate CRC
RRC A ; Move T0 Carry
MOV A,B ; Get The Last CRC Value
JNC CRC8LOOP2 ; Skip If Data==0
XRL A,#18H ; Update The CRC Value
CRC8LOOP2:
RRC A ; Position The New CRC
MOV B,A ; Store The New CRC
POP ACC ; Get The Remaining Bits
RR A ; Possition The Next Bit
PUSH ACC ; Save The Remaining Bits
DJNZ R7,CRC8LOOP1 ; Repeat For 9 Bits
POP ACC ;
RET ;
;******************************************
;读DS18B20的程序,从DS18B20中读出9个字节数据
;开始的两个字节为温度数据
;******************************************
READ_18200:
MOV R4,#9 ; 将温度高位和低位从DS18B20中读出
MOV R1,#TEMPER_L ; 低位存入40H(TEMPER_L),高位存入41H(TEMPER_H)
MOV B, #00H ;
;************************************
RE00:
MOV R2,#8 ; 数据一共有8位
RE01:
CLR C
SETB TEMPDIN ;
NOP
NOP
CLR TEMPDIN ;
NOP
NOP
NOP
SETB TEMPDIN ;
MOV R3,#9
RE10:
DJNZ R3,RE10 ;
MOV C,TEMPDIN ;
MOV R3,#23
RE20:
DJNZ R3,RE20 ;
RRC A
DJNZ R2,RE01 ;
;************************************
MOV @R1,A ;
INC R1 ;
LCALL CRC8CAL ;
DJNZ R4,RE00 ;
MOV A,B ;
JNZ READ_OUT ;
MOV TEMPL,TEMPER_L ;
MOV TEMPH,TEMPER_H ;
MOV TMSETVL,TMROMVL ;
MOV TMSETVH,TMROMVH ;
READ_OUT: RET ;
;****************************************
; TIMER0 INTERRUPT SUBROUTE
; GERANATE AN INTERRUPT PER 10ms
;****************************************
TIMER0: PUSH PSW ; PROTECT PSW,ACC REGISTER
PUSH ACC ;
MOV TL0, #0B1H ;
MOV TH0, #0E0H ;
INC T10MS ;
MOV A,T10MS ;
CJNE A,#05H,TMREND ;
MOV T10MS,#00H ;
SETB TIME1SOK ;
LCALL GET_TEMPER ;调用读温度子程序
LCALL CONVTEMP ;温度BCD码计算处理子程序
LCALL DISPBCD ;显示区BCD码温度值刷新子程序
LCALL DISPLAY ;
TMREND: POP ACC ;
POP PSW ;
RETI ;
;*****************************************
;显示子程序
;*****************************************
DISPLAY:
MOV DPTR,#NUMTAB ;指定查表启始地址
MOV R0,#4
DP11: MOV R1,#15 ;显示1000次
DPLP: MOV A,BUF1 ;取小位数
MOVC A,@A+DPTR ;查小位数的7段代码
MOV P0,A ;送出小位的7段代码
CLR P1.3 ;开小位显示
ACALL DL1ms ;显示1ms
SETB P1.3 ;
MOV A,BUF2 ;取个位数
MOVC A,@A+DPTR ;查个位数的7段代码
MOV P0,A ;送出个位的7段代码
CLR P1.2 ;开个位显示
ACALL DL1ms ;显示1ms
SETB P1.2 ;
MOV A,BUF3 ;取十位数
MOVC A,@A+DPTR ;查十位数的7段代码
MOV P0,A ;送出十位的7段代码
CLR P1.1 ;开十位显示
ACALL DL1ms ;显示1ms
SETB P1.1 ;
MOV A,BUF4 ;取百位数
MOVC A,@A+DPTR ;查百位数的7段代码
MOV P0,A ;送出百位的7段代码
CLR P1.0 ;开百位显示
ACALL DL1ms ;显示1ms
SETB P1.0 ;
DJNZ R1,DPLP ;250次没完循环
DJNZ R0,DP11 ;4个100次没完循环
RET
;**************************************
;10毫秒延时程序
;**************************************
DL10MS: LCALL DISPLAY ;
RET ;
;****************************************
;0.2MS延时(按12MHZ算)
;****************************************
DL1MS: MOV R7,#100
DJNZ R7,$
RET
;****************************************
;7段数码管0~9数字的共阳显示代码
;****************************************
NUMTAB: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0FFH,0BFH ;
; "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "不亮" "-"
;****************************************
END
于29日评论道:
太感谢了 我做的课程设计就是个 我用的单片机是AT89C2051 P1.0-P1.7接段选A-DP, P3.0-P3.3 接四位LED的位选,DQ EQU P3.4 ,P3.7接报警电路的输入端。所以必须用查询的方式来实现应该怎么修改啊。还有在你的程序里P2.1和P3.1是做什么用的 再次感谢