利用18B20测量室内温度

实验目的

1. 利用所学知识,解决实际问题。培养发现问题解决、问题的能力。

2. 学会如何利用误差理论处理测得的数据。

                           实验器材

HC6800单片机开发仪,KENKO牌KK-82MS型科学计算器

实验原理

1.HC6800中的18B20模块以及18B20电路图

        


 

 

 

 

 

 

 

18B20驱动程序

#include<reg52.H>

#include<intrins.h>

 

sbit    D18B20=P3^7;

#define  NOP()  _nop_()   /* 定义空指令*/

#define  _Nop() _nop_()   /*定义空指令*/

 

voidTempDelay (unsigned char idata us);

voidInit18b20 (void);

voidWriteByte (unsigned char idata wr);  //单字节写入

voidread_bytes (unsigned char idata j);

unsignedchar CRC (unsigned char j);

voidGemTemp (void);

voidConfig18b20 (void);

voidReadID (void);

voidTemperatuerResult(void);

 

 

bit  flag;

unsignedint  idata Temperature;

unsignedchar idata temp_buff[9]; //存储读取的字节,read scratchpad为字节,read rom ID为字节

unsignedchar idata id_buff[8];

unsignedchar idata *p;

externunsigned int xdata TIM;

unsignedchar idata crc_data;

 

 

unsignedchar code CrcTable [256]={

0,  94, 188, 226,  97,  63, 221,  131,  194, 156,  126,  32, 163,  253,  31, 65,

157,  195, 33,  127,  252, 162,  64,  30, 95,  1,  227, 189,  62,  96, 130,  220,

35,  125, 159,  193,  66, 28,  254,  160, 225,  191,  93,  3,  128,  222,  60, 98,

190,  224, 2,  92,  223, 129,  99,  61, 124,  34,  192, 158,  29,  67, 161,  255,

70,  24, 250,  164,  39, 121,  155,  197, 132,  218,  56, 102,  229,  187, 89,  7,

219,  133, 103, 57,  186,  228, 6,  88,  25, 71,  165,  251, 120,  38,  196, 154,

101,  59, 217, 135,  4,  90, 184,  230,  167, 249,  27,  69, 198,  152,  122, 36,

248,  166, 68, 26,  153,  199, 37,  123,  58, 100,  134,  216, 91,  5,  231, 185,

140,  210, 48, 110,  237,  179, 81,  15,  78, 16,  242,  172, 47,  113,  147, 205,

17,  79, 173,  243,  112, 46,  204,  146, 211,  141,  111, 49,  178,  236, 14,  80,

175,  241, 19, 77,  206,  144, 114,  44,  109, 51,  209,  143, 12,  82,  176, 238,

50,  108, 142,  208,  83, 13,  239,  177, 240,  174,  76, 18,  145,  207, 45,  115,

202,  148, 118, 40,  171,  245, 23,  73,  8, 86,  180,  234, 105,  55,  213, 139,

87,  9, 235,  181,  54, 104,  138,  212, 149,  203,  41, 119,  244,  170, 72,  22,

233,  183, 85,  11,  136, 214,  52,  106,  43,  117, 151,  201,  74, 20,  246,  168,

116,  42, 200,  150,  21, 75,  169,  247, 182,  232,  10, 84,  215,  137, 107,  53};

//

/************************************************************

*Function:延时处理

*parameter:

*Return:

*Modify:

*************************************************************/

voidTempDelay (unsigned char idata us)

{

    while(us--);

}

 

/************************************************************

*Function:18B20初始化

*parameter:

*Return:

*Modify:

*************************************************************/

voidInit18b20 (void)

{

    D18B20=1;

    _nop_();

    D18B20=0;

    TempDelay(80);   //delay 530 uS//80

    _nop_();

    D18B20=1;

    TempDelay(14);   //delay 100 uS//14

    _nop_();

    _nop_();

    _nop_();

   

    if(D18B20==0)

        flag = 1;   //detect 1820 success!

    else

        flag = 0;    //detect 1820 fail!

    TempDelay(20);       //20

    _nop_();

    _nop_();

    D18B20 = 1;

}

 

/************************************************************

*Function:向B20写入一个字节

*parameter:

*Return:

*Modify:

*************************************************************/

voidWriteByte (unsigned char idata wr)  //单字节写入

{

    unsigned char idata i;

    for (i=0;i<8;i++)

    {

        D18B20 = 0;

        _nop_();

        D18B20=wr&0x01;

        TempDelay(3);   //delay 45 uS //5

        _nop_();

        _nop_();

        D18B20=1;

        wr >>= 1;

    }

}

 

/************************************************************

*Function:读B20的一个字节

*parameter:

*Return:

*Modify:

*************************************************************/

unsignedchar ReadByte (void)     //读取单字节

{

    unsigned char idata i,u=0;

    for(i=0;i<8;i++)

    {

        D18B20 = 0;

        u >>= 1;

        D18B20 = 1;

        if(D18B20==1)

        u |= 0x80;

        TempDelay (2);

        _nop_();

    }

    return(u);

}

 

/************************************************************

*Function:读B20

*parameter:

*Return:

*Modify:

*************************************************************/

voidread_bytes (unsigned char idata j)

{

     unsigned char idata i;

     for(i=0;i<j;i++)

     {

         *p = ReadByte();

         p++;

     }

}

 

/************************************************************

*Function:CRC校验

*parameter:

*Return:

*Modify:

*************************************************************/

unsignedchar CRC (unsigned char j)

{

   unsignedchar idata i,crc_data=0;

    for(i=0;i<j;i++)  //查表校验

        crc_data= CrcTable[crc_data^temp_buff[i]];

    return (crc_data);

}

 

/************************************************************

*Function:读取温度

*parameter:

*Return:

*Modify:

*************************************************************/

voidGemTemp (void)

{

   read_bytes (9);

   if (CRC(9)==0) //校验正确

   {

       Temperature = temp_buff[1]*0x100 + temp_buff[0];

//     Temperature *= 0.625;

        Temperature /= 16;

        TempDelay(1);

    }

}

 

/************************************************************

*Function:内部配置

*parameter:

*Return:

*Modify:

*************************************************************/

voidConfig18b20 (void)  //重新配置报警限定值和分辨率

{

     Init18b20();

     WriteByte(0xcc);  //skip rom

     WriteByte(0x4e);  //write scratchpad

     WriteByte(0x19);  //上限

     WriteByte(0x1a);  //下限

     WriteByte(0x7f);     //set 12 bit (0.125)

     Init18b20();

     WriteByte(0xcc);  //skip rom

     WriteByte(0x48);  //保存设定值

     Init18b20();

     WriteByte(0xcc);  //skip rom

     WriteByte(0xb8);  //回调设定值

}

 

/************************************************************

*Function:读B20ID

*parameter:

*Return:

*Modify:

*************************************************************/

voidReadID (void)//读取器件id

{

    Init18b20();

    WriteByte(0x33);  //read rom

    read_bytes(8);

}

 

/************************************************************

*Function:18B20ID全处理

*parameter:

*Return:

*Modify:

*************************************************************/

voidTemperatuerResult(void)

{

    p =id_buff;

    ReadID();

    Config18b20();

    Init18b20 ();

    WriteByte(0xcc);   //skip rom

    WriteByte(0x44);   //Temperature convert

 

    Init18b20 ();

    WriteByte(0xcc);   //skip rom

    WriteByte(0xbe);   //read Temperature

    p = temp_buff;

    GemTemp();

}

 

 

voidGetTemp()

{      

     if(TIM >=500) //每隔500ms 读取温度

    { TIM=0;

      TemperatuerResult();

    }

 

}

18B20采集温度数据,送至单片机处理,最终结果显示在12864上。

2.数据处理

任何测量都不可避免地存在误差,为了提高测量精度,必须尽可能地消除或减小误差,因此有必要对各种误差的性质、出现规律、产生原因、发现与消除或减小它们的主要方法以及测量结果的评定等方面,作进一步分析。

实验步骤

1.     根据电路原理图连接电路。并对电路进行多次调校,使其工作在较理想的状态。


2.编写适当的程序,并编译。在确定程序无误之后,烧录至单片机。

实验程序如下

#include <reg52.h>

#include <intrins.h>

#include "lcd.h"

 

 

unsigned char  Tempera_Val[3] ,temp;  //温度

unsigned char  RTC_Val[15];          //时钟数组

unsigned int xdata TIM,TIM1;   //用于间隔读取温度和时钟

extern unsigned int  idataTemperature;  //温度

extern unsigned  charxdata D[8];    //读取时钟放到D数组中

 

extern void Read_RTC(void);

extern void GetTemp (void);

extern void Set_RTC(void); //set RTC

 

 

/**********************************************************

         配置定时器参数

 **********************************************************/

void Timer_Ini()

{

    TMOD|= 0x11;

    TH1 = 0xD8;    //10

    TL1 = 0xF0; 

IE = 0x8A; 

    TR1  = 1;

}

 

/**********************************************************

 

  主函数

 

**********************************************************/

void main(void)

    P2 = 0xff;

    P0 = 0xff;

 

     Timer_Ini();    //初始化

    LCD_init();      //初始化

    LCD_clear(5);    //清屏

 

   ChineseChar(14,10,2,colors[2],colors[7],1);   

   ChineseChar(38,10,2,colors[2],colors[7],2);   

   ChineseChar(62,10,2,colors[2],colors[7],3);   

   ChineseChar(86,10,2,colors[2],colors[7],4);   

 

   ChineseChar(24,50,1,colors[2],colors[7],10); 

ChineseChar(40,50,1,colors[2],colors[7],11); 

    ChineseChar(80,50,1,colors[2],colors[7],12); 

 

   ChineseChar(30,80,1,colors[2],colors[7],13); 

ChineseChar(46,80,1,colors[2],colors[7],14); 

ChineseChar(62,80,1,colors[2],colors[7],14); 

    ChineseChar(76,80,1,colors[2],colors[7],15);

  

Set_RTC();

 

   while(1) 

  {   

      if( TIM1 >=10)  //每隔10ms 读取ds1302

  {

    TIM1 =  0;

     Read_RTC();  //读取DS1302

  }

        GetTemp();

     //*****温度***********************

        Tempera_Val[0] =Temperature%100/10 + 0x30;   //Temperature;

        Tempera_Val[1] =Temperature%10 + 0x30;

 

     //******月***********************

     temp =   ((D[4]&0x70)>>4)*10 +(D[4]&0x0f);  

     RTC_Val[0] = temp/10 +0x30;     //将位转成ASCII码

     RTC_Val[1] = temp%10 +0x30;     //将个位转成ASCII码

    

     RTC_Val[2] = '-'  ;      //短横线

      //*****日***********************

     temp =   ((D[3]&0x70)>>4)*10 +(D[3]&0x0f);  

     RTC_Val[3] =  temp/10 + 0x30;

     RTC_Val[4] =  temp%10 + 0x30;

     RTC_Val[5] = ' '  ;

     //******时***********************

     temp =   ((D[2]&0x70)>>4)*10 +(D[2]&0x0f);   

     RTC_Val[6] = temp/10 +0x30;

     RTC_Val[7] = temp%10 +0x30;

 

     RTC_Val[8] = ':'    ;     //冒号

      //******分***********************

     temp =   ((D[1]&0x70)>>4)*10 +(D[1]&0x0f);  

     RTC_Val[9] =  temp/10 + 0x30;

     RTC_Val[10] = temp%10+ 0x30;

 

     RTC_Val[11] = ':';

      //******秒***********************

    temp =  ((D[0]&0x70)>>4)*10 + (D[0]&0x0f);    

     RTC_Val[12] = temp/10+ 0x30;

     RTC_Val[13] = temp%10+ 0x30;

 

       

    LCD_ShowString(60,50,colors[7],colors[2],Tempera_Val); //将字符送到彩屏中显示

     LCD_ShowString(10,100,colors[7],colors[2],RTC_Val);     //将字符送到彩屏中显示

 

  } 

}

 

 

/*************************************

 [ t1 (10ms)中断] 中断

*************************************/

void T1zd(void) interrupt 3

{

   TH1 = 0xD8;    //10

   TL1 = 0xF0;

   TIM++;

   TIM1++;

}

 

3. 开始记录数据。(温度单位:℃)

在连续的八天记录数据期间,单片机持续供电。每隔十分钟记录数据。每天都在11:50开始记录数据。

 

 

 

 

 

 

 

 

时间

11:50   

 

 

 

 

 

 

 

 

 

31

 

32

 

32

 

32

 

32

 

32

 

32

 

33

 

33

 

33

29

 

29

 

29

 

30

 

30

 

30

 

30

 

31

 

31

 

32

30

 

30

 

30

 

31

 

31

 

31

 

32

 

32

 

32

 

33

30

 

30

 

30

 

31

 

31

 

31

 

32

 

32

 

33

 

33

31

 

31

 

31

 

32

 

32

 

32

 

33

 

33

 

34

 

34

29

 

29

 

30

 

30

 

31

 

31

 

32

 

32

 

33

 

33

30

 

30

 

31

 

31

 

32

 

32

 

32

 

33

 

33

 

33

32

 

32

 

32

 

33

 

33

 

33

 

34

 

34

 

34

 

35

                                                       

 

计算每天获取数值的算术平均值,记录如下:

测量天数

     

1

32.2

0.575

0.3306

2

30.1

-1.525

2.3256

3

31.2

-0.425

0.1806

4

31.3

-0.325

0.1056

5

32.3

0.675

0.4556

6

31

-0.625

0.4556

7

31.7

0.075

0.0056

8

33.2

1.575

2.4806

注: =31.625℃, = /8,


   实验数据分析

在测量过程中,遇到明显的降温天气,使得测的数据的粗大误差偏大。

测量结果的数据处理

1、   算术平均值的计算校核

根据残余误差代数和校核规则,现用规则2进行校核,因

A=0.001,n=8

=0

计算正确。

2、由Bessal = = =0.33647

按Peters公式 1.253 / =0.1214

=1+u, =1- =0.5965,

=0.5965 =0.75593.

故测量列中不存在系统误差.

3、   n=8, 由狄克松准则得

= = =0.4091

不含粗大误差

= =0.4091

不含粗大误差.

4、   求算数平均值的标准差

0.3364

=0.2563

5、   求算术平均值的极限误差

已知

则 = 2.36x0.2563=0.6049

6、   写出最后测量结果

T=(31.625 )

 

心得体会

此次实验综合了单片机的应用,误差理论与数据处理的知识。

在测量温度时,会受到很多因素的影响,比如室内开启电风扇的数目及风扇的转速,单片机持续工作时内部电路产生的误差。在数据采集期间,武汉当地气温比较恒定,数据采集条件比较理想。

 

参考资料:

http://www.wpxap.com/智机网

http://www.mcuol.com/嵌入式在线

http://www.eepw.com.cn/电子产品世界网

http://www.eaw.com.cn/电子设计应用网 

《数字电子技术》                 康华光主编      高等教育出版社

《单片机原理及应用》        李建忠主编    西安电子科技大学出版社

《单片机应用系统设计实例与分析》   沈红卫主编   北京航空航天大学出版社

《误差理论与数据处理》(第五版)  费业泰主编  合肥工业大学出版社


阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭