单片机+DS18B20温度传感器测温

项目描述:
单片机(STC89C52RCA)通过1-wire总线协议控制DS18B20测量当前环境的温度,并将采集回的温度数据实时显示在LCD1602上。测温范围:-55°C ~ 125°C。超过温度范围时会蜂鸣器响起,LED灯闪烁报警。
C语言代码如下:

/*----------------------------
FileName:TempratureMeasure.h
Function: 头文件
Author: Zhang Kaizhou
Date: 2019-6-21 16:21:00
----------------------------*/
#include 
#include 
#include 
#define uchar unsigned char
#define uint unsigned int

/*主模块端口定义*/
sbit start = P3^4; // 启动温度测量
sbit buzzer = P2^3;
sbit led = P1^7;

/*DS18B20测温模块端口定义*/
sbit DQ = P2^2;

/*LCD1602显示模块端口定义*/
sbit lcdrs = P1^0;
sbit lcdrw = P1^1;
sbit lcden = P2^5;

/*主模块函数声明*/
void start18B20();
void getTemprature();
void setAlarmTemprature(uchar tHigh, uchar tLow);
void tempratureAlarming();
void timer0Init();

/*1-wire总线模块函数声明*/
void initResetBus();
void writeByte18B20(uchar dat);
void writeLogic1();
void writeLogic0();
void readByte18B20(uchar * dat);
bit readBit();

/*LCD1602显示模块函数声明*/
void LCDInit();
void display(float dat);
void writeCommand(uchar command);
void writeData(uchar dat);
void delay(uint xms);
/*---------------------------------------------------------------
FileName: main.c
Function: 单片机通过1-wire总线协议控制DS18B20测量当前环境的温度,
并将采集回的温度数据实时显示在LCD1602上。
Description: 测温范围:-55°C ~ 125°C。超过温度范围时会蜂鸣器响起,
LED灯闪烁报警。
Author: Zhang Kaizhou
Date: 2019-6-21 11:26:22
----------------------------------------------------------------*/
#include "TempratureMeasure.h"

/*定义全局变量*/
float temprature = 25; // 存放从18B20温度暂存器中读取的温度数据

/*主函数*/
void main(){
	LCDInit();
	timer0Init();
//	setAlarmTemprature(0x28, 0x14); // 温度上下限设置为20~30摄氏度
	start18B20();
	while(1){
		getTemprature();
		display(temprature);
		tempratureAlarming();
	}
}

///*设置18B20报警温度的上下限*/
//void setAlarmTemprature(uchar tHigh, uchar tLow){
//	initResetBus();
//	delay(1);
//	writeByte18B20(0xcc); // 总线上只有一个18B20, 跳过ROM序列检测
//	writeByte18B20(0x4e); // 写暂存器指令
//	writeByte18B20(tHigh); // 报警温度上限30摄氏度
//	writeByte18B20(tLow); // 报警温度下限20摄氏度
//}

/*温度报警函数*/
void tempratureAlarming(){
	if(temprature < 20 || temprature > 30){ // 温度上下限为20~30摄氏度
		buzzer = 0; // 开启蜂鸣器报警
		TR0 = 1; // 启动timer0,LED闪烁报警
	}else{
		buzzer = 1;
		TR0 = 0;
	}
}

/*timer0用于LED灯闪烁计时*/
void timer0Init(){
	TMOD = 0x01; // timer0 定时模式 16位定时器 非门控启动
	TH0 = (65536 - 50000) / 256; // 定时50ms
	TL0 = (65536 - 50000) % 256;
	ET0 = 1; // 开timer0溢出中断
	EA = 1; // 开全局中断
}

/*timer0溢出中断服务程序*/
void timer0Service() interrupt 1{
	TH0 = (65536 - 50000) / 256; // 定时50ms
	TL0 = (65536 - 50000) % 256;
	led = ~led;
}

/*启动18B20开始从环境中获取温度*/
void start18B20(){
	initResetBus();
	delay(1);
	writeByte18B20(0xcc); // 总线上只有一个18B20, 跳过ROM序列检测
	writeByte18B20(0x44); // 启动18B20开始温度转换
}

/*MCU从18B20的温度暂存器中读取温度*/
void getTemprature(){
	uchar tLow, tHigh;
	uint result;
	initResetBus(); // 复位总线
	delay(1);
	writeByte18B20(0xcc); // 总线上只有一个18B20, 跳过ROM序列检测
	writeByte18B20(0xbe); // 启动18B20开始温度转换
	readByte18B20(&tLow); // 读取温度暂存器中的低字节
	readByte18B20(&tHigh); // 读取温度暂存器中的低字节
	result = tHigh; // 高低字节合并成一个双字节数据
	result <<= 8;
	result |= tLow;
	temprature = result * 0.0625; // 温度寄存器为12bit, 温度分辨率为0.0625
}
/*-----------------------------
FileName: 1-wireBus.c
Function: 单总线操作相关的函数
Author: Zhang Kaizhou
Date: 2019-6-21 16:23:34
-----------------------------*/
#include "TempratureMeasure.h"

/*定义全局变量*/
uint i; // 延时变量

/*1-wire总线初始化(复位)函数*/
void initResetBus(){
	DQ = 0; // 主控设备将总线拉低(480us~960us), 使得总线处于初始化状态
	i = 103; while(i) i--; // 将总线拉低870us
	DQ = 1; // 释放总线并等待(15~60us)接收18B20的应答信号
	i = 4; while(i) i--; // 延时等待45us
	/*
		若总线上存在18B20设备, 在检测到总线上引第8行释放总线而产生的上升沿信号后,
		等待15~60us之后会将总线拉低60~240us
	*/
	
//	ack = DQ; // 读取18B20的应答信号(若ack = 0, 则总线上存在18B20, 否则无)
//	return ack;
}

/*向DS18B20写一个字节数据的函数*/
void writeByte18B20(uchar dat){
	bit bitFlag;
	uchar i;
	for(i = 0; i < 8; i++){
		bitFlag = dat & 0x01;
		dat >>= 1;
		if(bitFlag){ // 写1
			writeLogic1();
		}else{ // 写0
			writeLogic0();
		}
	}
}

/*向1-wire总线写逻辑1*/
void writeLogic1(){
	DQ = 0; // 将总线拉低至少1us声明要进行写操作(产生写时隙)
	_nop_(); _nop_(); // 延时2 * 1.09us = 2.18us
	DQ = 1; // 从产生写时隙开始在15us之内释放总线
	i = 8; while(i) i--; // 延时71us
}

/*向1-wire总线写逻辑0*/
void writeLogic0(){
	DQ = 0; // 将总线拉低至少1us声明要进行写操作(产生写时隙)
	i = 8; while(i) i--; // 延时71us
	DQ = 1; // 从产生写时隙开始要将总线持续拉低至少60us
	_nop_(); _nop_();
}

/*从1-wire总线上读取1byte数据*/
void readByte18B20(uchar * dat){
	uchar i, temp;
	for(i = 0; i < 8; i++){
		temp = readBit();
		* dat = (temp << 7) | ((* dat) >> 1);
	}
}

/*从1-wire总线上读取1bit数据*/
bit readBit(){
	bit dat;
	DQ = 0; // 将总线拉低大于1us开始进入读总线时段
	_nop_();
	DQ = 1; // 释放总线
	_nop_(); _nop_();
	dat = DQ;
	i = 8; while(i) i--; // 延时71us
	return dat;
}
/*-----------------------------
FileName:display.c
Function: LCD1602显示函数
Author: Zhang Kaizhou
Date: 2019-6-21 16:21:40
------------------------------*/
#include "TempratureMeasure.h"

uchar code table0[] = {"Welcome here"};
uchar code table1[] = {"T:"};
uchar code table2[] = {"0123456789"};
uchar code table3[] = {"'C"};
uchar num = 0;

/*初始化LCD1602的设置*/
void LCDInit(){
	uchar i;
	lcden = 0; // 拉低使能端,准备产生使能高脉冲信号
	writeCommand(0x38); // 显示模式设置(16x2, 5x7点阵,8位数据接口)
	writeCommand(0x0c); // 开显示,不显示光标
	writeCommand(0x06); // 写一个字符后地址指针自动加1
	writeCommand(0x01); // 显示清零,数据指针清零
	
	/*LCD上电界面*/
	writeCommand(0x80); // 将数据指针定位到第一行首
	for(i = 0; i < strlen(table0); i++){
		writeData(table0[i]);
		delay(5);
	}
	
	writeCommand(0x80 + 0x40); // 将数据指针定位到第二行首
	for(i = 0; i < strlen(table1); i++){
		writeData(table1[i]);
		delay(5);
	}
}

/*LCD显示函数*/
void display(float dat){
	uchar i;
	writeCommand(0x80 + 0x40 + strlen(table1));
	writeData(table2[(uchar)((uchar)(dat / 100))]); // 显示温度的百位
	delay(5);
	writeData(table2[(uchar)dat % 100 / 10]); // 显示温度的十位
	delay(5);
	writeData(table2[(uchar)dat % 10]); // 显示温度的个位
	delay(5);
	writeData('.'); // 显示小数点
	delay(5);
	writeData(table2[(uchar)(dat * 10) % 10]); // 显示温度的十分位
	delay(5);
	writeData(table2[(uchar)(dat * 100) % 10]); // 显示温度的百分位
	delay(5);
	for(i = 0; i < strlen(table3); i++){
		writeData(table3[i]);
		delay(5);
	}
}

/*写指令函数*/
void writeCommand(uchar command){
	lcdrs = 0; // 命令选择
	lcdrw = 0;
	P0 = command;
	delay(5);
	
	lcden = 1; // 产生一个正脉冲使能信号
	delay(5);
	lcden = 0;
}

/*写数据函数*/
void writeData(uchar dat){
	lcdrs = 1; // 数据选择
	lcdrw = 0;
	P0 = dat;
	delay(5);
	
	lcden = 1;
	delay(5);
	lcden = 0;
}

/*延时xms函数*/
void delay(uint xms){
	uint i, j;
	for(i = xms; i > 0; i--)
		for(j = 110; j > 0; j--);
}

你可能感兴趣的:(C51)