demo.c
/*****************************************************************************
* 步骤:
* 01、分文件把不同功能模块分开
* 02、定义管脚
* 03、定义temp.h文件,把一些全局参数和函数抽象出来,相当于接口
* 04、DS18B20初始化
* 05、DS18B20写数据
* 06、DS18B20读数据
* 07、DS18B20发送转换温度命令
* 08、DS18B20发送读取温度命令
* 09、DS18B20开始读取温度
* 10、处理温度数据(把温度数据包括负号拆分成数组用多个数码管显示)
* 11、动态数码管显示温度
******************************************************************************/
#include <reg52.h>
#include "temp.h"
// 138译码器管脚(动态数码管位选:即显示哪一个数码管)
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
// 动态数码管段选(即数码管显示什么数字)
uchar code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
/*****************************************************************************
* 用来保存温度数据,把温度 temp 拆分成数组:第0位是符号位(可正可负)
* 第1/2/3位是整数位(0-125℃),第4/5位是小数位
******************************************************************************/
uchar DisplayData[8];
/*******************************************************************************
* 函 数 名 : Delay
* 函数功能 : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void Delay(uint i)
{
while(i--);
}
/*******************************************************************************
* 函 数 名 : DataPros
* 函数功能 : 数据处理函数,把温度 temp 拆分成数组
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void DataPros(int temp)
{
float tp; // 温度
if(temp<0) // 如果温度为零下温度
{
DisplayData[0]=0x40; // 负号-
// 因为读取的温度是实际温度的补码,所以减1,再取反求出原码
temp-=1;
temp=~temp;
tp=temp;
}
else
{
DisplayData[0]=0x00; // 如果温度为正数,则去掉负号(即不显示)
tp=temp;
}
/*
留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
算加上0.5,还是在小数点后面
*/
temp=tp*0.0625*100+0.5;
DisplayData[1]=smgduan[temp/10000];
DisplayData[2]=smgduan[temp%10000/1000];
DisplayData[3]=smgduan[temp%1000/100]|0x80; // 0x80是小数点,对应七段码的dp管脚
DisplayData[4]=smgduan[temp%100/10];
DisplayData[5]=smgduan[temp%10];
}
/*******************************************************************************
* 函 数 名 : DigDisplay
* 函数功能 : 在动态数码管上显示温度
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void DigDisplay()
{
uchar i;
for(i=0; i<6; i++)
{
switch(i)
{
case(0):
LSA=0; LSB=0; LSC=0; break; // 显示第0位
case(1):
LSA=1; LSB=0; LSC=0; break; // 显示第1位
case(2):
LSA=0; LSB=1; LSC=0; break; // 显示第2位
case(3):
LSA=1; LSB=1; LSC=0; break; // 显示第3位
case(4):
LSA=0; LSB=0; LSC=1; break; // 显示第4位
case(5):
LSA=1; LSB=0; LSC=1; break; // 显示第5位
}
P0=DisplayData[5-i]; // 单个数码管的数据
Delay(100); // 间隔一段时间扫描
P0=0x00; // 数码管消影
}
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
while(1)
{
DataPros(Ds18b20ReadTemp()); // 读取温度,数据处理
DigDisplay(); // 显示温度
}
}
temp.c
#include "temp.h"
/*******************************************************************************
* 函 数 名 : Delay1ms
* 函数功能 : 延时函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Delay1ms(uint y)
{
uint x;
for(; y>0; y--)
{
for(x=110; x>0; x--);
}
}
/*******************************************************************************
* 函 数 名 : Ds18b20Init
* 函数功能 : 初始化
* 输 入 : 无
* 输 出 : 初始化成功返回1,失败返回0
*******************************************************************************/
uchar Ds18b20Init()
{
uchar i;
DSPORT=0; // 拉低总线
// 延时642us,480us-960us范围都行
i=70;
while(i--);
DSPORT=1; // 拉高总线
i=0; // 复位i
while(DSPORT) // 如果初始化成功,则Ds18b20会在15到60us之间返回0,失败则返回1
{
Delay1ms(1);
i++;
if(i>5) // 如果初始化失败,开始计数,5ms后自动返回0
{
return 0; // 初始化失败
}
}
return 1; // 初始化成功
}
/*******************************************************************************
* 函 数 名 : Ds18b20ReadByte
* 函数功能 : 读取一个字节
* 输 入 : 无
* 输 出 : uchar
*******************************************************************************/
uchar Ds18b20ReadByte()
{
uchar tmp, dat;
uint i, j;
for(i=0; i<8; i++)
{
DSPORT=0; // 将数据线拉低“0”
j++; // 延迟1us
DSPORT=1; // 将数据线拉高“1”,释放总线准备读数据
// 延时6us等待数据稳定
j++;
j++;
tmp=DSPORT; // 读数据线的状态得到1个状态位,并进行数据处理
// 先把dat右移1位,腾出最高位,再把tmp左移7位,留下最后一位x,相或后,x就变成了dat的最高位
dat=(dat>>1)|(tmp<<7);
// 读取完之后等待48us再接着读取下一个数
j=4;
while(j--);
}
return dat; // 返回读取的字节数据
}
/*******************************************************************************
* 函 数 名 : Ds18b20WriteByte
* 函数功能 : 向18B20写入一个字节
* 输 入 : dat
* 输 出 : 无
*******************************************************************************/
void Ds18b20WriteByte(uchar dat)
{
uint i, j;
for(i=0; i<8; i++)
{
DSPORT=0; // 数据线先置低电平“0”
j++;
DSPORT=dat&0x01; // 和0x01相与,最后一位由dat的最后一位来决定,0就是0,1就是1,其他位均为0
// 延时68us,持续时间最少60us
j=6;
while(j--);
DSPORT=1; // 将数据线拉到高电平
dat>>=1; // 最后一位已经写入,移出去,为下一次写入做准备
}
}
/*******************************************************************************
* 函 数 名 : Ds18b20ChangTemp
* 函数功能 : 让18b20发出转换温度的命令
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Ds18b20ChangTemp()
{
Ds18b20Init(); // 初始化
Delay1ms(1); // 延迟1ms
Ds18b20WriteByte(0xcc); // 跳过ROM操作命令
Ds18b20WriteByte(0x44); // 温度转换命令
//Delay1ms(100); // 等待转换成功,而如果你是一直刷着的话,就不用这个延时了
}
/*******************************************************************************
* 函 数 名 : Ds18b20ReadTempCom
* 函数功能 : 发送读取温度命令
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Ds18b20ReadTempCom()
{
Ds18b20Init(); // 初始化
Delay1ms(1); // 延迟1ms
Ds18b20WriteByte(0xcc); // 跳过ROM操作命令
Ds18b20WriteByte(0xbe); // 发送读取温度命令
}
/*******************************************************************************
* 函 数 名 : Ds18b20ReadTemp
* 函数功能 : 读取温度
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int Ds18b20ReadTemp()
{
int temp=0; // 温度临时变量
uchar tml, tmh; // tml,tmh分别是温度数据的低8位和高8位,温度数据由两个字节构成,共16位
Ds18b20ChangTemp(); // Ds18b20发出温度转换命令
Ds18b20ReadTempCom(); // 发送读取温度命令
tml=Ds18b20ReadByte(); // Ds18b20中低8位在前,高8位在后,所以先读低8位
tmh=Ds18b20ReadByte(); // 再读高8位
temp=tmh; // 因为高8位的前5位是符号位(+/-),所以先处理高8位
temp<<=8; // 先把temp的16位中的前8位移出(因为初始化时高8位均为0,变成:tmh00000000)
temp|=tml; // 再和低8位相或,变成:tmhtml
return temp; // 返回完整的温度
}
temp.h
/***************************************************************************** * 这里定义和 DS18B20 温度传感器相关的参数, * 这个 .h 文件只定义标准参数,全局参数,相当于 Java 中的接口 ******************************************************************************/ #ifndef _TEMP_H_ #define _TEMP_H_ #include <reg52.h> #ifndef uint #define uint unsigned int #endif #ifndef uchar #define uchar unsigned char #endif // DS18B20 温度传感器管脚 sbit DSPORT=P3^7; // 定义函数 uchar Ds18b20Init(); // Ds18b20 初始化 uchar Ds18b20ReadByte(); // Ds18b20 读数据 void Ds18b20WriteByte(uchar dat); // Ds18b20 写数据 void Ds18b20ChangTemp(); // Ds18b20 发送转换温度命令 void Ds18b20ReadTempCom(); // Ds18b20 发送读取温度命令 int Ds18b20ReadTemp(); // Ds18b20 开始读取温度 void Delay1ms(uint i); // 延迟1ms #endif
实验结果: