温度计全部代码:
ds18b20.c
#include "ds18b20.h"
void delay_1ms(uint y) //输入1就 是延时1ms
{
uint x;
for( ; y>0; y--)
{
for(x=110; x>0; x--);
}
}
void delay_10tus(uint t) //延时(t*10)us
{
do{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
while(--t); //当while里面的值有效,那么do里面的程序一直执行
}
uchar Ds18b20Init() //ds18b20的初始化
{
uchar i;
DSPORT = 0;
delay_10tus(65); //延时约640us(实粗线)
DSPORT = 1; //单片机释放总线就是给其高电平
delay_10tus(6); //延时是60us(细弧线)
i=0;
while(DSPORT) //当总线是高电平时
{
delay_1ms(1);
i++;
if(i>5){
return 0; //又等了5us DSPROT还是高电平则返回0表示初始化失败
}
}
return 1; //DSPROT是低电平(虚粗线)表示初始化成功
}
void Ds18b20WriteByte(uchar dat) //单片机向ds18b20输入一字节数据
{
uint i,j;
for(j=0;j<8;j++){
DSPORT = 0;
_nop_();
_nop_(); //写入1时最少1us所以直接延时2us
DSPORT = dat&0x01; //判断数值最后一位是0还是1
i=6;
while(i--);
delay_10tus(6); //延时60us************************************************
DSPORT = 1; //释放总线,至少1us给总线恢复时间才能接着写入第二个数值
dat >>= 1; //数值向右移一位为下次判断最后一位是0还是1做准备
}
}
uchar Ds18b20ReadByte() //单片机读取ds18b20的数据
{
uchar byte,bi;
uint i,j;
for(j=0;j<8;j++){
DSPORT = 0; //先拉低总线
_nop_();
_nop_(); //延时2us
DSPORT = 1; //释放总线
_nop_();
_nop_();; //延时2us等待数据稳定
bi = DSPORT; //读取数据,从最低位开始读取
byte = (byte>>1) | (bi<<7);
i=4;
while(i--);
delay_10tus(5); //读取完之后等待60us再接着读取下一个数
}
return byte;
}
void Ds18b20ChangeTemp() //发送读取温度命令--转换
{
Ds18b20Init(); //18b20初始化
delay_1ms(1);
Ds18b20WriteByte(0xcc); //跳过ROM操作命令
Ds18b20WriteByte(0x44); //发送读取温度的转换命令
//Delay1ms(100); //等待转换成功,而如果你是一直刷着的话,就不用这个延时了
}
void Ds18b20ReadTempCom() //发送读取温度命令--发送读取温度指令
{
Ds18b20Init();
delay_1ms(1);
Ds18b20WriteByte(0xcc); //跳过ROM操作命令
Ds18b20WriteByte(0xbe); //发送读取温度的读取存储器命令
}
int Ds18b20ReadTemp() //读取温度
{
int temp = 0; //int类型占2个字节,共16位
uchar tmh,tml;
Ds18b20ChangeTemp(); //先写入转换命令
Ds18b20ReadTempCom(); //然后等待转换完成后发送读取温度命令
tml = Ds18b20ReadByte();//先读出低字节
tmh = Ds18b20ReadByte();//再读出高字节
temp = tmh;
temp <<= 8; //相当于在低8位的温度高8位向左移8位到正确位置
temp |= tml; //再把tml放到低8位储存
return temp;
}
ds18b20.h
#ifndef _ds18b20_H_
#define _ds18b20_H_
#include<reg52.h>
#include<intrins.h>
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
sbit DSPORT = P3^7;
void delay_1ms(uint );
void delay_10tus(uint );
uchar Ds18b20Init();
void Ds18b20WriteByte(uchar );
uchar Ds18b20ReadByte();
void Ds18b20ChangeTemp();
void Ds18b20ReadTempCom();
int Ds18b20ReadTemp();
#endif
main.c
/*
实现现象:下载程序后,在DS18B20温度传感器接口处,按照丝印方向插好温度传感器,数码管就会显示
检测的温度值,
注意事项:将LED点阵模块的J1短接片短接到VCC端
*/
#include "reg52.h"
#include "ds18b20.h"
typedef unsigned int u16;
typedef unsigned char u8;
sbit LSA = P3^0;
sbit LSB = P3^1;
sbit LSC = P3^3;
char num = 0;
u8 DisplayData[8];
u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void delay(u16 i)
{
while(i--);
}
void datapros(int temp)
{
float tp;
if(temp<0){
DisplayData[0] = 0x40; //数码管显示一个‘-’来表示负号
temp = temp-1; //因为读取的温度是实际温度的补码,而又是负数所以原码是补码减1然后取反
temp = ~temp; //得到实际温度
tp = temp;
temp = tp*0.0625*100+0.5; //由于temp是整形所以当小数赋给temp时会把小数点后面的数字去掉,
//为了不让小数部分去掉我们乘100把小数变成整数
}
else{
DisplayData[0] = 0x00;
tp = temp;
temp = tp*0.0625*100+0.5;
}
DisplayData[1] = smgduan[temp/10000]; //取出5位数的最高位
DisplayData[2] = smgduan[temp%10000/1000]; //取出次高位
DisplayData[3] = smgduan[temp%1000/100] | 0x80; //取出一位并加上个小数点
DisplayData[4] = smgduan[temp%100/10];
DisplayData[5] = smgduan[temp%10]; //最低位
}
void DigDisplay()
{
u8 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[i]; //向数码管发送数据
delay(100);//间隔一段时间扫描
P0 = 0x00;
}
}
void main()
{
while(1){
datapros(Ds18b20ReadTemp()); //数据处理函数
DigDisplay(); //数码管显示函数
}
}
网友评论