基于STC8系列单片机对DS18B20和TM1650的电子温度计设计

电子温度计

利用温度传感器DS18B20和TM1650驱动的数码管模块实现温度检测和显示功能,温度显示含一位小数。

头文件和库的引用:

包含了一些头文件,如 <stc8h.h>、"TM1650.h" 和 <INTRINS.h>。定义了一些数据类型,如 INT8U 和 INT16U。

定义全局变量:

DSFlag: DS18B20是否响应的标志位。

temp: 用于存放温度整数和小数部分的数组。

tempdata: 存放读取到的温度数据。

e: 存放温度的整数值。

定义DS18B20相关的IO引脚和延时函数:

使用 sbit 定义DS18B20单总线引脚 DS 和其他IO引脚。定义了不同精度的延时函数,如 Delay1us()、Delay5us()、Delay50us()、Delay240us() 和 Delay800ms()。

DS_setup() 函数:

初始化DS18B20传感器,发送初始化序列,包括拉低总线、释放总线、等待DS18B20响应等步骤。检查DS18B20是否响应,如果未响应,设置 DSFlag 标志位为1。

DS_WriteData() 函数:

用于向DS18B20写入数据。通过位操作将一个字节的数据写入DS18B20。

DS_ReadData() 函数:

用于从DS18B20读取数据。通过位操作读取8位数据。

readTemperature() 函数:

向DS18B20发送温度转换指令,并读取温度数据。处理温度数据,包括负温度的处理。

displayTemp() 函数:

根据读取到的温度数据,将温度数据以BCD码的形式写入TM1650LED数码管,实现温度显示。

main() 函数:

初始化端口和TM1650数码管。进入无限循环,不断读取温度并根据DSFlag来选择是否显示温度。如果DSFlag为1,说明DS18B20未响应,数码管显示全“FF”表示异常。否则,显示温度,并通过延时控制温度的刷新速度。实现了从DS18B20温度传感器读取温度数据,并在TM1650数码管上显示温度值。同时,还处理了DS18B20未响应的情况,以及负温度的显示。

主函数:

//STC8H1K28

#include <stc8h.h>
#include "TM1650.h"
#include <INTRINS.h>

typedef unsigned char INT8U;
typedef unsigned char uchar;
typedef unsigned int INT16U;
typedef unsigned int uint;
int e;

unsigned char temp[2] = {'\0'}; //存放温度整数和小数
uchar tempdata;

sbit DS  = P2^2;   //DS18B20单总线


void DS_setup()
{

	DS = 1;
	Delay1us();
	DS = 0;   //拉低电平 
	Delay480us();
    Delay240us();  //480us-960us之间均可
	DS = 1;   //拉高电平
	Delay50us();   //等待15us-60us
	if(DS == 1) //如果未响应
	{
		DSFlag = 1; //DS18B20未响应 标志位置1
	}
	Delay240us();	
	
}

void DS_WriteData(unsigned char com)
{
	uchar i;
	for(i=0;i<8;i++)
	{
		DS=1;
		Delay1us();
		Delay1us();
		DS= 0; //拉低电平//延时至少1us
		Delay5us();
		Delay1us();
		Delay1us();
		DS=com&0x01;
		Delay50us(); //至少60us直到周期结束
		Delay5us();
		Delay5us();
		DS= 1;
		com=com>>1; //右移一位
	}	
  P12=0;	
}
/*DS18B20读数据函数*/
unsigned char DS_ReadData()//DLA,P13
{
	unsigned char i,j;
	unsigned char dat = 0; //接收数据
	P13=1;
	j=1;
	for(i=0;i<8;i++)
	{
		bit x;
		DS=1;
		Delay1us();
		Delay1us();
		DS=0;  //拉低电平至少1us
		Delay1us();
		Delay1us();
		Delay1us();
		Delay1us();
		Delay1us();
		Delay1us();
		DS=1; //释放总线
		Delay1us();
		Delay1us();
		Delay1us();
		Delay1us();
		x=DS;
		Delay50us();
		if(x==1) //如果是1
		{
			dat=dat+(j<<i);
		}
	}
	tempdata=dat;
	P13=0;
	return dat;
	
}

void readTemperature()
{
	unsigned char tempLow;  //温度低字节
	unsigned char tempHigh; //温度高字节
	unsigned char tempFlag = 0; //温度正负标志位
	DS_setup();	//初始化DS18B20
	DS_WriteData(0xcc); //跳过ROM
	DS_WriteData(0x44); //启动温度转换指令
	//Delay800ms();//延时一段时间
	DS_setup(); //每一次写命令都需要初始化
	DS_WriteData(0xcc); //跳过ROM
	DS_WriteData(0xbe); //读暂存器内容
	tempLow =DS_ReadData();	 //获取温度的第一个字节
	tempHigh =DS_ReadData(); //获取温度的第二个字节
	if(tempHigh>=128)  //温度是负数
	{
		tempLow= ~tempLow+1;
		tempHigh= ~tempHigh;
		tempFlag = 1;
	}
	temp[0]=tempLow;
	temp[1]=tempHigh;
    e=temp[1]*256+temp[0];		
}

void displayTemp()
{
	int a,b,c,d
	a=(int)(e*0.000625)%10;
	b=(int)(e*0.00625)%10;
	c=(int)(e*0.0625)%10;
	d=(int)(e*0.625)%10;
	TM1650_write_data(0x68,tab[a]);
	TM1650_write_data(0x6a,tab[b]);
	TM1650_write_data(0x6c,tab[c]|0x80);//强与0x80添加小数点
	TM1650_write_data(0x6e,tab[d]);
	if(a==0)
		if(b==0)
			if(c==0)
				if(d==0)
				{DSFlag=1;}
}



void main()
{
	P1=0x00;
	P2M0=0xff;
	P2M1=0xff;
	TM1650_Init();
	TM1650_clear();
	while(1)
	{
		readTemperature();		
		displayTemp();
		Delay200ms();	
	}
		
	
	
}













I2C头文件: 

#include "intrins.h"	 	 bit busy;
/***********初始化***********/
#ifndef _IICHEAD_H_
#define _IICHEAD_H_
void I2C_init()
{
P_SW2 = 0x80;//因为I2C的寄存器在扩展的SFR中(XFR外部RAM),所以使用前必须将P_SW2最高位EAXFR置1。
P1M1 = 0;
P1M0 = 0;
I2CCFG = 0xe0; //允许I2C,主机模式,等待时钟数16
I2CMSST = 0x00;//清空状态标志位
EA = 1;
}

/***********开始信号***********/
void Start()
{
busy = 1;
I2CMSCR = 0x81; //开启中断允许位,发送START命令
while (busy);
}

/***********发送一个字节数据***********/
void SendData(char dat)
{
I2CTXD = dat; //写数据到数据缓冲区
busy = 1;
I2CMSCR = 0x82; //发送SEND命令
while (busy);
}

/***********等待接收从机返回接收成功的信号***********/
void RecvACK()
{
busy = 1;
I2CMSCR = 0x83; //发送读ACK命令
while (busy);
}
/***********停止信号***********/
void Stop()
{
busy = 1;
I2CMSCR = 0x86; //发送STOP命令
while (busy);
}
/***********中断,清除标志位***********/
void I2C_Isr() interrupt 24
{
if (I2CMSST & 0x40)
{
I2CMSST &= ~0x40; //清中断标志
busy = 0;
}
}

#endif

 TM1650头文件:

#include <IICHEAD.h>
#include <stdio.h>
#include <stc8h.h>
#ifndef _TM1650_H_
#define _TM1650_H_
//typedef unsigned char uchar;
//                     0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
unsigned char tab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};

//================================================================
// 描述: TM1650写函数
// 参数: add:地址;dat:数据.
// 返回: none.
//================================================================
void TM1650_write_data(unsigned char add,unsigned char dat)
{
Start(); //开始信号
SendData(add); //发送显存地址(控制字)
RecvACK();
SendData(dat); //发送待显示数据(操作数)
RecvACK();
Stop(); //停止命令
}
//================================================================
// 描述: TM1650初始化
// 参数: none.
// 返回: none.
//================================================================
void TM1650_Init()
{
 I2C_init();
 TM1650_write_data(0x48,0x31); // 开显示、8段显示方式、3级亮度
}
//================================================================
// 描述: TM1650清除
// 参数: none.
// 返回: none.
//================================================================
void TM1650_clear()
{
 unsigned char i;
for(i=0; i<4;i++)
{
 TM1650_write_data(0x68+i*2,0);
}
}


#endif

作者:珠科莫工2106

物联沃分享整理
物联沃-IOTWORD物联网 » 基于STC8系列单片机对DS18B20和TM1650的电子温度计设计

发表回复