基于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