基于AVR128的DS18B20源程序
- 格式:doc
- 大小:19.00 KB
- 文档页数:4
DS18B20原理及程序编写(一)概述DS18B20为单总线12位(二进制)温度读数。
内部有64位唯一的ID编码。
工作电压从3.0~5.5V。
测量温度范围从-55℃~125℃。
最高±0.0625℃分辩率。
其内部结构如下图所示。
DS18B20的核心功能是直接数字温度传感器。
温度传感器可以配置成9、10、11和12位方式。
相应的精度分别为:0.5℃、0.25℃、0.125℃和0.0625℃。
默认的分辨率为12位。
DS18B20在空闲低功耗状态下加电(寄生电源工作方式)。
主机必须发出Convert T [44h]命令使其对测量温度进行A-D转换。
接下来进行采集转换,结果存于两字节高速温度寄存器并返回到空闲低功耗状态。
如果DS18B20在外部VDD供电方式下,单片机可以在发出Convert T 命令并总线为1时(总线为0表示正在转换)发出“read time slots”命令。
DS18B20芯片内部共有8字节的寄存器,其中地址编号0,1为温度寄存器,里面存储着DS18B20温度转换后的AD值,其格式如表1所示。
地址编号2,3为温度报警寄存器,里面为报警设定值,地址编号4为配置寄存器(这三个寄存器在读取之前请使用“重新调入EEPROM”命令将存储在EEPROM里的内容调出,同样,在向温度报警寄存器里写入内容后,也要使用“复制到存储器”命令48H将温度报警寄存器内的内容存入EEPROM当中,以免掉电丢失数据)。
DS18B20内部寄存器映射如下图所示。
配置寄存器的格式如表2和表3所示。
DS18B20内部寄存器映射表1 温度寄存器的格式表2 配置寄存器的格式表3 温度分辨率配置DS18B20使用单总线工作方式,其通信协议以电平的高平时间作为依据,其基本时序有复位时序,写时序、读时序。
//********************************************************************** //** 文件名:DS18B20.c//** 说明:DS18B20驱动程序文件//----------------------------------------------------------------------//** 单位://** 创建人:张雅//** 创建时间:2010-01-20//** 联系方式:QQ:276564402//** 版本:V1.0//----------------------------------------------------------------------//**********************************************************************//----------------------------------------------------------------------//** 芯片:AT89S52//** 时钟:11.0592MHz//** 其它:这个文档为18B20的驱动程序,引用了数码管的驱动。
源代码:;这是关于单个DS18B20的测温程序,数据脚为P3.3,晶振是11.059MHZ;(因为我要用到串口通信,只是下面没有给出具体的程序,所以下面的延时用12MHZ计算) ;温度传感器18B20采用器件默认的12位转化,最大转化时间要750毫秒;用1602液晶屏显示,显示温度从00到99度,精确到0.0625度;内存分配声明TEMPER_L EQU 29H;用于保存读出温度的低字节TEMPER_H EQU 28H;用于保存读出温度的高字节T_DF EQU 27H ;FORMA T后的小数部分(decimal fraction),半字节的温度小数(存在低四位) T_INTEGER EQU 26H ;FORMA T后的整数部分(integer),将两字节的温度整合成1字节FLAG1 BIT 50H;位地址50H是字节2AH的最低位,用作是否检测到DS18B20的标志位A_BIT EQU 20h ;液晶十位数存放内存位置B_BIT EQU 21h ;液晶个位数存放内存位置C_BIT EQU 22H ;个位小数D_BIT EQU 23H ;十位小数E_BIT EQU 24H ;百位小数F_BIT EQU 25H ;千位小数RS BIT P3.7 ;这3位是液晶屏的控制信号,连接方式由具体硬件而定RW BIT P3.6E BIT P3.5ORG 0000HLJMP MAINORG 0100HMAIN: LCALL T_CONVERSION;调用读温度子程序LCALL T_FORMA T;将读出的2字节温度格式化LCALL DISPLAY;调用液晶显示子程序LCALL D1S;延时1秒后再测LJMP MAIN;--------------DS18B20的温度转换子程序,具体时序请参考资料-------------------T_CONVERSION:LCALL INIT_1820;先复位DS18B20JB FLAG1,T_C0RET ; 判断DS1820是否存在?若DS18B20不存在则返回T_C0: MOV A,#0CCH ; 跳过ROM匹配LCALL WRITE_1820MOV A,#44H ; 发出温度转换命令LCALL WRITE_1820LCALL D1S ;这里等待AD转换结束,12位的话要延时750m秒LCALL INIT_1820;准备读温度前先复位MOV A,#0CCH ; 跳过ROM匹配LCALL WRITE_1820MOV A,#0BEH ; 发出读温度命令LCALL WRITE_1820LCALL READ_1820; 将读出的温度数据保存到28H(TEMPER_H)和29H(TEMPER_L)处RET;------DS18B20复位初始化程序-----------------------------------------INIT_1820: SETB P3.3NOPCLR P3.3MOV R0,#2 ;主机发出延时500微秒的复位低脉冲INIT0: MOV R1,#250DJNZ R1,$DJNZ R0,INIT0SETB P3.3;然后拉高数据线NOPMOV R0, #15INIT1: JNB P3.3, INIT3;延时60us等待DS18B20回应DJNZ R0, INIT1LJMP INIT4 ; 超时而没有响应INIT3: SETB FLAG1 ; 置标志位,表示DS1820存在LJMP INIT5INIT4: CLR FLAG1 ; 清标志位,表示DS1820不存在LJMP INIT6INIT5: MOV R0, #120DJNZ R0, $ ; 延时240usINIT6: SETB P3.3RET;---------写DS18B20的子程序(有具体的时序要求)-------------------------------------WRITE_1820: MOV R2,#8;一共8位数据WR0: CLR P3.3MOV R3,#6DJNZ R3,$RRC AMOV P3.3,CMOV R3,#20DJNZ R3,$SETB P3.3NOPNOPDJNZ R2,WR0SETB P3.3RET;------读DS18B20的程序,从DS18B20中读出两个字节的温度数据-------------------------- READ_1820: MOV R4,#2 ; 将温度高位和低位从DS18B20中读出MOV R1,#TEMPER_L ; 低位存入29H(TEMPER_L)RE0: MOV R2,#8RE1: SETB P3.3NOPNOPCLR P3.3NOPNOPSETB P3.3MOV R3,#5DJNZ R3, $MOV C,P3.3MOV R3,#20DJNZ R3, $RRC ADJNZ R2,RE1MOV @R1,ADEC R1 ; 高位存入28H(TEMPER_H)DJNZ R4,RE0RET;-----整合读出的两字节温度(关于DS18B20读出的2字节温度格式请参考资料)---------- T_FORMAT: MOV A, #0FHANL A, TEMPER_LMOV T_DF, A ;获得小数部分(4位)MOV A, TEMPER_LSWAP AMOV TEMPER_L, AMOV A, TEMPER_HSWAP AMOV R0, #TEMPER_LXCHD A, @R0MOV T_INTEGER, A ;获得整数部分(1字节)RET;-------液晶显示的子程序(显示前先格式转换)--------------------------------------- DISPLAY: mov a, T_INTEGERmov b,#10div abmov A_BIT,a ;十位存在A_BITmov B_BIT,b ;个位存在B_BITMOV A, T_DFMOV R0, #C_BITMOV R2, #4D0: MOV B, #10MUL ABMOV B, #16DIV ABMOV @R0, A ;从个位小数C_BIT,到十位D_BIT,百位E_BIT,千位F_BITINC R0MOV A, BDJNZ R2, D0;----二进制到ASCII码转换--------------MOV A, #30HORL A_BIT, AORL B_BIT, AORL C_BIT, AORL D_BIT, AORL E_BIT, AORL F_BIT, A;-------------------------------------LCALL INITIALMOV A, #10000000B ; LINE1: DB 'Now is:',00HLCALL WRITE_INSTRUCTIONMOV DPTR, #LINE1LCALL PR_STRINGMOV A, A_BITLCALL WRITE_LCDDATAMOV A, B_BITLCALL WRITE_LCDDATAMOV A, #2EH ;'.'字符LCALL WRITE_LCDDATAMOV A, C_BITLCALL WRITE_LCDDATAMOV A, D_BITLCALL WRITE_LCDDATAMOV A, E_BITLCALL WRITE_LCDDATAMOV A, F_BITLCALL WRITE_LCDDATAMOV A, #0DFH ;下面两个是摄氏度的数字符号LCALL WRITE_LCDDATAMOV A, #63HLCALL WRITE_LCDDATAmov a, #11000000B ; LINE2: DB 'Design by liang!',00HLcall write_instructionMOV DPTR, #LINE2LCALL PR_STRINGRET;---液晶屏初始化,具体请参考资料------------------------------------------------- initial: MOV A, #01HLCALL WRITE_INSTRUCTIONMOV A, #38HLCALL WRITE_instructionMOV A, #0FHLCALL WRITE_instructionMOV A, #06HLCALL WRITE_instructionRET;----写液晶指令的子程序------------------------------------------WRITE_instruction: MOV P1, ACLR RS ;写入控制命令CLR RWCLR ELCALL DELAYSETB ERET;----写液晶数据的子程序---------------------------------------------write_lcddata: MOV P1, ASETB RS ;写入数据CLR RWCLR ELCALL DELAY ;判断液晶模块是否忙?SETB ERET;-----写行字符的子程序---------------------------------------------------------------PR_STRING: CLR AMOVC A, @A+DPTRJZ END_PRLCALL WRITE_LCDDATAINC DPTRLJMP PR_STRINGEND_PR: RET;----查看液晶忙碌信号的子程序--------------------------------------------------------- DELAY: MOV P1,#0FFH ;判断液晶显示器是否忙的子程序CLR RSSETB RWCLR ENOPSETB EJB P1.7,DELAY ;如果P1.7为高电平表示忙就循环等待RET;---1mS延时(按12MHZ算)----------------------------------------------------------------- D1mS: MOV R7,#250LOOP0: NOPNOPDJNZ R7,LOOP0RET;----1S延时(按12MHZ算)----------------------------------------------------------------- D1S: Mov R6,#4LOOP2: mov R5,#250LOOP1: LCALL D1mSDJNZ R5,LOOP1DJNZ R6,LOOP2RET;--------------------------------------------------------------------------------------LINE1: DB 'Now is:',00HLINE2: DB 'Design by liang!',00HEND。
DS18B20温度传感器数字温度传感器DS18B20是由Dallas半导体公司生产的,它具有耐磨耐碰,体积小,使用方便,封装形式多样(如图1.1.1),适用于各种狭小空间设备数字测温和控制领域。
图1.1.1引脚说明:GND为接地引脚;DQ为数据输入输出脚。
用于单线操作,漏极开路;VCC接电源正;单总线通常要求接一个约4.7K左右的上拉电阻,这样,当总线空闲时,其状态为高电平。
如图1.1.2是温度传感器DS18B20的接线图图1.1.2温度传感器DS18B20的参数:●适应电压范围更宽,电压范围:3.0~5.5V,在寄生电源方式下可由数据线供电●温范围-55℃~+125℃,在-10~+85℃时精度为±0.5℃●可编程的分辨率为9~12位,对应的可分辨温度分别为0.5℃、0.25℃、0.125℃和0.0625℃,可实现高精度测温●在9位分辨率时最多在93.75ms内把温度转换为数字,12位分辨率时最多在750ms内把温度值转换为数字,速度更快●被测温度用符号扩展的16位数字量方式串行输出●有两种供电方式既可以直接加 3.0~5.5V的电源,也可以采用寄生电源方式由数据线供电DS18B20内部结构及功能:DS18B20的内部结构如图1.1.3所示。
主要包括:寄生电源,温度传感器,64位ROM和单总线接口,存放中间数据的高速暂存器RAM,用于存储用户设定温度上下限值的TH和TL触发器,存储与控制逻辑,8位循环冗余校验码(CRC)发生器等7部分。
开始8位是产品类型的编号,接着共有48 位是DS18B20 唯一的序列号。
最后8位是前面56 位的CRC 检验码,这也是多个DS18B20 可以采用一线进行通信的原因。
高速暂存存储器:高速暂存存储器由9个字节组成,其分配如图所示。
高速暂存存储器字节0~1 温度寄存器当DS18B20接收到温度转换命令后,开始启动转换。
转换完成后的温度值就以16位带符号扩展的二进制补码形式存储在高速暂存存储器的第1,2字节。
单片机中使用DS18B20温度传感器C语言程序(参考1)/********************************************************************************DS18B20 测温程序硬件:AT89S52(1)单线ds18b20接P2.2(2)七段数码管接P0口(3)使用外部电源给ds18b20供电,没有使用寄生电源软件:Kei uVision 3**********************************************************************************/ #include "reg52.h"#include "intrins.h"#define uchar unsigned char#define uint unsigned intsbit ds=P2^2;sbit dula=P2^6;sbit wela=P2^7;uchar flag ;uint temp; //参数temp一定要声明为int 型uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //不带小数点数字编码uchar code table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; //带小数点数字编码/*延时函数*/void TempDelay (uchar us){while(us--);}void delay(uint count) //延时子函数{uint i;while(count){i=200;while(i>0)i--;count--;}}/*串口初始化,波特率9600,方式1 */void init_com(){TMOD=0x20; //设置定时器1为模式2 TH1=0xfd; //装初值设定波特率TR1=1; //启动定时器SM0=0; //串口通信模式设置SM1=1;// REN=1; //串口允许接收数据PCON=0; //波特率不倍频// SMOD=0; //波特率不倍频// EA=1; //开总中断//ES=1; //开串行中断}/*数码管的显示*/void display(uint temp){uchar bai,shi,ge;bai=temp/100;shi=temp%100/10;ge=temp%100%10;dula=0;P0=table[bai]; //显示百位dula=1; //从0到1,有个上升沿,解除锁存,显示相应段dula=0; //从1到0再次锁存P0=0xfe;wela=1;wela=0;delay(1); //延时约2ms P0=table1[shi]; //显示十位dula=1;dula=0;P0=0xfd;wela=1;wela=0;delay(1);P0=table[ge]; //显示个位dula=1;dula=0;P0=0xfb;wela=1;wela=0;delay(1);}/*****************************************时序:初始化时序、读时序、写时序。
DS18B20汇编程序;实验目的:熟悉DS18B20的使用;六位数码管显示温度结果,其中整数部分2位,小数部分4位;每次按下RB0键后进行一次温度转换。
;硬件要求:把DS18B20插在18B20插座上; 拨码开关S10第1位置ON,其他位置OFF; 拨码开关S5、S6全部置ON,其他拨码开关全部置OFF;*****************以下是暂存器的定义*****************************#INCLUDE<P16F877A.INC>#DEFINE DQ PORTA,0 ;18B20数据口__CONFIG_DEBUG_OFF&_CP_ALL&_WRT_HALF&_CPD_ON&_LVP_OFF&_BODEN_OFF&_PWRTE_ON&_WDT_OFF&_HS _OSCCBLOCK 20HDQ_DELAY1DQ_DELAY2TEMPTEMP1TEMP2 ;存放采样到的温度值TEMP3COUNTCOUNT1ENDCTMR0_VALUE EQU 0AH ;寄存器初值为6,预分频比1:4,中断一次时间为4*(256-6)=1000usDQ_DELAY_VALUE1 EQU 0FAHDQ_DELAY_VALUE2 EQU 4H;**********************以下是程序的开始************************ ORG 00HNOPGOTO MAIN ;入口地址ORG 04HRETFIE ;在中断入口出放置一条中断返回指令,防止干扰产生中断TABLEADDWF PCL,1RETLW 0C0H ;0的编码(公阳极数码管)RETLW 0F9H ;1的编码RETLW 0A4H ;2的编码RETLW 0B0H ;3的编码RETLW 99H ;4的编码RETLW 92H ;5的编码RETLW 082H ;6RETLW 0F8H ;7RETLW 080H ;8RETLW 090H ;9;***************************主程序******************************* MAINCLRF PORTACLRF PORTBBANKSEL TRISACLRF TRISA ;A口所有先设置为输出CLRF TRISDMOVLW 01HMOVWF TRISB ;B0口为输入,其他为输出MOVLW 06HMOVWF ADCON1 ;关闭所有A/D口MOVLW 01HMOVWF OPTION_REG ;分频比1:4,定时器,内部时钟源BCF STATUS,RP0CLRF TEMPCLRF TEMP1CLRF TEMP2 ;清零临时寄存器MOVLW 8HMOVWF COUNTMOVLW 38HMOVWF FSRCLRF INDFINCF FSR,1DECFSZ COUNT,1GOTO $-3;****************************循环处理部分************************;先启动18B20温度转换程序,在判断温度转换是否完成(需750us);未完成则调用显示子程序,直到完成温度转换;完成后读取温度值;送LCD显示LOOPBTFSC PORTB,0 ;判断温度转换按键是否按下GOTO LOOP1 ;否,转显示CALL DELAY ;消抖BTFSC PORTB,0 ;再次判断GOTO LOOP1CALL RESET_18B20 ;调用复位18B20子程序MOVLW 0CCHMOVWF TEMPCALL WRITE_18B20 ;SKIP ROM命令MOVLW 44HMOVWF TEMPCALL WRITE_18B20 ;温度转换命令CLRF STATUSCALL DELAY_750MS ;调用温度转换所需要的750MS延时NOPCALL RESET_18B20MOVLW 0CCHMOVWF TEMPCALL WRITE_18B20 ;SKIP ROM命令MOVLW 0BEHMOVWF TEMPCALL WRITE_18B20 ;读温度命令CALL READ_18B20 ;调用读温度低字节MOVFW TEMPMOVWF TEMP1 ;保存到TEMP1CALL READ_18B20 ;调用读温度高字节MOVFW TEMPMOVWF TEMP2 ;保存到TMEP2CALL RESET_18B20LOOP1CALL TEMP_CHANGE ;调用温度转换程序CALL DISPLAY ;调用LCD显示程序GOTO LOOP ;循环工作;*********************复位DS18B20子程序************************** RESET_18B20;根据DATASHEET介绍,写数据时应遵照如下规定:;主控制器把总线拉低至少480us,;18B20等待15-60us后,把总线拉低做为返回给控制器的应答信号BANKSEL TRISABCF TRISA,0BCF STATUS,RP0BCF DQMOVLW 0A0HMOVWF COUNT ;160USDECFSZ COUNT,1GOTO $-1 ;拉低480usBSF DQ ;释放总线MOVLW 14HMOVWF COUNTDECFSZ COUNT,1GOTO $-1 ;等待60usBANKSEL TRISABSF TRISA,0 ;DQ设置为输入BCF STATUS,RP0BTFSC DQ ;数据线是否为低GOTO RESET_18B20 ;否则继续复位MOVLW 4HMOVWF COUNTDECFSZ COUNT,1 ;延时一段时间后再次判断GOTO $-1BTFSC DQGOTO RESET_18B20MOVLW 4BHMOVWF COUNTDECFSZ COUNT,1GOTO $-1BANKSEL TRISABCF TRISA,0 ;DQ设置为输出BCF STATUS,RP0RETURN;*********************写DS18B20子程序**************************** WRITE_18B20;根据DATASHEET介绍,写数据时应遵照如下规定:;写数据0时,主控制器把总线拉低至少60us;写数据1时,主控制器把总线拉低,但必须在15us内释放MOVLW 8HMOVWF COUNT ;8位数据BANKSEL TRISABCF TRISA,0BCF STATUS,RP0BCF STATUS,CWRITE_18B20_1BSF DQ ;先保持DQ为高MOVLW 5HMOVWF COUNT1BCF DQ ;拉低DQ15usDECFSZ COUNT1,1GOTO $-1RRF TEMP,1BTFSS STATUS,C ;判断写的数据为0还是1GOTO WRITE_0BSF DQ ;为1,立即拉高数据线GOTO WRITE_ENDWRITE_0BCF DQ ;继续保持数据线为低WRITE_ENDMOVLW 0FHMOVWF COUNT1 ;保持45msDECFSZ COUNT1,1GOTO $-1BSF DQ ;释放总线DECFSZ COUNT,1 ;是否写完8位数据GOTO WRITE_18B20_1RETURN;**********************读DS18B20子程序**************************** READ_18B20;根据DATASHEET介绍,读数据时应遵照如下规定:;读数据0时,主控制器把总线拉低后,18B20再把总线拉低60us;读数据1时,主控制器把总线拉低后,保持总线状态不变;主控制器在数据线拉低后15us内读区数据线上的状态。
Atmega 128控制DS18B20在1602上显示申明:本程序为课程设计测试过程序,直供学习交流。
有共同爱好或相同专业着加本人QQ,以便相互交流学习。
QQ:2528620472//基于DS18B20的水温控制系统//其中PA5为蜂鸣器端口,PA6,7为输出端口,分别控制继电器、蜂鸣器。
DS18B20data为PE3单片机接口//按键为单片机G口的0,1两个口。
设计标准温度,当实际温度大于标准温度,继电器断电,中断加热,同时蜂鸣器报警。
//2015_4_28鹄鹰#include <iom128v.h>#include <macros.h>#define uint unsigned int#define uchar unsigned charuchar const table1 []="0123456789.";uchar const table2 []="temp:+'C";uchar const table3 []="Du Weidong";uint ge,shi,dot1,dot2;uint wendu;uint ge_in=1;uint shi_in=3;void delay (uint ms){uint i,j;for(i=0;i<ms;i++){for(j=0;j<1141;j++);}}void Delay_1us(uint x){uint i;x=x*5/4;for( i=0;i<x;i++);}void DS18B20_rst(){DDRE|=BIT(3);PORTE&=~BIT(3);Delay_1us(500);PORTE|=BIT(3);Delay_1us(60);DDRE&=~BIT(3);while(PINE&BIT(3));while(!(PINE&BIT(3)));}void DS18B20_Write(uchar Data) {uchar i;DDRE|=BIT(3);for(i=0;i<8;i++){PORTE&=~BIT(3);Delay_1us(10);if(Data&0x01) PORTE|=BIT(3); else PORTE&=~BIT(3);Delay_1us(40);PORTE|=BIT(3);Delay_1us(1);Data>>=1;}}uchar DS18B20_Read(){uchar i,Temp;for(i=0;i<8;i++){Temp>>=1;DDRE|=BIT(3);PORTE&=~BIT(3);PORTE|=BIT(3);DDRE&=~BIT(3);if(PINE&BIT(3)) Temp|=0x80; Delay_1us(45);}return Temp;}unsigned int Read_Temperature() {uint Temp1,Temp2;DS18B20_rst();DS18B20_Write(0xCC);DS18B20_Write(0x44);DS18B20_rst();DS18B20_Write(0xCC);DS18B20_Write(0xbe);Temp1=DS18B20_Read();Temp2=DS18B20_Read();DS18B20_rst();return (((Temp2<<8)|Temp1)*6.25);}//*********************************LCD1602**************** **************//*********************************LCD1602**************** **************void write_order(uchar order){PORTA&=~BIT(0);PORTA&=~BIT(1);PORTA&=~BIT(2);PORTC=order;//写指令,将具体的指令写入PORTA|=BIT(2);delay(1);PORTA&=~BIT(2);}void write_data(uchar data){PORTA|=BIT(0);PORTA&=~BIT(1);PORTA&=~BIT(2);PORTC=data;//写数据,将具体的数据写入PORTA|=BIT(2);delay(1);PORTA&=~BIT(2);}void show_LCD (){uchar i,j,K;DDRC=0XFF;DDRA=0X07;write_order (0X38);delay (5);write_order (0X01);delay (5);write_order (0X0C);delay (5);write_order (0x06);delay (5);write_order (0X80+0X48); delay (5);write_data (table1[10]); write_order (0X80+0X40);for(i=0;i<6;i++){write_data (table2[i]);Delay_1us(100);}write_order (0X80+0X4C);for(i=6;i<8;i++){write_data (table2[i]);Delay_1us(100);}write_order (0X80+0X00);for(j=0;j<10;j++){write_data (table3[j]);Delay_1us(100);}}void shuju(uint num)//动态数据显示{uchar i,k;ge=num%1000/100;shi=num/1000;dot1=num%100/10;dot2=num%10;//******************************************** write_order (0X80+0X46);write_data (table1[shi]);Delay_1us(100);//******************************************** write_order (0X80+0X47);write_data (table1[ge]);Delay_1us(100);//******************************************** write_order (0X80+0X49);write_data (table1[dot1]);Delay_1us(100);//******************************************** write_order (0X80+0X4A);write_data (table1[dot2]);Delay_1us(100);//******************************************** write_order (0X80+0X0D);write_data (table1[shi_in]);Delay_1us(100);//******************************************** write_order (0X80+0X0E);write_data (table1[ge_in]);Delay_1us(100);}void jingao (){if (shi>=shi_in&&ge>=ge_in){DDRA|=BIT(5);PORTA|=BIT(5);DDRA|=BIT(6);PORTA|=BIT(6);}else{PORTA&=~BIT(5);PORTA&=~BIT(6);}}//**********************************4X4矩阵键盘*****************************uchar keypress () {uchar j;DDRG|=0X0F; PORTG|=0X0F; DDRG&=0XF0;j=PING;j=PING&0X0F;if(j==0XFF){return 0;}else{return 1;}}uchar keyscan () {uchar key,key_l; delay (10);if(keypress()){key=PING;key&=0X0F;switch (key){case 0X0E: key_l=10;break;case 0X0D: key_l=11;break;case 0X0B: key_l=12;break;case 0X07: key_l=13;break;default : key_l=17;}}else{key_l=17;}return key_l;}void shuru_ge (){uint i,j;i=keypress();j=keyscan();if(i){if(j==10){if(ge_in>=9)ge_in=0;elsege_in=ge_in+1;delay (300);}}else{ge_in=ge_in;}}void shuru_shi (){uint i,j;i=keypress();j=keyscan();if(i){if(j==11){if(shi_in>=9)shi_in=0;elseshi_in=shi_in+1;delay (300);}}else{shi_in=shi_in;}}void main(){show_LCD ();while(1){wendu=Read_Temperature(); shuru_ge ();shuru_shi ();shuju(wendu);Delay_1us(100); jingao ();}}。
ds18b20详解及程序最近都在学习和写单⽚机的程序, 今天有空⼜模仿DS18B20温度测量显⽰实验写了⼀个与DS18B20基于单总线通信的程序. DS18B20 数字温度传感器(参考:智能温度传感器DS18B20的原理与应⽤)是DALLAS 公司⽣产的1-Wire,即单总线器件,具有线路简单,体积⼩的特点。
因此⽤它来组成⼀个测温系统,具有线路简单,在⼀根通信线,可以挂很多这样的数字温度计。
DS18B20 产品的特点:(1)、只要求⼀个I/O ⼝即可实现通信。
(2)、在DS18B20 中的每个器件上都有独⼀⽆⼆的序列号。
(3)、实际应⽤中不需要外部任何元器件即可实现测温。
(4)、测量温度范围在-55 到+125℃之间; 在-10 ~ +85℃范围内误差为±5℃; (5)、数字温度计的分辨率⽤户可以从9 位到12 位选择。
将12位的温度值转换为数字量所需时间不超过750ms;(6)、内部有温度上、下限告警设置。
DS18B20引脚分布图DS18B20 详细引脚功能描述:1、GND 地信号;2、DQ数据输⼊出引脚。
开漏单总线接⼝引脚。
当被⽤在寄⽣电源下,此引脚可以向器件提供电源;漏极开路, 常太下⾼电平.通常要求外接⼀个约5kΩ的上拉电阻.3、VDD可选择的VDD 引脚。
电压范围:3~5.5V; 当⼯作于寄⽣电源时,此引脚必须接地。
DS18B20存储器结构图暂存储器的头两个字节为测得温度信息的低位和⾼位字节;第3, 4字节是TH和TL的易失性拷贝, 在每次电复位时都会被刷新;第5字节是配置寄存器的易失性拷贝, 同样在电复位时被刷新;第9字节是前⾯8个字节的CRC检验值.配置寄存器的命令内容如下:MSB LSBR0和R1是温度值分辨率位, 按下表进⾏配置.默认出⼚设置是R1R0 = 11, 即12位.温度值分辨率配置表4种分辨率对应的温度分辨率为0.5℃, 0.25℃, 0.125℃, 0.0625℃(即最低⼀位代表的温度值)12位分辨率时的两个温度字节的具体格式如下:⾼字节:其中⾼字节前5位都是符号位S, 若分辨率低于12位时, 相应地使最低为0, 如: 当分辨率为10位时, 低字节为:, ⾼字节不变....由上表可看出, 当输出是负温度时, 使⽤补码表⽰, ⽅便计算机运算(若是⽤C语⾔, 直接将结果赋值给⼀个int变量即可).DS18B20 的使⽤⽅法:由于DS18B20 采⽤的是1-Wire 总线协议⽅式,即在⼀根数据线实现数据的双向传输,⽽对单⽚机来说,我们必须采⽤软件的⽅法来模拟单总线的协议时序来完成对DS18B20芯⽚的访问。
基于AVR的DS18b20程序第一篇:基于AVR的DS18b20程序//说明:单片机ATmega16的18B20程序。
调这个18B20程序问题主要出现在延时部分,即单片机实际输出的延时与设定不符。
//后面为别人精确延时,我用自己的单片机通过示波器重新测量实际延时。
建议调延时用示波器先看看。
我用的晶振12M,但延时根本就与理论不符。
其中480us的延时要在480us与960us之间,选取550us 比较合适,一般都这么选。
最后一句话:DS18B20的程序很多,模块基本相似,调不出来就是因为延时问题,示波器是必备工具,否则很盲目。
#include#define uchar unsigned char#define uchar unsigned char#define uint unsigned int//------------------------////.....18B20........void init_1820(void){int Flag_1820Error;uchar i;uint j=0;PORTD|=(1<<7);//PORTC|=(1<<7);PORTD&=~(1<<7);//PORTC&=~(1<<7);for(i=0;i<8;i++)delay(180);//delay_60us();//480us以上PORTD|=(1<<7);//PORTC|=(1<<7);DDRD&=~(1<<7);//DDRC&=~(1<<7);//delay(40);//delay_15us();//15~60usdelay(40);//delay_15us();Flag_1820Error=0;while(PIND&(1<<7){ delay(180);//delay_60us();j++;if(j>=18000){Flag_1820Error=1;break;}}DDRD|=(1<<7);//DDRC|=(1<<7);//PORTC7 is OUTPUTPORTD|=(1<<7);//PORTC|=(1<<7);for(i=0;i<4;i++)delay(180);//delay_60us();//240us}/********************************//********************************/void write_1820(uchar x){uchar m;for(m=0;m<8;m++){if(x&(1<{PORTD&=~(1<<7);//PORTC&=~(1<<7);delay_5us();//5usP ORTD|=(1<<7);//PORTC|=(1<<7);//write“1”delay(40);//delay_ 15us();//15~45usdelay(40);//delay_15us();delay(40);//delay_15us ();}else{PORTD&=~(1<<7);//PORTC&=~(1<<7);delay_15us();//15us delay(40);//delay_15us();//write“0”delay(40);//delay_15us( );//15~45usdelay(40);//delay_15us();PORTD|=(1<<7);//PORTC|=(1<<7);}PORTD|=(1<<7);// PORTC|=(1<<7);}/*******************************/uchar read_1820(void){uchar temp,k,n;temp=0;for(n=0;n<8;n++){PORTD&=~(1<<7);//PORTC&=~(1<<7);delay(13);//delay_5us();PORTD|=(1<<7);//PORTC|=(1<<7);delay(13);//delay_5us();DDRD&=~(1<<7);//DDRC&=~(1<<7);//“PINC7 is INPUT”k=(PIND&(1<<7));//k=(PINC&(1<<7));//读数据,从低位开始if(k)temp|=(1<elsetemp&=~(1<delay(40);//delay_15us();//45usdelay(40);//delay_15us();delay(40);//delay_15us();DDRD|=(1<<7);//DDRC|=(1<<7);//}return(temp);}/*************************************/float read_temperature(void){float temp;////////////uchar teml=0,temh=0;unsigned long t=0;init_1820();//复位18b20write_1820(0xcc);// 发出转换命令write_1820(0x44);//Delay_nms(100);init_1820();write_1820(0xcc);//发出读命令write_1820(0xbe);teml=read_1820();//读数据byte1temh=read_1820();//byte2 t=temh;t=t<<8;t=t|teml;temp=t*0.0625*260/286;return(temp);/*if(t emh&0xf8)sign=0;else sign=1;if(sign==0){temh=255-temh;teml=255-teml;}temh=temh<<4;temh|=(teml&0xf0)>>4;}//再在主程序中调用一下read_temperature(void),读取温度。
DS18B20汇编程序(完整版)DS18B20汇编程序;实验目的:熟悉DS18B20的使用;六位数码管显示温度结果,其中整数部分2位,小数部分4位;每次按下RB0键后进行一次温度转换。
;硬件要求:把DS18B20插在18B20插座上; 拨码开关S10第1位置ON,其他位置OFF; 拨码开关S5、S6全部置ON,其他拨码开关全部置OFF;*****************以下是暂存器的定义*****************************#INCLUDE#DEFINE DQ PORTA,0 ;18B20数据口__CONFIG_DEBUG_OFF&_CP_ALL&_WRT_HALF&_CPD_ON&_LVP_OFF &_BODEN_OFF&_PWRTE_ON&_WDT_OFF&_HS _OSC CBLOCK 20HDQ_DELAY1DQ_DELAY2TEMPTEMP1TEMP2 ;存放采样到的温度值TEMP3COUNTCOUNT1ENDCTMR0_VALUE EQU 0AH ;寄存器初值为6,预分频比1:4,中断一次时间为4*(256-6)=1000usDQ_DELAY_VALUE1 EQU 0FAHDQ_DELAY_VALUE2 EQU 4H;**********************以下是程序的开始************************ ORG 00HNOPGOTO MAIN ;入口地址ORG 04HRETFIE ;在中断入口出放置一条中断返回指令,防止干扰产生中断TABLEADDWF PCL,1RETLW 0C0H ;0的编码(公阳极数码管)RETLW 0F9H ;1的编码RETLW 0A4H ;2的编码RETLW 0B0H ;3的编码RETLW 99H ;4的编码RETLW 92H ;5的编码RETLW 082H ;6RETLW 0F8H ;7RETLW 080H ;8RETLW 090H ;9;***************************主程序******************************* MAINCLRF PORTACLRF PORTBBANKSEL TRISACLRF TRISA ;A口所有先设置为输出CLRF TRISDMOVLW 01HMOVWF TRISB ;B0口为输入,其他为输出MOVLW 06HMOVWF ADCON1 ;关闭所有A/D口MOVLW 01HMOVWF OPTION_REG ;分频比1:4,定时器,内部时钟源BCF STATUS,RP0CLRF TEMPCLRF TEMP1CLRF TEMP2 ;清零临时寄存器MOVLW 8HMOVWF COUNTMOVLW 38HMOVWF FSRCLRF INDFINCF FSR,1DECFSZ COUNT,1GOTO $-3;****************************循环处理部分************************;先启动18B20温度转换程序,在判断温度转换是否完成(需750us);未完成则调用显示子程序,直到完成温度转换;完成后读取温度值;送LCD显示LOOPBTFSC PORTB,0 ;判断温度转换按键是否按下GOTO LOOP1 ;否,转显示CALL DELAY ;消抖BTFSC PORTB,0 ;再次判断GOTO LOOP1CALL RESET_18B20 ;调用复位18B20子程序MOVLW 0CCHMOVWF TEMPCALL WRITE_18B20 ;SKIP ROM命令MOVLW 44HMOVWF TEMPCALL WRITE_18B20 ;温度转换命令CLRF STATUSCALL DELAY_750MS ;调用温度转换所需要的750MS延时NOPCALL RESET_18B20MOVLW 0CCHMOVWF TEMPCALL WRITE_18B20 ;SKIP ROM命令MOVLW 0BEHMOVWF TEMPCALL WRITE_18B20 ;读温度命令CALL READ_18B20 ;调用读温度低字节MOVFW TEMPMOVWF TEMP1 ;保存到TEMP1CALL READ_18B20 ;调用读温度高字节MOVFW TEMPMOVWF TEMP2 ;保存到TMEP2CALL RESET_18B20LOOP1CALL TEMP_CHANGE ;调用温度转换程序CALL DISPLAY ;调用LCD显示程序GOTO LOOP ;循环工作;*********************复位DS18B20子程序************************** RESET_18B20;根据DATASHEET介绍,写数据时应遵照如下规定:;主控制器把总线拉低至少480us,;18B20等待15-60us后,把总线拉低做为返回给控制器的应答信号BANKSEL TRISABCF TRISA,0BCF STATUS,RP0BCF DQMOVLW 0A0HMOVWF COUNT ;160USDECFSZ COUNT,1GOTO $-1 ;拉低480usBSF DQ ;释放总线MOVLW 14HMOVWF COUNTDECFSZ COUNT,1GOTO $-1 ;等待60usBANKSEL TRISABSF TRISA,0 ;DQ设置为输入BCF STATUS,RP0BTFSC DQ ;数据线是否为低GOTO RESET_18B20 ;否则继续复位MOVLW 4HMOVWF COUNTDECFSZ COUNT,1 ;延时一段时间后再次判断GOTO $-1BTFSC DQGOTO RESET_18B20MOVLW 4BHMOVWF COUNTDECFSZ COUNT,1GOTO $-1BANKSEL TRISABCF TRISA,0 ;DQ设置为输出BCF STATUS,RP0RETURN;*********************写DS18B20子程序**************************** WRITE_18B20;根据DATASHEET介绍,写数据时应遵照如下规定:;写数据0时,主控制器把总线拉低至少60us;写数据1时,主控制器把总线拉低,但必须在15us内释放MOVLW 8HMOVWF COUNT ;8位数据BANKSEL TRISABCF TRISA,0BCF STATUS,RP0BCF STATUS,CWRITE_18B20_1BSF DQ ;先保持DQ为高MOVLW 5HMOVWF COUNT1BCF DQ ;拉低DQ15usDECFSZ COUNT1,1GOTO $-1RRF TEMP,1BTFSS STATUS,C ;判断写的数据为0还是1GOTO WRITE_0BSF DQ ;为1,立即拉高数据线GOTO WRITE_ENDWRITE_0BCF DQ ;继续保持数据线为低WRITE_ENDMOVLW 0FHMOVWF COUNT1 ;保持45msDECFSZ COUNT1,1GOTO $-1BSF DQ ;释放总线DECFSZ COUNT,1 ;是否写完8位数据GOTO WRITE_18B20_1RETURN;**********************读DS18B20子程序**************************** READ_18B20;根据DATASHEET介绍,读数据时应遵照如下规定:;读数据0时,主控制器把总线拉低后,18B20再把总线拉低60us ;读数据1时,主控制器把总线拉低后,保持总线状态不变;主控制器在数据线拉低后15us内读区数据线上的状态。
数字温度传感器DS18B20摘要DS-18B20 数字温度传感器具有耐磨耐碰,体积小,使用方便,封装形式多样,适用于各种狭小空间设备数字测温和控制领域。
应用范围广泛,适用于冷冻库,粮仓,储罐,电讯机房,电力机房,电缆线槽等测温和控制领域,轴瓦,缸体,纺机,空调,等狭小空间工业设备测温和控制和汽车空调、冰箱、冷柜、以及中低温干燥箱等。
一、引脚图DS18B20引脚定义:(1)DQ为数字信号输入/输出端;(2)GND为电源地;(3)VDD为外接供电电源输入端(在寄生电源接线方式时接地)二、DS18B20的主要特性1.1、电压范围:3.0~5.5V,在寄生电源方式下可由数据线供电1.2、DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯1.3、多个DS18B20可以并联在唯一的三线上,实现组网多点测温1.4、DS18B20在使用中不需要任何外围元件1.5、温范围-55℃~+125℃,在-10~+85℃时精度为±0.5℃1.6、可编程的分辨率为9~12位,对应的可分辨温度分别为0.5℃、0.25℃、0.125℃和0.0625℃,可实现高精度测温1.7、在9位分辨率时最多在93.75ms内把温度转换为数字,12位分辨率时最多在750ms内把温度值转换为数字,速度更快1.8、测量结果直接输出数字温度信号,以"一线总线"串行传送给CPU,同时可传送CRC校验码,具有极强的抗干扰纠错能力1.9、负压特性:电源极性接反时,芯片不会因发热而烧毁,但不能正常工作。
三、DS18B20的外形和内部结构DS18B20内部结构主要由四部分组成:64位光刻ROM 、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。
DS18B20内部结构图四、DS18B20工作原理DS18B20的温度转换时的延时时间由2s 减为750ms。
DS18B20测温原理如图3所示。
1.单DS18B20温度读取#include<reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intsbit DQ = P1^4; //数据线端口void delayms(uint x) //延时函数{uchar j;while(x--){for(j=0;j<123;j++){;}}}//ROM操作命令#define READ_ROM 0x33 //读ROM#define SKIP_ROM 0xCC //跳过ROM#define MATCH_ROM 0x55 //匹配ROM#define SEARCH_ROM 0xF0 //搜索ROM#define ALARM_SEARCH 0xEC //告警搜索//存储器操作命令#define ANEW_MOVE 0xB8 //重新调出E^2数据#define READ_POWER 0xB4 //读电源#define TEMP_SWITCH 0x44 //启动温度变换#define READ_MEMORY 0xBE //读暂存存储器#define COPY_MEMORY 0x48 //复制暂存存储器#define WRITE_MEMORY 0x4E //写暂存存储器//数据存储结构typedef struct tagTempData{unsigned char btThird; //百位数据unsigned char btSecond; //十位数据unsigned char btFirst; //个位数据unsigned char btDecimal; //小数点后一位数据unsigned char btNegative; //是否为负数}TEMPDATA;void Delay16us() //延时16us子函数{unsigned char a;for (a = 0; a < 4; a++);}void Delay60us() //延时60us子函数{unsigned char a;for (a = 0; a < 18; a++);}void Delay480us() //延时480us子函数{unsigned char a;for (a = 0; a < 158; a++);}void Delay240us() //延时240us子函数{unsigned char a;for (a = 0; a < 78; a++);}void Initialization() //芯片初始化{while(1) //无限循环知道收到了存在脉冲(即DS18B20的应答脉冲){DQ = 0;Delay480us(); //延时480us 复位单总线至少480us的低电平信号DQ = 1;Delay60us(); //延时60us 在复位电平结束后将数据总线拉高,以便在15~60us后接收存在脉冲if(~DQ) //收到ds18b20的应答信号{DQ = 1;Delay240us(); //延时240us 存在脉冲为一个60~240us的低电平信号break;}}}void WriteByte(unsigned char btData) //写ROM(从低位开始写) {unsigned char i, btBuffer;for (i = 0; i < 8; i++){btBuffer = btData >> i; //最低位移出if (btBuffer & 1){DQ = 0;_nop_(); //延时1个机器周期_nop_();DQ = 1;Delay60us(); //延时60us}else{DQ = 0;Delay60us();DQ = 1;}}}unsigned char ReadByte() //读ROM(从低位开始读) {unsigned char i, btDest;for (i = 0; i < 8; i++){btDest >>= 1;DQ = 0;_nop_();_nop_();DQ = 1;Delay16us();if (DQ) btDest |= 0x80;Delay60us();}return btDest;}//读取温度值TEMPDATA ReadTemperature(){TEMPDATA TempData; //定义储存结构用于存储温度的值unsigned int iTempDataH;unsigned char btDot, iTempDataL;TempData.btNegative = 0; //为0温度为正Initialization();WriteByte(SKIP_ROM); //跳过ROM匹配WriteByte(TEMP_SWITCH); //启动温度转换delayms(1); //温度转换需要时间500usInitialization();WriteByte(SKIP_ROM); //跳过ROM匹配(单个芯片时用这句换掉上面的switch)WriteByte(READ_MEMORY); //读暂存储存数据iTempDataL = ReadByte(); //读取温度的低8位iTempDataH = ReadByte(); //读取温度的高8位iTempDataH <<= 8;iTempDataH |= iTempDataL;if (iTempDataH & 0x8000) //判断温度的值是否为负数{TempData.btNegative = 1; //负数标志iTempDataH = ~iTempDataH + 1; //负数求补}btDot = (unsigned char)(iTempDataH & 0x000F); //得到小数部分iTempDataH >>= 4; //得到整数部分btDot *= 5; //btDot*10/16得到转换后的小数数据btDot >>= 3;//数据处理TempData.btThird = (unsigned char)iTempDataH /100; //整数部分的百位TempData.btSecond = (unsigned char)iTempDataH % 100/10;//整数部分的十位TempData.btFirst = (unsigned char)iTempDataH % 10; //整数部分的个位TempData.btDecimal = btDot; //小数点后的一位return TempData; //函数返回温度值的存储结构体}2.多个DS18B20单总线温度读取#include<reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intsbit DQ = P2^7; //数据线端口unsigned char channel,n=0;void delayms(uint x) //延时函数{uchar j;while(x--){for(j=0;j<123;j++){;}}}//ROM操作命令#define READ_ROM 0x33 //读ROM#define SKIP_ROM 0xCC //跳过ROM #define MATCH_ROM 0x55 //匹配ROM #define SEARCH_ROM 0xF0 //搜索ROM//存储器操作命令#define ANEW_MOVE 0xB8//重新调出E^2数据#define READ_POWER 0xB4 //读电源#define TEMP_SWITCH 0x44 //启动温度变换#define READ_MEMORY 0xBE //读暂存存储器#define COPY_MEMORY 0x48 //复制暂存存储器#define WRITE_MEMORY 0x4E //写暂存存储器//数据存储结构typedef struct tagTempData{unsigned char btThird; //百位数据unsigned char btSecond; //十位数据unsigned char btFirst; //个位数据unsigned char btDecimal; //小数点后一位数据unsigned char btNegative; //是否为负数}TEMPDATA;//DS18B20序列号const unsigned char code ROMData1[8] = {0x28, 0x33, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xD7}; //U1const unsigned char code ROMData2[8] = {0x28, 0x30, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x8E}; //U2const unsigned char code ROMData3[8] = {0x28, 0x31, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xB9}; //U3const unsigned char code ROMData4[8] = {0x28, 0x32, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xE0}; //U4const unsigned char code ROMData5[8] = {0x28, 0x34, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x52}; //U5const unsigned char code ROMData6[8] = {0x28, 0x35, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x65}; //U6const unsigned char code ROMData7[8] = {0x28, 0x36, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x3C}; //U7const unsigned char code ROMData8[8] = {0x28, 0x37, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x0B}; //U8void Delay16us() //延时16us子函数{unsigned char a;for (a = 0; a < 4; a++);}void Delay60us() //延时60us子函数{unsigned char a;for (a = 0; a < 18; a++);}void Delay480us() //延时480us子函数{unsigned char a;for (a = 0; a < 158; a++);}void Delay240us() //延时240us子函数{unsigned char a;for (a = 0; a < 78; a++);}void Initialization() //芯片初始化{while(1) //无限循环知道收到了存在脉冲(即DS18B20的应答脉冲){DQ = 0;Delay480us(); //延时480us 复位单总线至少480us的低电平信号DQ = 1;Delay60us(); //延时60us 在复位电平结束后将数据总线拉高,以便在15~60us后接收存在脉冲if(!DQ) //收到ds18b20的应答信号{DQ = 1;Delay240us(); //延时240us 存在脉冲为一个60~240us的低电平信号break;}}}void WriteByte(unsigned char btData) //写ROM(从低位开始写) {unsigned char i, btBuffer;for (i = 0; i < 8; i++){btBuffer = btData >> i; //最低位移出if (btBuffer & 1){_nop_(); //延时1个机器周期_nop_();DQ = 1;Delay60us(); //延时60us}else{DQ = 0;Delay60us();DQ = 1;}}}unsigned char ReadByte() //读ROM(从低位开始读) {unsigned char i, btDest;for (i = 0; i < 8; i++){DQ = 0;_nop_();_nop_();DQ = 1;Delay16us();if (DQ) btDest |= 0x80;Delay60us();}return btDest;}//序列号匹配void MatchROM(const unsigned char *pMatchData) {unsigned char i;Initialization(); //芯片初始化WriteByte(MATCH_ROM); //写入匹配ROM指令for (i = 0; i < 8; i++) WriteByte(*(pMatchData + i)); }//读取温度值TEMPDATA ReadTemperature(){TEMPDATA TempData; //定义储存结构用于存储温度的值unsigned int iTempDataH;unsigned char btDot, iTempDataL;static unsigned char i = 0;TempData.btNegative = 0; //为0温度为正i++;if (i == 9) i = 1;channel=i;Initialization();WriteByte(SKIP_ROM); //跳过ROM匹配WriteByte(TEMP_SWITCH); //启动温度转换if(n==0)delayms(1000); //温度转换需要时间500msn++;if(n==8)n=1;delayms(1);Initialization();//多个芯片的时候用MatchROM(ROMData)换掉WriteByte(SKIP_ROM)switch (i){case 1 : MatchROM(ROMData1); break; //匹配1case 2 : MatchROM(ROMData2); break; //匹配2case 3 : MatchROM(ROMData3); break; //匹配3case 4 : MatchROM(ROMData4); break; //匹配4case 5 : MatchROM(ROMData5); break; //匹配5case 6 : MatchROM(ROMData6); break; //匹配6case 7 : MatchROM(ROMData7); break; //匹配7case 8 : MatchROM(ROMData8); break; //匹配8 }//WriteByte(SKIP_ROM); //跳过ROM匹配(单个芯片时用这句换掉上面的switch)WriteByte(READ_MEMORY); //读暂存储存数据iTempDataL = ReadByte(); //读取温度的低8位iTempDataH = ReadByte(); //读取温度的高8位iTempDataH <<= 8;iTempDataH |= iTempDataL;if (iTempDataH & 0x8000) //判断温度的值是否为负数{TempData.btNegative = 1; //负数标志iTempDataH = ~iTempDataH + 1; //负数求补}btDot = (unsigned char)(iTempDataH & 0x000F); //得到小数部分iTempDataH >>= 4; //得到整数部分btDot *= 5; //btDot*10/16得到转换后的小数数据btDot >>= 3;//数据处理TempData.btThird = (unsigned char)iTempDataH / 100;//整数部分的百位TempData.btSecond = (unsigned char)iTempDataH % 100 / 10;//整数部分的十位TempData.btFirst = (unsigned char)iTempDataH % 10;//整数部分的个位TempData.btDecimal = btDot; //小数点后的一位return TempData; //函数返回温度值的存储结构体}3. DS18B20的序列号读取程序<用LCD1602显示序列号>#include<reg52.h>#include<LCD1602.h>#include<string.h>#define uchar unsigned char#define uint unsigned intuchar sn[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10};uchar t;uchart01,t02,t11,t12,t21,t22,t31,t32,t41,t42,t51,t52,t61,t62,t71,t72;sbit DQ=P2^7;//ds18b20与单片机连接口void delay1ms(unsigned int ms)// 延时1毫秒(不够精确的){unsigned int i,j;for(i=0;i<ms;i++)for(j=0;j<100;j++);}void delay_18B20(unsigned int i)// 延时1微秒{while(i--);}void ds1820rst()/*ds1820复位*/{unsigned char x=0;DQ = 1; //DQ复位delay_18B20(4); //延时DQ = 0; //DQ拉低delay_18B20(100); //精确延时大于480usDQ = 1; //拉高delay_18B20(40);}uchar ds1820rd()/*读数据*/{unsigned char i=0;unsigned char dat = 0;for (i=8;i>0;i--){DQ = 0; //给脉冲信号dat>>=1;DQ = 1; //给脉冲信号if(DQ)dat|=0x80;delay_18B20(10);}return(dat);}void ds1820wr(uchar wdata)/*写数据*/{unsigned char i=0;for (i=8; i>0; i--){DQ = 0;DQ = wdata&0x01;delay_18B20(10);DQ = 1;wdata>>=1;}}////////////////////////读取器件序列号子程序////////////////////////////void rom(void){ds1820rst(); //复位//delay1ms(1); //延时//ds1820wr(0x33); //发送读序列号子程序//sn[0]=ds1820rd(); //连续读出64位ROM t01=sn[0]/16;t02=sn[0]%16; //转为16进制sn[1]=ds1820rd(); //t11=sn[1]/16;t12=sn[1]%16; //转为16进制sn[2]=ds1820rd(); //t21=sn[2]/16;t22=sn[2]%16; //转为16进制sn[3]=ds1820rd(); //t31=sn[3]/16;t32=sn[3]%16; //转为16进制sn[4]=ds1820rd(); //t41=sn[4]/16;t42=sn[4]%16; //转为16进制sn[5]=ds1820rd(); //t51=sn[5]/16;t52=sn[5]%16; //转为16进制sn[6]=ds1820rd(); //t61=sn[6]/16;t62=sn[6]%16; //转为16进制sn[7]=ds1820rd(); //t71=sn[7]/16;t72=sn[7]%16; //转为16进制}void chuan(uchar i,uchar j,uchar x) {if(x<10)DisplayOne(i,j,x,1);if(x==10)DisplayOne(i,j,'A',0);if(x==11)DisplayOne(i,j,'B',0);if(x==12)DisplayOne(i,j,'C',0);if(x==13)DisplayOne(i,j,'D',0);if(x==14)DisplayOne(i,j,'E',0);if(x==15)DisplayOne(i,j,'F',0);}void Displaychar(){chuan(0,0,t01);chuan(0,1,t02);chuan(0,4,t11);chuan(0,5,t12);chuan(0,8,t21);chuan(0,9,t22);chuan(0,12,t31);chuan(0,13,t32);chuan(1,0,t41);chuan(1,1,t42);chuan(1,4,t51);chuan(1,5,t52);chuan(1,8,t61);chuan(1,9,t62);chuan(1,12,t71);chuan(1,13,t72);}/********************主程序***********************************/void main(){Clear();Init();while(1){rom(); //调用读序列号子程序//Displaychar();}}。
基于A VR128的DS18B20源程序
——龙毅强毕业设计
#include<iom128.h>
#include"delay_18b20.c"
#define DQON PORTA_PORTA7=1; //数据高
#define DQOFF PORTA_PORTA7=0; //数据低
//#define DS_DIR DDRA_DDA7; //I/O方向选择
unsigned char Temp_sign;//指示温度值的正负,方便LCD显示用
void delay_ms(unsigned int data)
{
unsigned int i;
for(i=0;i<data;i++)
{
delay_us(999);
delay(5);
}
}
Init_DS18B20(void) //DS18B20初始化
{
DDRA_DDA7=1;//DQ为输出模式
do
{
do
{
DQON; //DQ置高
delay_us(1); //延时
DQOFF; //发送复位脉冲
delay_us(600); //延时600us(>480us)
DQON; //拉高数据线
delay_us(40); //等待(15~60us)
DDRA_DDA7=0;//DQ为输入模式
}while(PINA&=0x80) ; //检测信号线,若为低,进行下一步,否则重新初始化
delay_us(240); //等待240us
}while(!(PINA&=0x80));//等待240us内信号线变高,如果高表示初始化完成,否则重新初始化
delay_us(600); //延时至少480us,确保应答正确
}
ReadOneChar(void)
{
unsigned char i=0;
unsigned char dat=0;
for(i=8;i>0;i--)
{
//DQON;
//delay(1);
DDRA_DDA7=1;//DQ为输出模式
DQOFF; //拉低数据线
dat>>=1;
DQON; //主机将总线拉高
DDRA_DDA7=0;//DQ为输入模式
if(PINA&0x80)
dat|=0x80;
delay_us(100); //延时(>60us)
}
return(dat);
}
WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for(i=8;i>0;i--)
{
DDRA_DDA7=1;//DQ为输出模式
DQOFF; //拉低数据线
if(dat&0x01)
{DQON;} //写“1”
else
{DQOFF;} //写“0”
delay_us(100); //延时(>60us)
DQON;
delay_us(1);
dat>>=1;
}
delay_us(100);
}
float ReadTemperature(void)
{
unsigned int tempL; //临时变量:温度低位(LSB)unsigned int tempH; //临时变量:温度高位(MSB)
unsigned int temp; //临时变量:温度补码(MSB+LSB)
float temperature; //实际温度值
Init_DS18B20();
WriteOneChar(0xcc); //跳过读系列号的操作
WriteOneChar(0x44); //启动温度变换
delay_ms(750); //转化需要一定时间,延时750ms
Init_DS18B20();
WriteOneChar(0xcc);
WriteOneChar(0xbe); //读温度寄存器(头两个值分别为温度的低位和高位)tempL=ReadOneChar();
tempH=ReadOneChar();
temp=(tempH<<=8)|tempL;
if(tempH&0xf8) //温度为负
{
Temp_sign=0;//全局变量Temp_sign=0表明温度为负
temperature=((~temp)+1)*0.0625;
}
else //温度为正
{
Temp_sign=1;//全局变量Temp_sign=1表明温度为正
temperature=temp*0.0625;
}
delay_ms(150);
return temperature;
}
void main(void)
{
unsigned int i=0,j=0;
float TEMP;
while(1)
{
TEMP=ReadTemperature();
if(Temp_sign==0)
i++;
else if(TEMP>25.0)
i++;
else if(TEMP<10.0)
i++;
else
j++;
//delay_ms(2);
delay_s(1);
}
/*unsigned char data[10],i;
Init_DS18B20();
WriteOneChar(0x33); //跳过读系列号的操作for(i=0;i<9;i++)
data[i]=ReadOneChar();
data[10]=0;*/
}。