单片机综合实验报告-06 | 数字温度计设计

一、实验目的和任务

1、熟悉单总线及DS18B20传感器的特性和工作原理。

2、掌握数字温度计的硬件结构及程序设计方法。

二、实验原理简介

ZSC-1实验箱配置了DS18B20数字温度传感器以及LED数码管、蜂鸣器、按键等外设,另外还设有RS232、USB两种外部通信接口,为实现数字温度计功能提供了很好的硬件支持。图3.12.1为具体硬件电路。DS18B20的数据线DQ与单片机P3.7口线相连,单片机通过程序模拟单总线时序,实现与DS18B20的通信。LED数码管用于显示DS18B20所测温度(实际只用3位),蜂鸣器BZ1用于超温报警,按键KX0~KX2用于报警温度的设置。通信接口用于连接PC机,实现温度上传等功能。

单片机综合实验报告-06 | 数字温度计设计

为完成一次温度采集,单片机首先按照单总线协议的时序要求,对DS18B20进行初始化,初始化成功后,发送命令字CCH,跳过ROM序列码匹配操作(多个DS18B20并联时才需要通过ROM序列码匹配命令来选择某个DS18B20),接下来发送命令字44H,启动DS18B20进行温度转换。转换一次所需时间为93.75~750ms(取决于DS18B20的位数设置,12位对应的转换时间为750ms)。此后,单片机对DS18B20重新进行初始化,并相继发送CCH和BEH命令,再进行连续两字节读操作,即可得到16位温度值(低字节在先)。

DS18B20温度值采用16位补码,低字节中的D-1~D-4为小数位,12位分辨率时全部有效,11位分辨率时D-4无效,10位分辨率时D-4和D-3无效,9位分辨率时D-4、D-3和D-2无效。高字节中的S为符号位,温度为正时全为0,温度为负时全为1。

DS18B20所有总线读写操作都由一个初始化序列开始。单总线平时为高电平状态,初始化时,单片机先将单总线拉低至少480us然后再释放(总线将通过4.7K上拉电阻迅速拉高),从而发出一个复位脉冲。正常情况下,DS18B20会在检测到总线释放后,先等待15-60us,然后将总线拉低60-240us,再释放。至此,完成一个初始化序列。

三、实验内容和步骤

1、设计程序,利用DS18B20检测温度,并通过数码管显示。(程序略)

2、对程序1进行改进,设置当温度超过31.5℃时蜂鸣器报警。程序如下:

//*****************************头文件声明****************************
#include <reg51.h>
//****************************数据类型定义***************************
typedef unsigned char uint8;
typedef unsigned int  uint16;
//****************************I/O口线声明****************************
#define SEG_CODE_PORT P0       
#define BIT_CODE_PORT P2       
sbit    DS18B20_DATA=P3^7;
sbit    BUZZ=P1^0;
//************************常量数组(段码表)声明*********************
uint8 code SegCodeTable[]=
    {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};      
//****************************全局变量声明***************************
int Temperature;
//****************************函数原型声明***************************
void   DS18B20Init();
void   DS18B20BitWrite(bit Bit);
bit    DS18B20BitRead();
void   DS18B20ByteWrite(uint8 Byte);
uint8  DS18B20ByteRead();
void   GetTemperature();
void   DispTemperature();
void   Delay(uint16 ms);
void   AlarmCheck();
//*******************************主函数******************************
void main()
{
    while(1)
      {
          GetTemperature();        //采集当前温度
          DispTemperature();        //显示当前温度
		   AlarmCheck();
	   } 
}
//*************************DS18B20初始化函数*************************
void DS18B20Init()
{
    uint16  i;  
    while(1)
      {
        DS18B20_DATA=0;
        i=640;           
        while(--i);       //延时800us(STC12C5A60S2,11.0592MHz,代码5级优化)  
        DS18B20_DATA=1;
        i=56;
        while(--i);                     //延时70us
        if(DS18B20_DATA==1) continue;   //无响应则重发复位脉冲
        i=224;
        while(--i);                     //延时280us
        if(DS18B20_DATA==1) break;      //复位成功
      }   
    i=160;
    while(--i);                         //延时200us
}
//***********************DS18B20位写操作函数*************************
void DS18B20BitWrite(bit Bit)
{
    uint16  i;
    DS18B20_DATA=0; 
    i=4;
    while(--i);                   //延时5us
    DS18B20_DATA=Bit;             //发送1位数到DS18B20
    i=48;
    while(--i);                   //延时60us
    DS18B20_DATA=1;     
}
//**********************DS18B20位读操作函数**************************
bit DS18B20BitRead()
{
    bit    temp;
    uint16 i;
    DS18B20_DATA=0;
    i=4;
    while(--i);                   //延时5us
    DS18B20_DATA=1;
    i=4;
    while(--i);                   //延时5us
    temp=DS18B20_DATA;            //读来自DS18B20的1位数
    i=48;
    while(--i);                   //延时60us
    return temp;
}     
//**********************DS18B20字节写操作函数************************
void DS18B20ByteWrite(uint8 Byte)
{
    uint8 i;
    for(i=0;i<8;i++)              //一共发送8位
      {
        if( Byte&0x01==1  )     //先发最低位
          DS18B20BitWrite(1);     //发送1
        else
          DS18B20BitWrite(0);     //发送0
        Byte>>=1;
      }    
}
//**********************DS18B20字节读操作函数************************
uint8 DS18B20ByteRead()
{
    uint8 i,temp=0;
    for(i=0;i<8;i++)              //一共读8位
      {
        temp>>=1;                 //字节变量右移
        if(DS18B20BitRead()==1)   //读取1位数据并存入临时变量temp中
          temp|=0x80;             //temp最高位置1
      }
    return temp;                  //返回读到的8位数
}
//*****************************温度采集函数**************************
void GetTemperature()
{
    uint8  Buff[2],i;
    DS18B20Init();                //DS18B20初始化
    DS18B20ByteWrite(0xCC);       //跳过ROM匹配(因为只有一个DS18B20)
    DS18B20ByteWrite(0x44);       //启动温度转换
    for(i=0;i<250;i++)
    DispTemperature();          //等待750ms,期间不断刷新LED显示
    DS18B20Init();                //DS18B20初始化
    DS18B20ByteWrite(0xCC);       //跳过ROM匹配(因为只有一个DS18B20)
    DS18B20ByteWrite(0xbe);       //准备读转换结果
    Buff[0]=DS18B20ByteRead();    //读温度值低字节
    Buff[1]=DS18B20ByteRead();    //读温度值高字节
    Temperature=(Buff[1]<<8)+Buff[0];  //拼成16位温度值
}
//******************************温度显示函数*************************
void DispTemperature()
{
    uint8 temp;
    temp=(Temperature>>4)/10;                             //显示十位
    if(temp==0)
      SEG_CODE_PORT=0xFF       ;                             //十位为0则隐去
    else
      SEG_CODE_PORT=SegCodeTable[temp];
    BIT_CODE_PORT=0xF5;                                   //选择显示位置
    Delay(1);
    BIT_CODE_PORT=0xFF;
    SEG_CODE_PORT=SegCodeTable[(Temperature>>4)%10]&0x7F; //显示个位(带点)
    BIT_CODE_PORT=0xF6;                                   //选择显示位置
    Delay(1);
    BIT_CODE_PORT=0xFF;
    SEG_CODE_PORT=SegCodeTable[(Temperature&0x0F)*10/16]; //显示十分位
    BIT_CODE_PORT=0xF7;                                   //选择显示位置
    Delay(1);
    BIT_CODE_PORT=0xFF;      
}
//********************************超温报警函数***************************//
void AlarmCheck()
{
  uint8 i;
  if(Temperature > 0x01F8 )       //判断温度是否超过31.5℃
    {
      for(i=0;i<50;i++)
        {
          BUZZ=~ BUZZ ;
          Delay(1);             //控制无源蜂鸣器发声50ms
        }
      BUZZ=1;      
      Delay(100);
     }
}
//******************************软件延时函数*************************
void Delay(uint16 ms)
{
    uint16 i;
    do{
        i=790;
        while(--i);   //延时1ms(STC12C5A60S2,11.0592MHz,代码5级优化)
       } while(--ms);
}

 

上一篇:基于wemos d1开发版读取 DS18B20 传感器的温度及-127度问题


下一篇:2021-05-04