温度传感器DS18B20原理图:
onewire总线
比赛中,官方提供的资源包里会头文件onewire.h和源代码onewire.c。把头文件和源代码添加到工程文件夹中,然后进行修改即可。
代码解析:
修改的地方:官方提供的资源包里面提供的是51通信程序,比赛用的是15系列的单片机,在相同晶振下15单片机的速度是51单片机的8-12倍。为了方便计算,在onewire.c源代码里的延时函数后面全给它添加一个0。下面是修改完成之后的代码。
onewire.c
/*
程序说明: 单总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
日 期: 2011-8-9
*/
#include "reg52.h"
sbit DQ = P1^4; //单总线接口
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
while(t--);
}
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(50);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(50);
}
//从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(50);
}
return dat;
}
//DS18B20设备初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(120);
DQ = 0;
Delay_OneWire(800);
DQ = 1;
Delay_OneWire(100);
initflag = DQ;
Delay_OneWire(50);
return initflag;
}
添加的代码:
官方提供只是提供的一部分程序,还需要我们添加一些驱动。
unsigned long Temperget(void); //需要在onewire.h头文件中进行定义
{
unsigned char low,high;
unsigned long temp;
init_ds18b20();
Write_DS18B20(0xCC);
Write_DS18B20(0x44);
Delay_OneWire(200);
init_ds18b20();
Write_DS18B20(0xCC);
Write_DS18B20(0xBE);
low=Read_DS18B20();
high=Read_DS18B20();
temp=(high&0x0f);
temp<<=8;
temp=temp|low;
temp=temp*625;
return temp;
}
onewire.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
unsigned long Temperget(void); //添加程序的定义
#endif
实现代码
结合半小时程序:
#include <STC15F2K60S2.H>
#include <ONEWIRE.H>
#define uchar unsigned char
#define uint unsigned int
uchar SMG_duanma[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xbf,0xff};
uchar yi,er,san,si,wu,liu,qi,ba;
long wendu;
void Allinit(void);
void Delayms(int ms);
void Display1(uchar yi,uchar er);
void Display2(uchar san,uchar si);
void Display3(uchar wu,uchar liu);
void Display4(uchar qi,uchar ba);
void main(void)
{
Allinit();
while(1)
{
wendu=Temperget();
yi=wendu/100000;er=wendu%100000/10000+10; //后面+10,就是在数码管上加上小数点
san=wendu%10000/1000;si=21;wu=21;liu=21;qi=21;ba=21; //显示到小数点后一位
Display1(yi,er);
Display2(san,si);
Display3(wu,liu);
Display4(qi,ba);
}
}
void Display1(uchar yi,uchar er)
{
P2|=0xC0;
P2&=0xDF;
P0=0x01;
P2|=0xE0;
P2&=0xFF;
P0=SMG_duanma[yi];
Delayms(1);
P2|=0xC0;
P2&=0xDF;
P0=0x02;
P2|=0xE0;
P2&=0xFF;
P0=SMG_duanma[er];
Delayms(1);
}
void Display2(uchar san,uchar si)
{
P2|=0xC0;
P2&=0xDF;
P0=0x04;
P2|=0xE0;
P2&=0xFF;
P0=SMG_duanma[san];
Delayms(1);
P2|=0xC0;
P2&=0xDF;
P0=0x08;
P2|=0xE0;
P2&=0xFF;
P0=SMG_duanma[si];
Delayms(1);
}
void Display3(uchar wu,uchar liu)
{
P2|=0xC0;
P2&=0xDF;
P0=0x10;
P2|=0xE0;
P2&=0xFF;
P0=SMG_duanma[wu];
Delayms(1);
P2|=0xC0;
P2&=0xDF;
P0=0x20;
P2|=0xE0;
P2&=0xFF;
P0=SMG_duanma[liu];
Delayms(1);
}
void Display4(uchar qi,uchar ba)
{
P2|=0xC0;
P2&=0xDF;
P0=0x40;
P2|=0xE0;
P2&=0xFF;
P0=SMG_duanma[qi];
Delayms(1);
P2|=0xC0;
P2&=0xDF;
P0=0x80;
P2|=0xE0;
P2&=0xFF;
P0=SMG_duanma[ba];
Delayms(1);
P2|=0xC0;
P2&=0xDF;
P0=0x80;
P2|=0xE0;
P2&=0xFF;
P0=0xFF;
}
void Allinit(void) //初始化
{
P2|=0xA0;
P2&=0xBF;
P0=0x00;
P2|=0xC0;
P2&=0xDF;
P0=0xFF;
P2|=0xE0;
P2&=0xFF;
P0=0xFF;
P2|=0x80;
P2&=0x9F;
P0=0xFF;
}
void Delayms(int ms) //延时函数
{
int i,j;
for(i=0;i<ms;i++)
for(j=845;j>0;j--);
}