⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ds18b20.asm

📁 用89C51单片机,LCD1602,建成的数字温度计.
💻 ASM
字号:
;===========================================================================
;DS18B20与77E58系列单片机的接口程序
;单片机晶振40MHz,机器周期为0.1uS
;此代码已调试通过。

;	温度转换--->....→读取温度→CRC校验→温度转换→数据处理→其他服务→
;        		          ↑_________↓_____________________________↓
;===========================================================================
;1 wire 总线DQ
DQ bit P3^5
//DQ1 bit P0^0

;===========================================================================
NAME	DS18B20	;模块名称

;===========================================================================

;===========================================================================
;主机对1 wire 设备初始化子程序
;函数原型:bit  reset_ds18b20(void)
;返回值Cy:1=设备存在;0=设备不存在
;===========================================================================
?PR?reset_ds18b20?DS18B20   SEGMENT CODE 
	PUBLIC	reset_ds18b20

RSEG  ?PR?reset_ds18b20?DS18B20	
reset_ds18b20:
	clr	ea;
	clr	DQ;
	call	delay_500uS;
	setb	DQ;
	call	delay_90uS;
	setb	c;	设备存在
	jnb	DQ,i_ret;
	clr	c;	设备不存在
	ajmp	j_ret;	
i_ret:	call	delay_400uS;
 //    clr	DQ1
j_ret:	setb	ea;
	ret		

;==============================================================================
;主机向DS18B20写一个字节数据
;入口:欲写的数据在A中


;==============================================================================
write_byte:
	push	psw;
	mov	r4,#8;
	clr	c;
w_loop1:
	rrc	a;	数据的低位先发,后发高位
	clr	ea;//禁止中断
	jc	write1;
	clr	DQ;
	call	delay_90uS;
	setb	DQ;
	ajmp	w_loop2;
write1:	clr	DQ;
;	mov	r7,#1;	恢复时间延时必须大于1uS
;	djnz	r7,$;
 NOP
	setb	DQ;
	call	delay_90uS;
w_loop2:setb	ea;开中断
	djnz	r4,w_loop1;
	pop	psw;
	ret

;==============================================================================
;主机从DS18B20读取一个字节数据
;出口:数据在A中
;

;===============================================================================
read_byte:
	
	push	psw;
	mov	r4,#8;
	clr	a
read_loop:
	clr	ea;禁止中断
	clr	DQ;
;	mov	r7,#1;	拉低总线时间应大于1uS	
;	djnz	r7,$;
  NOP
	setb	DQ;
	mov	r7,#5;	//必须在从拉低总线开始的15uS以内采样总线
	djnz	r7,$;
;	mov	c,DQ;
    call DQ_select_responses1	
	rrc	a;
	mov	r7,#25;延时50uS
	djnz	r7,$;
	;mov	r7,#1;3;	恢复时间延时必须大于1uS
	;djnz	r7,$;
	NOP
	setb	ea;开中断
	djnz	r4,read_loop;
	pop	psw;
	ret
DQ_select_responses1:
    PUSH	acc
	mov		a,#2
	anl		a,P0 ;选择对应的端口
	setb		c
	jz	   c_next
	 sjmp	c_next1
c_next: clr	c
c_next1:
	pop		acc
	ret 
;===============================================================================
;读取ROM序列码
;函数原型:void read_rom(unsigned char data * buf)
?PR?_read_rom?DS18B20   SEGMENT CODE 
	PUBLIC	_read_rom

RSEG  ?PR?_read_rom?DS18B20	
_read_rom:
	mov	a,r7;
	mov	r0,a;
	mov	r3,#8;
	call	reset_ds18b20;
	mov	a,#33h;
	call	write_byte;
read:	call	read_byte;
	mov	@r0,a;
	inc	r0;
	djnz	r3,read;
	call	reset_ds18b20;
	ret	



;=================================================================================
;单从设备温度转换函数
;函数原型:void temp_conver(void)
;

;=================================================================================
?PR?temp_conver?DS18B20   SEGMENT CODE 
	PUBLIC	temp_conver

RSEG  ?PR?temp_conver?DS18B20	
temp_conver:
	call	reset_ds18b20;
	mov	A,#0cch;	//跳跃ROM命令
	call	write_byte;
	mov	A,#044h;	//温度转换命令
	call	write_byte;	
	ret
	
;=================================================================================
;主机读取单从设备暂存器函数
;函数原型:void read_scrat(unsigned char data * buf,unsigned char n)
;入口:r7(buf):数据缓冲区首址
;	R5(n):欲读取的字节数	
;================================================================================
?PR?_read_scrat?DS18B20   SEGMENT CODE 
	PUBLIC	_read_scrat

RSEG  ?PR?_read_scrat?DS18B20
_read_scrat: 
	mov	a,r7;
	mov	r0,a;
	mov	a,r5;
	mov	r3,a;
	call	reset_ds18b20; //
	mov	A,#0cch;	//跳跃ROM命令
	call	write_byte;
	mov	A,#0beh;	//读暂存器命令
	call	write_byte;	
r_scrat_loop:
	call	read_byte;
	mov	@r0,a;
	inc	r0;
	djnz	r3,r_scrat_loop;
	call	reset_ds18b20;
	ret


;================================================================================
;主机写单从设备的3个暂存器函数
;函数原型:void write_scrat(unsigned char data * buf)
;入口:R7(buf)欲写数据的首地址	

;================================================================================
?PR?_write_scrat?DS18B20   SEGMENT CODE 
	PUBLIC	_write_scrat

RSEG  ?PR?_write_scrat?DS18B20
_write_scrat:
	mov	r3,#3;
	mov	a,r7;
	mov	r0,a;
	call	reset_ds18b20; //
	mov	a,#0cch;	//跳跃ROM命令
	call	write_byte;
	mov	a,#04eh;	//写暂存器命令
	call	write_byte;	
w_scrat_loop:
	mov	a,@r0;
	call	write_byte;//写数据
	inc	r0;
	djnz	r3,w_scrat_loop;
	ret
	


;===================================================================================

;===================================================================================
;温度数据(HEX)转换为8位(4字节)BCD码
;函数原型:void hextobcd(unsigned char data * source ,unsigned char data * disten)
;入口:source(R7):需转换数据的首地址指针;disten(R5):转换后数据保存地址指针
;===================================================================================
?PR?_hextobcd?DS18B20   SEGMENT CODE 
	PUBLIC	_hextobcd

RSEG  ?PR?_hextobcd?DS18B20
_hextobcd:
	mov	a,r7;
	mov	r0,a;
	mov	a,r5;
	mov	r1,a;
	mov	a,@r0;
	mov	r5,a;//低字节
	inc	r0;
	mov	a,@r0;
	mov	r7,a;//高字节
	call	neg;//判负求补
	call	data_apart;整数与小数分离
	call	hbcd;//转换为BCD码
	mov	a,r0;//恢复数据指针
	mov	r7,a;
	mov	a,r1;
	mov	r5,a;
	ret
	
	

;===================================================================================




;===================================================================================
;两字节HEX数据转换为两字节BCD(
;入口:欲转换的数据在R6R7,R6为整数,R7为小数部分;
;	R1=转换后BCD数据保存首地址
 ;出口:转换后的BCD码首地址在R1中,(R1),(R1)+1为整数部分,(R1)的第7位为数据符号位:1=负数;0=正数
 ;	(R1)+2,(R1)+3为小数部分。
;================================================================================= 
hbcd:
;整数部分转换	
	mov	a,r1;
	push	acc;
	mov	a,r6;
	mov	c,acc.7;
	mov	F0,c;//暂存符号位
	mov	b,#100;
	div	ab;
	mov	c,F0;
	mov	acc.7,c;恢复符号位
	mov	@r1,a;
	mov	a,#10;
	xch	a,b;
	div	ab;
	swap	a;
	orl	a,b;
	inc	r1;
	mov	@r1,a;
;小数部分BCD码转换
	clr	a;
	mov	r2,a;
	mov	r3,a;
	mov	a,r7;
	jnb	acc.7,hbcd_1;
	mov	r2,#50h;
hbcd_1:	jnb	acc.6,hbcd_2;
	mov	a,r2;
	add	a,#25h;
	mov	r2,a;
	mov	a,r7;
hbcd_2:	jnb	acc.5,hbcd_3;
	mov	a,r2;
	add	a,#12h;
	mov	r2,a;
	mov	r3,#50h;
	mov	a,r7;
hbcd_3:	jnb	acc.4,hbcd_4;
	mov	a,r2;
	add	a,#06h;
	da	a;
	mov	r2,a;
	mov	a,r3;
	add	a,#25h;
	mov	r3,a;
hbcd_4:	mov	a,r2;
	inc	r1;
	mov	@r1,a;
	mov	a,r3;
	inc	r1;
	mov	@r1,a;
	pop	acc;//恢复数据指针
	mov	r1,a;
	ret		
;===================================================================================
;数据求补运算子程序
;入口:R5,R7;R7为高字节
;出口:数据地址不变
;===================================================================================
neg:
	mov	a,r7;
	jnb	acc.7,neg_ret;//判断数据是否是负数,若非负数则直接退出
	mov	a,r5;              //否则求补
	cpl	a;
	clr	c;
	add	a,#1;
	mov	r5,a;
	mov	a,r7;
	cpl	a;
	addc	a,#0;
	setb	acc.3;//设置负数标志
	mov	r7,a;
neg_ret:	ret	


		


;==========================================================================================
;整数与小数部分的分离	
;入口:数据在R6,R7中,R7为高字节
;出口:分离的整数在R6中,小数在R7中
;=========================================================================================	
data_apart:
	mov	a,r7;//高字节
	anl	a,#0fh;
	swap	a;
	mov	b,a;//
	mov	a,r5;
	anl	a,#0f0h;
	swap	a;
	orl	a,b;
	mov	r6,a;//存整数部分
	mov	a,r5;
	anl	a,#0fh;
	swap	a;
	mov	r7,a;//存小数部分
	ret
;=============================================================================================
;CRC校验
;函数原型:bit tcrc(unsigned char data *buf,unsigned char len)
;入口:数据首址在R7;字节数在R5中
;出口:cy=1数据正确;ACC=0数据不正确,需重新读取数据
;=============================================================================================
?PR?_tcrc?DS18B20   SEGMENT CODE 
	PUBLIC	_tcrc

RSEG  ?PR?_tcrc?DS18B20


_tcrc:	                 ;字节计数单元赋初值
	mov	r2,#0;	移位寄存器清零
	mov	a,r7;
	mov	r0,a;
tcrc2:	mov	a,@r0;
	mov	r3,a;
	mov	r6,#8;移位次数单元赋初值
tcrc3:	xrl	a,r2;
	anl	a,#01h;
	mov	r4,a;
	mov	a,r2;
	clr	c;
	rrc	a;
	cjne	r4,#1,tcrc4;结果为1进行异或操作
	xrl	a,#8ch;
tcrc4:	mov	r2,a;
	mov	a,r3;
	rrc	a;
	mov	r3,a;
	djnz	r6,tcrc3;
	inc	r0;
	djnz	r5,tcrc2;
	mov	a,r2;
	setb	c;	
	jz	tcrc5;
	clr	c;
tcrc5:	ret
;=============================================================================================
;单字节BCD码转换为单字节HEX
;入口:ACC
;出口:ACC
;=============================================================================================
bcdh:	mov	b,#10;
	div	ab;
	mov	r4,b;
	mov	b,#10;
	mul	ab;
	add	a,r4;
	ret;
;============================================================================================
;延时子程序
;===========延时值的计算=================
;	mov	r5,#x1;	//2MC
;loop:	mov	r6,#x2;//2MC
;	djnz	r6,$;	//2/3MC
;	djnz	r5,loop;//2/3MC
;	ret		//2
;time = x1(2/3*x2+2+2/3)/24.5;
;========================================
;;延时大于480u
delay_500uS:		;延时大于480uS
	mov	r5,#2;
d500_1:	mov	r6,#130;
	djnz	r6,$;		
	djnz	r5,d500_1; 
	ret	
		
delay_90uS:
	MOV	R5,#2;
d90_1:	mov	r6,#20;
	DJNZ	R6,$;
;  	jnb	DQ,i_rett;
	djnz	R5,d90_1;
;	ajmp    i_rett1
;i_rett:nop
; 	clr	DQ1;
 ;i_rett1: 
	ret
	
delay_400uS:
	mov	r5,#2;
d400_1:	mov	r6,#100;
	djnz	r6,$;
	djnz	r5,d400_1;
	ret
	
	end				

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -