一、原理部分
读温度使用的是DS18B20芯片,该芯片通过单总线one-wire协议和单片机进行通讯,在比赛的时候会提供onewire.c和onewire.h两个文件。完整代码会放在最后,下面讲解如何编写读取温度的程序。
跳过ROM操作指令
启动温度转化
开始读取暂存器的数据
完整读温度函数
添加到onewire.c中
unsigned char duwendu()
{
unsigned char high,low;
unsigned int temp=0;
Init_DS18B20();//初始化DS18B20
Write_DS18B20(0xcc);//跳过ROM检查
Write_DS18B20(0x44);//启动温度转化
Delay_OneWire(200);//等待温度转化完成
Init_DS18B20();//再次初始化DS18B20,开始新一轮的操作
Write_DS18B20(0xcc);//跳过ROM检查
Write_DS18B20(0xbe);//读取暂存器中的数据
low=Read_DS18B20();//读取低八位
high=Read_DS18B20();//读取高八位
temp=high<<8;//高八位放进temp
temp|=low; //低八位放进temp
temp = temp*0.0625;//数据转化
return temp;//返回温度值
}
在onewire.h中添加声明
unsigned char duwendu();
二、代码部分
实验平台:CT107D
实验芯片:stc15f2k60s2
实验现象:获取当前环境温度,显示在数码管上
代码如下
onewire.c
#include "onewire.h"
//单总线延时函数
void Delay_OneWire(unsigned int t)
{
t*=12;
while(t--);
}
//DS18B20芯片初始化
bit Init_DS18B20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//读温度
unsigned char duwendu()
{
unsigned char high,low;
unsigned int temp=0;
Init_DS18B20();//初始化DS18B20
Write_DS18B20(0xcc);//跳过ROM检查
Write_DS18B20(0x44);//启动温度转化
Delay_OneWire(200);//等待温度转化完成
Init_DS18B20();//再次初始化DS18B20,开始新一轮的操作
Write_DS18B20(0xcc);//跳过ROM检查
Write_DS18B20(0xbe);//读取暂存器中的数据
low=Read_DS18B20();//读取低八位
high=Read_DS18B20();//读取高八位
temp=high<<8;//高八位放进temp
temp|=low; //低八位放进temp
temp = temp*0.0625;//数据转化
return temp;//返回温度值
}
onewire.h
#ifndef _ONEWIRE_H
#define _ONEWIRE_H
#include "stc15f2k60s2.h"
#define OW_SKIP_ROM 0xcc
#define DS18B20_CONVERT 0x44
#define DS18B20_READ 0xbe
//IC引脚定义
sbit DQ = P1^4;
//函数声明
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
bit Init_DS18B20(void);
unsigned char Read_DS18B20(void);
unsigned char duwendu();//新增
#endif
main.c
# include "stc15f2k60s2.h"
# include "onewire.h"
#define uchar unsigned char
#define uint unsigned int
uchar duan[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,
0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,
0x00,0x40};
uchar dispbuff[8];
uint temp;
bit temp_flag;
void close_buzz()
{
P2 = P2&0x1f|0xa0;
P0 = 0xaf;
P2 = P2&0x1f;
}
void display()
{
static uchar index = 0;
P2 = P2&0x1f|0xe0;
P0 = 0xff;
P2 = P2&0x1f;
P2 = P2&0x1f|0xc0;
P0 = 1<<index;
P2 = P2&0x1f;
P2 = P2&0x1f|0xe0;
P0 = ~duan[dispbuff[index]];
P2 = P2&0x1f;
index++;
index&=0x07;
}
void show_temp()
{
dispbuff[0] = 22;
dispbuff[1] = 22;
dispbuff[2] = 22;
dispbuff[3] = 22;
dispbuff[4] = 22;
dispbuff[5] = 22;
dispbuff[6] = temp/10;
dispbuff[7] = temp%10;
}
void Timer0Init(void) //2毫秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x40; //设置定时初值
TH0 = 0xA2; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
void Timer_display() interrupt 1
{
static uchar temp_count = 0;
TL0 = 0x40; //设置定时初值
TH0 = 0xA2; //设置定时初值
display();
if(++temp_count >= 200)//400ms读取一次温度
{
temp_count = 0;
temp_flag = 1;
}
}
void main()
{
close_buzz();
Timer0Init();
while(1)
{
if(temp_flag == 1)
{
temp=(uchar)duwendu();
temp_flag = 0;
}
show_temp() ;
}
}