如何基于单片机51,实现16路或者32路的温度监测?
温度传感器用DS18B20
该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
要基于单片机实现16路或32路的温度监测,可以使用DS18B20数字温度传感器。DS18B20是一种数字式温度传感器,具有易于使用、高精度、数字输出等特点。
以下是一个实现16路温度测量的示例代码:
#include <reg51.h>
#include "ds18b20.h" // DS18B20驱动库头文件
#define DQ P2_0 // DS18B20数据引脚
void main()
{
unsigned char i;
float temp[16]; // 存储16路温度值的数组
while (1)
{
for (i = 0; i < 16; i++)
{
temp[i] = ds18b20_read_temp(DQ); // 读取温度值
}
}
}
在上面的代码中,我们使用了 ds18b20.h
头文件中的 ds18b20_read_temp
函数来读取温度值。该函数接收一个参数,即DS18B20数据引脚的引脚号,返回一个浮点数表示当前DS18B20的温度值。
如果要实现32路温度测量,可以类似地定义一个32个元素的数组,然后在主循环中读取每个DS18B20的温度值,将其存储在相应的数组元素中即可。
需要注意的是,在使用DS18B20时,需要先进行初始化,然后再读取温度值。具体的初始化过程可以参考DS18B20的数据手册。另外,由于DS18B20是一种数字式温度传感器,读取温度值时需要进行一定的计算,将读取到的原始数据转换为温度值。具体的温度值计算公式也可以在DS18B20的数据手册中找到。
如果以上回答对您有所帮助,点击一下采纳该答案~谢谢
1、DS18B20介绍
2、 引脚及应用电路
3、内部结构图
4、存储器结构
5、单总线介绍
6、单总线电路规范
7、单总线时序结构
8、DS18B20操作流程
9、DS18B20数据帧
10、温度存储格式
11、编写程序
main.c
#include <STC89C5xRC.H>
#include "LCD1602.h"
#include "DS18B20.h"
#include "Delay.h"
#include "AT24C02.h"
#include "Key.h"
#include "Timer0.h"
float T,TShow;
char TLow,THigh;
unsigned char KeyNum;
void main()
{
DS18B20_ConvertT(); //上电先转换一次温度,防止第一次读数据错误
Delay(1000); //等待转换完成
THigh=AT24C02_ReadByte(0); //读取温度阈值数据
TLow=AT24C02_ReadByte(1);
if(THigh>125 || TLow<-55 || THigh<=TLow)
{
THigh=20; //如果阈值非法,则设为默认值
TLow=15;
}
LCD_Init();
LCD_ShowString(1,1,"T:");
LCD_ShowString(2,1,"TH:");
LCD_ShowString(2,9,"TL:");
LCD_ShowSignedNum(2,4,THigh,3);
LCD_ShowSignedNum(2,12,TLow,3);
Timer0_Init();
while(1)
{
KeyNum=Key();
/*温度读取及显示*/
DS18B20_ConvertT(); //转换温度
T=DS18B20_ReadT(); //读取温度
if(T<0) //如果温度小于0
{
LCD_ShowChar(1,3,'-'); //显示负号
TShow=-T; //将温度变为正数
}
else //如果温度大于等于0
{
LCD_ShowChar(1,3,'+'); //显示正号
TShow=T;
}
LCD_ShowNum(1,4,TShow,3); //显示温度整数部分
LCD_ShowChar(1,7,'.'); //显示小数点
LCD_ShowNum(1,8,(unsigned long)(TShow*100)%100,2);//显示温度小数部分
/*阈值判断及显示*/
if(KeyNum)
{
if(KeyNum==1) //K1按键,THigh自增
{
THigh++;
if(THigh>125){THigh=125;}
}
if(KeyNum==2) //K2按键,THigh自减
{
THigh--;
if(THigh<=TLow){THigh++;}
}
if(KeyNum==3) //K3按键,TLow自增
{
TLow++;
if(TLow>=THigh){TLow--;}
}
if(KeyNum==4) //K4按键,TLow自减
{
TLow--;
if(TLow<-55){TLow=-55;}
}
LCD_ShowSignedNum(2,4,THigh,3); //显示阈值数据
LCD_ShowSignedNum(2,12,TLow,3);
AT24C02_WriteByte(0,THigh); //写入到At24C02中保存
Delay(5);
AT24C02_WriteByte(1,TLow);
Delay(5);
}
if(T>THigh) //越界判断
{
LCD_ShowString(1,13,"OV:H");
}
else if(T<TLow)
{
LCD_ShowString(1,13,"OV:L");
}
else
{
LCD_ShowString(1,13," ");
}
}
}
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
T0Count++;
if(T0Count>=20)
{
T0Count=0;
Key_Loop(); //每20ms调用一次按键驱动函数
}
}
OneWrite.c
#include <STC89C5xRC.H>
//引脚定义
sbit OneWire_DQ=P3^7;
/**
* @brief 单总线初始化
* @param 无
* @retval 从机响应位,0为响应,1为未响应
*/
unsigned char OneWire_Init(void)
{
unsigned char i;
unsigned char AckBit;
OneWire_DQ=1;
OneWire_DQ=0;
i = 247;while (--i); //Delay 500us
OneWire_DQ=1;
i = 32;while (--i); //Delay 70us
AckBit=OneWire_DQ;
i = 247;while (--i); //Delay 500us
return AckBit;
}
/**
* @brief 单总线发送一位
* @param Bit 要发送的位
* @retval 无
*/
void OneWire_SendBit(unsigned char Bit)
{
unsigned char i;
OneWire_DQ=0;
i = 4;while (--i); //Delay 10us
OneWire_DQ=Bit;
i = 24;while (--i); //Delay 50us
OneWire_DQ=1;
}
/**
* @brief 单总线接收一位
* @param 无
* @retval 读取的位
*/
unsigned char OneWire_ReceiveBit(void)
{
unsigned char i;
unsigned char Bit;
OneWire_DQ=0;
i = 2;while (--i); //Delay 5us
OneWire_DQ=1;
i = 2;while (--i); //Delay 5us
Bit=OneWire_DQ;
i = 24;while (--i); //Delay 50us
return Bit;
}
/**
* @brief 单总线发送一个字节
* @param Byte 要发送的字节
* @retval 无
*/
void OneWire_SendByte(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
OneWire_SendBit(Byte&(0x01<<i));
}
}
/**
* @brief 单总线接收一个字节
* @param 无
* @retval 接收的一个字节
*/
unsigned char OneWire_ReceiveByte(void)
{
unsigned char i;
unsigned char Byte=0x00;
for(i=0;i<8;i++)
{
if(OneWire_ReceiveBit()){Byte|=(0x01<<i);}
}
return Byte;
}
OneWrite.h
#ifndef __ONEWIRE_H__
#define __ONEWIRE_H__
unsigned char OneWire_Init(void);
void OneWire_SendBit(unsigned char Bit);
unsigned char OneWire_ReceiveBit(void);
void OneWire_SendByte(unsigned char Byte);
unsigned char OneWire_ReceiveByte(void);
#endif
可以采用循环遍历的方式,不断读取温度传感器DS18B20的输出值,并将其转化为实际温度值。具体实现方法如下:
FLAG BIT F0 ; 声明传感器复位返回的标志位
DQ BIT P1.7 ; 定义DQ作为数据传输端口名
ABIT EQU 35H
BBIT EQU 36H
CBIT EQU 37H ; 固定个,十,百位的存储位置,名称
INIT_1:SETB DQ ; 总线释放
NOP ; 保持高电平,延时
CLR DQ ; 总线置 0,请求响应
MOV R0,#0FBH
TSR1: DJNZ R0,TSR1 ; 延时
SETB DQ ; 再释放
MOV R0,#25H
TSR2: JNB DQ,TSR3 ; 改变为0,则代表得到对应
DJNZ R0,TSR2 ; 未得到则继续等待,判断
TSR3: SETB FLAG ; 得到相应则标志位置1,代表传感器正常存在
MOV R0,#06BH
TSR4: DJNZ R0,TSR4 ; 延时
SETB DQ ; 释放总线,完成复位
RET
FBLCHANGE:
LCALL INIT_1 ; 复位
MOV A,#0CCH ; 跳过ROM
LCALL WRITE ; 把A写入传感器
MOV A,#1FH ; 改变温度分辨率为9
LCALL WRITE ; 把A写入传感器
RET
GET_TEMP:
SETB DQ ; 释放总线
LACALL INIT_1 ; 复位
JB FLAG,TSS1 ; 若传感器不存在,则直接返回主程序
RET
TSS2: MOV A,#0CCH
LCALL WRITE ; 执行跳过ROM指令
MOV A,#44H
LCALL WRITE ; 执行测温指令
LCALL DISPLAY ; 不仅延时,还让程序完全生效前数码管置零
LCALL INIT_1 ; 复位
MOV A,#0CCH
LCALL WRITE ; 执行跳过ROM置零
MOV A,#0BEH
LCALL WRITE ; 执行读取温度数据指令
LCALL READ ; 跳转至通信子程序
RET
``` CHANGE: MOV A,29H MOV 26H,29H MOV 25H,28H MOV 24H,28H ; 在24H存储原始数据防止丢失 MOV C,25H.7 ; 存