DS18B20温度测量
ds18b20.h
#ifndef __DS18B20_H__
#define __DS18B20_H__
#include <reg52.h>
//---重定义关键字---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
//---定义使用的IO口---//
sbit DQ = P3^7;
//---声明全局函数---//
uchar Ds18b20Init(); //DS18B20初始化
uchar Ds18b20ReadByte(); //读一个字节
void Ds18b20WriteByte(uchar dat);//写一个字节
int Ds18b20ReadTemp(); //度温度值
void Send_str(char *str);
void Delay500us();
#endif
ds18b20.c
#include "DS18B20.H"
#include <intrins.h>
bit fg = 1;
//extern char s[20]; //外部变量
void Delay500us() //@11.0592MHz
{
unsigned char i, j;
i = 6;
j = 93;
do
{
while (--j);
} while (--i);
}
void Delay68us() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 1;
j = 183;
do
{
while (--j);
} while (--i);
}
void delay(uint x)
{
while( x -- );
}
void Send_str(char *str)
{
while(*str)
{
SBUF = *str;
str ++;
while(!TI);
TI = 0;
}
}
uchar Ds18b20Init() //DS18B20初始化
{
DQ = 1; //DQ先置高 //确保空闲DQ为高电平
delay(8); //延时一会
DQ = 0; //发送复位脉冲 //将总线拉低480us~960us
Delay500us(); //延时500
DQ = 1; //拉高数据线 (15~60us)
Delay68us();//68us
fg = DQ;
Delay500us(); //延时500us
return fg;//返回初始化结果
}
//读一个字节
uchar Ds18b20ReadByte()
{
uchar i, dat = 0;
for( i = 0; i < 8; i ++)
{
DQ = 1; //确保空闲DQ为高电平
delay(8);
DQ = 0; //先将总线拉低1us
dat >>= 1;
DQ = 1; //然后释放总线
delay(2); //延时6us等待数据稳定
if(DQ) //为1
dat |= 0x80;
Delay68us(); //读取完之后等待一段时间(确保每个读周期>60us)再接着读取下一个数
}
return dat;
}
/****************************************
* 数据线从高电平拉至低电平,产生开始信号
*15us之内将所需写的位送到数据线上
*在15~60us之间对数据线进行采样,如果是高电平就写1,低写0
*****************************************/
//写一个字节
void Ds18b20WriteByte(uchar dat)
{
uchar i, j;
for(i = 0; i < 8; i ++)
{
DQ = 0; //在开始另一个写周期前必须有1us以上的低电平恢复期
j ++; //延时1us
DQ = dat & 0x01;
Delay68us();//延时时间最少60us
DQ = 1; //然后释放总线,至少1us给总线恢复时间
dat >>= 1;
}
}
//度温度值
int Ds18b20ReadTemp()
{
uchar tempH = 0, tempL = 0;
int temp = 0;
Ds18b20Init(); //初始化
Ds18b20WriteByte(0xcc); //跳过ROM操作指令
Ds18b20WriteByte(0x44); //温度转换命令
delay(125); //转换需要点时间,延时
Ds18b20Init(); //初始化
Ds18b20WriteByte(0xcc); //跳过POM操作指令
Ds18b20WriteByte(0xbe); //读温度寄存器(头两个值分别为温度的低位和高位)
tempL = Ds18b20ReadByte(); //读出温度低8位
tempH = Ds18b20ReadByte(); //读出温度高8位
temp = tempH;
temp <<= 8;
temp |= tempL;
return temp;
}
1.c
#include <reg52.h>
#include <stdio.h>
#include "Ds18b20.h"
sfr AUXR = 0x8e;
sfr BRT = 0x9c;
#define F_f 11059200UL
#define Baud_rate 9600UL
uchar code smgduan[17]= //共阴显示0~9的值
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f};
//位选
sbit ASEG = P1^2;
sbit BSEG = P1^3;
sbit CSEG = P1^4;
sbit DSEG = P1^5;
uchar showdata[4] = { 0 };
char s[20] = { 0 };
void UART_Init()
{
PCON &= 0x7F; // 波特率不加倍
SCON = 0x50; //设置串行工作方式1并允许串行接收
AUXR &= 0xFB; //独立波特率发生器时钟12T
BRT = 256 - F_f / (12 * Baud_rate * 32);
AUXR |= 0x11;
}
void seg4show(uchar i)
{
switch(i)
{
case 0: ASEG = 0; BSEG = 1; CSEG = 1; DSEG = 1; break;
case 1: ASEG = 1; BSEG = 0; CSEG = 1; DSEG = 1; break;
case 2: ASEG = 1; BSEG = 1; CSEG = 0; DSEG = 1; break;
case 3: ASEG = 1; BSEG = 1; CSEG = 1; DSEG = 0; break;
default: ASEG = 1; BSEG = 1; CSEG = 1; DSEG = 1; break;
}
P0 = showdata[i];
Delay500us();
P0 = 0x00;
}
void dataProcess(int temp)
{
float tp;
if(temp< 0) //当温度值为负数
{
showdata[0] = 0x40; // -
//因为读取的温度是实际温度的补码,所以减1,再取反求出原码
temp=temp-1;
temp=~temp;
tp=temp;
sprintf(s, "当前温度为: -%0.1f℃\n", tp * 0.0625);
temp=tp*0.0625*10+0.5;
//留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
//算加上0.5,还是在小数点后面。
}
else
{
showdata[0] = 0x00;
tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
//如果温度是正的那么,那么正数的原码就是补码它本身
sprintf(s, "当前温度为: %0.1f℃\n", tp * 0.0625);
temp=tp*0.0625*10+0.5;
//留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
//算加上0.5,还是在小数点后面。
}
showdata[1] = smgduan[temp / 100];
showdata[2] = smgduan[temp / 10 % 10] | 0x80;
showdata[3] = smgduan[temp % 10];
}
void main()
{
uchar i;
DQ = 1;
UART_Init();
EA = 1;
ES = 1;
while(1)
{
dataProcess(Ds18b20ReadTemp());
for(i = 0; i < 4; i ++)
{
seg4show(i);
}
}
}
void UART1_Routine() interrupt 4
{
uchar buf_str;
if(RI)
{
buf_str = SBUF;
if(buf_str == 0xaa )
Send_str(s);
RI = 0;
}
}