导航: 老古网老古论坛XMOS公共讨论区XMOS开源项目区单片机程序设计嵌入式系统广告区域
→DS18B20单从设备与51的接口程序(最新)[sjpu]

 *第21532篇: DS18B20单从设备与51的接口程序(最新)

  
楼 主:sjpu 2004年4月30日09:50
 DS18B20单从设备与51的接口程序(最新)
;===========================================================================
;DS18B20与80C51系列单片机的接口程序
;单片机晶振24MHz,机器周期为0.5uS
;

; 温度转换--->  ....→读取温度→CRC校验→温度转换→数据处理→其他服务→
;                    ↑_____________↓________________________________↓
;===========================================================================
;1 wire 总线DQ
DQ bit P1^1

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

;===========================================================================
;延时子程序

delay_500uS:  ;延时大于480uS
 mov r5,#2;
d500_1: mov r6,#248;
 djnz r6,$;
 djnz r5,d500_1;
 ret
delay_90uS:
 mov r5,#89;
 djnz r5,$;
 ret
delay_400uS:
 mov r5,#2;
d400_1: mov r6,#198;
 djnz r6,$;
 djnz r5,d400_1;
 ret

;===========================================================================
;主机对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 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;
j_ret: ret  

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


;==============================================================================
write_byte:
 push psw;
 mov r6,#8;
 clr c;
w_loop1:
 rrc a; 数据的低位先发,后发高位
 jc write1;
 clr DQ;
 call delay_90uS;
 setb DQ;
 ajmp w_loop2;
write1: clr DQ;
 nop; 恢复时间延时必须大于1uS
 nop;
 nop;
 nop;
 setb DQ;
 call delay_90uS;
w_loop2:djnz r6,w_loop1;
 pop psw;
 pop acc;
 ret

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

;===============================================================================
read_byte:
 
 push psw;
 mov r6,#8;
read_loop: clr DQ;
 nop; 拉低总线时间应大于1uS
 nop;
 nop;
 setb DQ;
 mov r7,#5; //必须在从拉低总线开始的15uS以内采样总线
 djnz r7,$;
 mov c,DQ;
 rrc a;
 mov r7,#49;延时50uS
 djnz r7,$;
 nop;;恢复时间延时必须大于1uS
 nop
 nop
 djnz r6,read_loop;
 pop psw;
 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;
 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 r5,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 r6,#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 r6,w_scrat_loop;
 ret
 
;=================================================================================
;单从设备将3个暂存器内容复制到E2PROM函数
;函数原型:void copy_scrat(void)
;=================================================================================
?PR?copy_scrat?DS18B20   SEGMENT CODE 
 PUBLIC copy_scrat

RSEG  ?PR?copy_scrat?DS18B20
copy_scrat:
 call _reset_ds18b20; //
 mov a,#0cch; //跳跃ROM命令
 call write_byte;
 mov a,#048h; //复制暂存器命令
 call write_byte; 
 ret
 
;=================================================================================
;单从设备回读E2PROM内容至暂存器函数
;函数原型:void recall_e2p(void)
;=================================================================================
?PR?recall_e2p?DS18B20   SEGMENT CODE 
 PUBLIC recall_e2p

RSEG  ?PR?recall_e2p?DS18B20
recall_e2p:
 call _reset_ds18b20; //
 mov a,#0cch; //跳跃ROM命令
 call write_byte;
 mov a,#0b8h; //回读E2prom命令
 call write_byte; 
 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 r7,a;//低字节
 inc r0;
 mov a,@r0;
 mov r6,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;
 mov r7,a;
 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;
 push acc;
 mov a,r2;
 add a,#25h;
 mov r2,a;
 pop acc;
hbcd_2: jnb acc.5,hbcd_3;
 push acc;
 mov a,r2;
 add a,#12h;
 mov r2,a;
 mov r3,#50;
 pop acc;
hbcd_3: jnb acc.4,hbcd_4;
 mov a,r2;
 add a,#06h;
 da a;
 inc r1;
 mov @r1,a;
 mov a,r3;
 add a,#25h;
 inc r1;
 mov @r1,a;
hbcd_4: pop acc;//恢复数据指针
 mov r1,a;
 ret  
;===================================================================================
;数据求补运算子程序
;入口:R6,R7;R6为高字节
;出口:数据地址不变
;===================================================================================
neg:
 mov a,r6;
 jnb acc.7,neg_ret;//判断数据是否是负数,若非负数则直接退出
 mov a,r7;              //否则求补
 cpl a;
 clr c;
 add a,#1;
 mov r7,a;
 mov a,r6;
 cpl a;
 addc a,#0;
 setb acc.3;//设置负数标志
 mov r7,a;
neg_ret: ret 


  


;==========================================================================================
;整数与小数部分的分离 
;入口:数据在R6,R7中,R6为高字节
;出口:分离的整数在R6中,小数在R7中
;========================================================================================= 
data_apart:
 mov a,r7;
 anl a,#0f0h;
 swap a;
 mov b,a;//
 mov a,r6;
 anl a,#0fh;
 swap a;
 orl a,b;
 mov r6,a;//存整数部分
 mov a,r7;
 anl a,#0fh;
 swap a;
 mov r7,a;//存小数部分
 ret
;=============================================================================================
;CRC校验
;入口:数据首址在R0;
;出口:ACC,ACC=0,数据正确;ACC≠0数据不正确,需重新读取数据
;=============================================================================================
tcrc: mov r7,#9; 字节计数单元赋初值
 mov r2,#0; 移位寄存器清零
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 r7,tcrc2;
 mov a,r2;
 ret
;=============================================================================================
;单字节BCD码转换为单字节HEX
;入口:ACC
;出口:ACC
;=============================================================================================
bcdh: mov b,#10;
 div ab;
 mov r4,b;
 mov b,#10;
 mul ab;
 add a,r4;
 ret;
;============================================================================================
 
 end    

  
2楼:sjpu 2004年4月30日09:55
 write_byte子程序应删除最后的pop acc一句

>>>>>>对该主题发表你的看法

本主题贴数2,分页: [第1页]


[上一篇主题]:大虾们:请你们帮个忙。

[下一篇主题]:液晶显示方法(小屏幕)