DS18B20数字温度测量传感器,网上介绍很多,我就不罗嗦了。见图

DS18B20与前产品DS1820的不同:

  DS18B20继承了DS1820的全部优点,并做了如下改进 1.供电范围扩大为3.0--5.5V。2.温度分辨力可编程。3.转换速率有很大提高.4.内部存储器映射关系发生变化。5.具有电源反接保护电路。5.体积减小一半。 对我们使用来说最大的不同就是DS18B20可以程序设定9~12位的分辨率数字值,而DS1820为固定的9位数字值,且温度转换时的延时时间由2s减为750ms。。

电路的接法:
  DS18B20说明书上介绍了几种电路的接法,但我这里就说最常用的一种接法见图:

先介绍一下DS18B20内部的结构:
常规的内部逻辑图我就不说了,只说说跟我们使用直接相关的内容。
DS18B20的内部存储资源分为8个字节的ROM、9个字节的RAM、3个字节的EEPROM如下图:

一、ROM:
在DS18B20内部光刻了一个长度为64bit的ROM,这个编码是器件的身份识别标志。如下图:

  64位光刻ROM的排列是:开始(最低)8位是产品类型标号,对于DS18B20来说就是(28H),接着的48位是该DS18B20自身的序列号,最后8位是前面56位的循环冗余校验码(CRC=X8+X5+X4+1)。光刻ROM的作用是使每一个DS18B20都各不相同,这样就可以实现一根总线上挂接多个DS18B20的目的。

二、RAM:
  高速暂存存储器(RAM)由9个字节组成,包含了8个连续字节,前两个字节是测得的温度信息,第一个字节的内容是温度温度的低八位,第二个字节是温度的高八位。第三个和第四个字节是温度高限TH、温度低限TL暂存区,第五个字节是配置寄存器暂存区,第6、7、8字节是系统保留用,就相当于DS18B20的运算内存,第九个字节是冗余检验字节。其分配如下表所示。

①、第0和第1字节:
  当温度转换命令发布后,经转换所得的温度值以二字节补码形式存放在高速暂存存储器的第0和第1个字节。单片机可通过单线接口读到该数据,读取时低位在前,高位在后。对应的温度计算:当符号位S=0时,直接将二进制位转换为十进制;当S=1时,先将补码变为原码,再计算十进制值。

这是12位转化后得到的12位数据,存储在18B20的两个8比特的RAM中,二进制中的前面5位是符号位,如果测得的温度大于0,这5位为0,只要将测到的数值乘于0.0625即可得到实际温度;如果温度小于0,这5位为1,测到的数值需要取反加1再乘于0.0625即可得到实际温度。看下图

例如+125℃的数字输出为07D0H,十进制是2000,乘以0.0625就等于125℃。同样+25.0625℃的数字输出为0191H,十进制为401,乘以0.0625就得出25.0625℃了。-55℃的数字输出为FC90H,因为符号位为1,先将1111110010010000取反,得1101101111,再加一得1101110000,十进制为880,乘以0.0625就得55,为负值,即-55℃。

② 第2第3字节:
  RAM的第2、3、4字节和EEPROM的三个字节是对应的,内容是相同的,只是RAM因为是暂存器,失电后数据就丢失了。而EEPROM是电擦除只读存储器,失电后数据不会丢失。在工作时得到复位命令后就从EEPROM复制一份数据到RAM的第2、3、4字节内,作为我们进行报警搜索、改写报警值和改写器件设置用,我们从外部只能对RAM进行操作,EEPROM只能从RAM复制而得到要保存的数据。
  第2字节为报警值高限TH,第3字节为报警值低限。DS18B20完成一次温度转换后,就拿温度值和存储在TH和TL中的值进行比较,因为这些寄存器是8位的,所以小数位被忽略不计。TH或TL的最高有效位直接对应16位温度寄存器的符号位。如果测得的温度高于TH或低于TL,器件内部就会置位一个报警标识。每进行一次测温就对这个标识进行一次更新。当报警标识置位时,DS18B20会对报警搜索命令有反应。这样就允许许多DS18B20并联在一起同时测温,如果某个地方温度超过了限定值。报警的器件就会被立即识别出来并读取。而不用读未报警的器件。

③ 第4字节 配置寄存器:
  第4字节的配置寄存器是用来设置DS18B20的工作模式和测量精度的,其内容如下图:

  低五位一直都是"1",TM是测试模式位,用于设置DS18B20在工作模式还是在测试模式。在DS18B20出厂时该位被设置为0,用户不要去改动。R1和R0用来设置分辨率,如下图所示:(DS18B20出厂时被设置为12位)

  我们使用时可以跟据实际需要通过修改RAM第4字节的R0和R1的值来DS18B20的温度测量精度。需要保存这种设置时,还要用一条复制命令将RAM内的数据复制到EEPROM内。

④ 第5、6、7、8字节:
  前面我们已经说过。RAM的第5、6、7字节是器件的保留字节,就相当于器件内部转换运算时所用的内存。第8字节是循环冗余校验字节。它是前面8个字节的CRC值。起着对前面字节的校验作用。

三、EEPROM:
  EEPROM只有三个字节,和RAM的第2、3、4字节的内容相对应,它的作用就是存储RAM第2、3、4字节的内容,以使这些数据在掉电后不丢失。可能通过几条命令将RAM的该3个字节内容复制到EEPROM或从EEPROM将该3个字节内容复制到RAM的第2、3、4字节去。因为我们从外部想改写报警值和器件的设置都是只对RAM进行操作的。要保存这些设置后的数据就还要用相应的命令将RAM的数据复制到EEPROM去。

好了,下面说说对DS18B20的操作都有哪些命令:
  对DS18B20的操作分为对ROM的操作和对RAM的操作。列表见下图:

实际操作的具体实现:
  DS18B20是单总线器件,通讯协议包括几种单线信号类型:复位脉冲、存在脉冲、写0、写1、读0、读1。所有这些信号,除存在脉冲外,其余都是由总线控制器(单片机)发出的。根据DS18B20的通讯协议,主机(单片机)控制DS18B20完成一次操作经过三个步骤:①要对DS18B20进行复位操作,②复位成功后发送一条ROM指令,③最后发送RAM指令,这样才能对DS18B20进行预定的操作。

  ① 对DS18B20复位操作:
   主机(单片机)和DS18B20间的任何通讯都需要以初始化序列开始,初始化序列就是主机发出一个复位脉冲跟着检测一个DS18B20的存在脉冲,表明DS18B20已经准备好发送和接收数据。初始化序列见下图:

  主机首先发出一个480-960微秒的低电平脉冲,然后释放总线变为高电平,并在随后的480微秒时间内对总线进行检测,如果有低电平出现说明总线上有器件已做出应答。若无低电平出现一直都是高电平说明总线上无器件应答。
  做为从器件的DS18B20在一上电后就一直在检测总线上是否有480-960微秒的低电平出现,如果有,在总线转为高电平后等待15-60微秒后将总线电平拉低60-240微秒做出响应存在脉冲,告诉主机本器件已做好准备。若没有检测到就一直在检测等待。

 ② 对DS18B20的写和读操作:
  接下来就是主机发出各种操作命令,但各种操作命令都是向DS18B20写0和写1组成的命令字节,接收数据时也是从DS18B20读取0或1的过程。因此首先要搞清主机是如何进行写0、写1、读0和读1的。
  写周期最少为60微秒,最长不超过120微秒。写周期一开始做为主机先把总线拉低1微秒表示写周期开始。随后若主机想写0,则继续拉低电平最少60微秒直至写周期结束,然后释放总线为高电平。若主机想写1,在一开始拉低总线电平1微秒后就释放总线为高电平,一直到写周期结束。而做为从机的DS18B20则在检测到总线被拉底后等待15微秒然后从15us到45us开始对总线采样,在采样期内总线为高电平则为1,若采样期内总线为低电平则为0。
  

  对于读数据操作时序也分为读0时序和读1时序两个过程。读时隙是从主机把单总线拉低之后,在1微秒之后就得释放单总线为高电平,以让DS18B20把数据传输到单总线上。DS18B20在检测到总线被拉低1微秒后,便开始送出数据,若是要送出0就把总线拉为低电平直到读周期结束。若要送出1则释放总线为高电平。主机在一开始拉低总线1微秒后释放总线,然后在包括前面的拉低总线电平1微秒在内的15微秒时间内完成对总线进行采样检测,采样期内总线为低电平则确认为0。采样期内总线为高电平则确认为1。完成一个读时序过程,至少需要60us才能完成。(为什么不可以像写时序那样将采样时间放在读周期开始后的第15微秒到45微秒之间呢。虽然目前这样也不是不可以,但总觉得不安全。有点悬啊!)
  DS18B20的说明书上也说,由于主机拉低总线电平时间Tint、释放总线时的恢复时间TRC与采样时间Tsample之和必须小于15微秒。如下图13。为了使读出数据更可靠,说明书上建议Tint和TRC保持时间尽可能小,把控制器采样时间放到15微秒周期的最后。如下图14。
  (要是像写周期那样不就从容了,何必搞得紧紧张张的,唉!)

好!弄清了如何复位,如何写1写0和读1读0,我们现在就要看看在总线上如何进行实际的运用。
例如,我们做两个操作,第一个是让DS18B20进行一次温度的转换。第二是读取RAM内的温度。
  ① 让DS18B20进行一次温度的转换。前面已经讲过每一个对DS18B20的操作都要有三个步骤。一是复位操作。二是对ROM的操作。三是对RAM的操作。现在我们要做的是让DS18B20进行一次温度的转换,那具体的操作就是:1、主机先作个复位操作,2、主机再写跳过ROM的操作(CCH)命令,3、然后主机接着写个转换温度的操作命令,后面释放总线至少一秒,让DS18B20完成转换的操作。在这里要注意的是每个命令字节在写的时候都是低字节先写,例如CCH的二进制为11001100,在写到总线上时要从低位开始写,写的顺序是“零、零、壹、壹、零、零、壹、壹”。整个操作的总线状态如下图。

  ② 读取RAM内的温度数据。同样,这个操作也要接照三个步骤。1、主机发出复位操作并接收DS18B20的应答(存在)脉冲。2、主机发出跳过对ROM操作的命令(CCH)。3、主机发出读取RAM的命令(BEH),随后主机依次读取DS18B20发出的从第0一第8,共九个字节的数据。如果只想读取温度数据,那在读完第0和第1个数据后就不再理会后面DS18B20发出的数据即可。同样读取数据也是低位在前的。整个操作的总线状态如下图:

在这里得说明一下,第二步跳过对ROM操作的命令是在总线上只有一个器件时,为节省时间而简化的操作,若总线上不止一个器件,那么跳过ROM操作命令将会使几器件同时响应,这样就会出现数据冲突。

这个扩展,电路很简单,板子就不用做了吧!把电路焊好就行了。

这个是原理图:

实际接线图如下:

接好的实物图如下:

接下来就是写程序了,我们还是一步步地来完成:
① 向总线发出复位信号:
sbit TMDAT=P1^1;   //设P1.1为TMDAT

  void tmreset(void)
{
uint i;
TMDAT=0;     //将总线拉低
i=103;
while(i>0) i--;    //延时700微秒
TMDAT=1;      //释放总线
i=4;
while(i>0) i--;    //延时40微秒
}

② 检测总线上是否有器件应答(是否有存在信号):
void tmpre(void)
{
uint i;
while(TMDAT);     //检测低电平的存在。否则一直循环。
while(~TMDAT); //检测高电平的存在。否则一直循环。
i=4;
while(i>0) i--;     //延时
}
这段程序就是检测一个先低后高的脉冲的存在。说明有器件应答了。

③ 从DS18B20上读一个bit
bit tmrbit(void)
{
uint i;
bit dat;
TMDAT=0;   //先将总线拉低
i++;              //延时一微秒
TMDAT=1;   //释放总线
i++;
i++;            //延时两微秒
dat=TMDAT;    //读取总线
i=8;
while(i>0) i--;     //延时
return(dat);
}

④ 向总线写一个bit
void tmwbit(bit testb)
{
if(testb)                    //如果是1
       { TMDAT=0;     //先拉低总线
         i++; i++;            //延时2微秒
         TMDAT=1;     //释放总线
         i=8;
         while(i>0) i--;   //延时40微秒
       }
     else                     //如果是0
       { TMDAT=0;     //先拉低总线
         i=8;
         while(i>0) i--;   //延时40微秒
         TMDAT=1;      //释放总线
         i++; i++;          //延时2微秒
       }
}

我这么写大家能看懂吧!

与单片机连接图:

好!现在上完整的程序:(要慢慢的读了)
//LCD12864
//**********************************************************
//连线表: CPU=89C51    SysClock=12MHz                     *
//RS=P2.0   R/W=P2.1    E=P2.2    CS1=P2.3    CS2=P2.4     *
//DB0-DB7=P3.0-P3.7       /Reset=InBoard                   *
//**********************************************************

//DS18B20
//**********************************************************
//连线表: CPU=89C51    SysClock=12MHz                     *
//单总线: TMDAT=P1.1
//                
//********************************************************** 
#include <reg52.h>
#include <stdlib.h>
#include <intrins.h>
#include <stdio.h> 
#include <math.h>
#define uchar unsigned char
#define uint unsigned int
/********************LCD引脚定义********************/ 
#define DataPort P3     //LCD128*64 I/O 信号管脚
sbit    RS =P2^0;      //数据指令
sbit    RW =P2^1;      //读写
sbit    E   =P2^2;      //使能
sbit    CSL =P2^3;      //左片选
sbit    CSR =P2^4;      //右片选 
uchar Page;             //页 地址
uchar Col;              //列 地址 
uchar code ASC_5x7[];   //5×7阵点字模
uchar str[4];           //char的值转换成字符串
/********************DS18B20引脚定义********************/ 
sbit TMDAT=P1^1;

/********************DS18B20函数定义*******************/
void dmsec(uint count);//延时(count)毫秒
void tmreset(void);    //产生复位信号
void tmpre(void);      //检测器件应答信号
bit tmrbit(void);      //从总线读一个bit
uchar tmrbyte(void);   //从总线读一个字节
void mwbyte(uchar dat);//向总线写一个字节
void tmstart(void);    //启动一次温度转换
uchar tmrtemp(void);   //读取温度数据

/********************LCD函数定义*******************/
void BusyL(void);          //左屏检测忙
void BusyR(void);          //右屏检测忙
void CheckBusy(void);      //读取忙信号
void Delay(uint MS);       //延时
void Locatexy(void);       //将屏幕横向0-12纵向0-7转换成左、右屏的的X、Y
void WriteCommandL( uchar CommandByte );    //向左屏写入指令
void WriteCommandR( uchar CommandByte );    //向右屏写入指令
uchar ReadData( void );       //读数据
void WriteData( uchar DataByte );    //写数据
void LcmClear( void );       //清屏
void LcmInit( void );        //初始化
uchar * uchartostr(unsigned char unm);            //将值转成字符串
void LcmPutAsc( uchar asc );     //显示一个5×7的ASC字符
void LcmPutstr( uchar row,uchar y,uchar * str );       //在设定位置显示字符串

/*****************DS18B20函数体定义****************/
void dmsec(uint count)
{
uint i;
while(count--)
   { for(i=0;i<125;i++){}
   }
}

void tmreset(void)
{
uint i;
TMDAT=0;
i=103;
while(i>0) i--;
TMDAT=1;
i=4;
while(i>0) i--;
}

void tmpre(void)
{
uint i;
while(TMDAT);
while(~TMDAT);
i=4;
while(i>0) i--;
}

bit tmrbit(void)
{
uint i;
bit dat;
TMDAT=0;
i++;
TMDAT=1;
i++;
i++;
dat=TMDAT;
i=8;
while(i>0) i--;
return(dat);
}

uchar tmrbyte(void)
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{ j=tmrbit();
    dat=(j<<7)|(dat>>1);
}
return(dat);
}

void tmwbyte(uchar dat)
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
   { testb=dat & 0x01;
     dat=dat>>1;
     if(testb)
       { TMDAT=0;
         i++; i++;
         TMDAT=1;
         i=8;
         while(i>0) i--;
       }
     else
       { TMDAT=0;
         i=8;
         while(i>0) i--;
         TMDAT=1;
         i++; i++;
       }
   }
}

void tmstart(void)
{
tmreset();
tmpre();
dmsec(1);
tmwbyte(0xcc);
tmwbyte(0x44);
}

uchar tmrtemp(void)
{
uchar a,b,y1,y2,y3;
tmreset();
tmpre();
dmsec(1);
tmwbyte(0xcc);
tmwbyte(0xbe);
a=tmrbyte();
b=tmrbyte();
y1=a>>4;
y2=b<<4;
y3=y1|y2;
return(y3);
}

/************LCD12864函数体***************/

/***************************/
/*检查Busy                 */
/***************************/
void BusyL(void)
{
        CSL= 1;
        CSR= 0;
        CheckBusy();

void BusyR(void)
{
        CSL= 0;
        CSR= 1;
        CheckBusy();

void CheckBusy(void)
{
        RS = 0;         //指令
        RW = 1;
DataPort= 0xFF;      //输出0xff以便读取正确
        E = 1;
        _nop_();
        while(0);//DataPort & 0x80);       //Status Read Bit7 = BUSY
        E = 0;
        _nop_();

/********************************************************/
/*根据设定的坐标数据,定位LCM上的下一个操作单元位置     */
/********************************************************/
void Locatexy(void)
{
        uchar x,y;
        switch (Col&0xc0)       /* col.and.0xC0        */
        {                       /*条件分支执行          */
                case 0:         {BusyL();break;}/*左区 */
                case 0x40:      {BusyR();break;}/*右区 */
        }
        x = Col&0x3F|0x40;      /* col.and.0x3f.or.Set Y Address*/
        y = Page&0x07|0xB8;     /* row.and.0x07.or.set Page     */
        CheckBusy();                /* waitting for enable */
        RS = 0;                 //指令
        RW = 0;                 //写
        DataPort = y;                 //设置页面地址
        E = 1;
        _nop_();
        E = 0;
        _nop_();
        CheckBusy();                /* waitting for enable */
        RS = 0;
        RW = 0;
        DataPort = x;                 //设置列地址
        E = 1;
        _nop_();
        E = 0;
        _nop_();

/***************************/
/*写指令                   */
/***************************/
void WriteCommandL( uchar CommandByte )
{
        BusyL();
        DataPort = CommandByte;
        RS = 0;         //指令
        RW = 0;
        E = 1;
        _nop_();
        E = 0;
        _nop_();

void WriteCommandR( uchar CommandByte )
{
        BusyR();
        DataPort = CommandByte;
        RS = 0;         //指令
        RW = 0;
        E = 1;
        _nop_();
        E = 0;
        _nop_();

/***************************/
/*读数据                   */
/***************************/
uchar ReadData( void )
{
        uchar DataByte;
        Locatexy();     /*坐标定位,返回时保留分区状态不变      */
        RS = 1;         /*数据输出*/
        RW = 1;         /*读入 */
        DataPort = 0xFF;              //输出0xff以便读取正确
        E = 1;         /*读入到LCM*/
        _nop_();
        DataByte = DataPort; /*数据读出到数据口P1 */
        E = 0;
        _nop_();
        return DataByte;

/***************************/
/*写数据                   */
/***************************/
void WriteData( uchar DataByte )
{
        Locatexy();     /*坐标定位,返回时保留分区状态不变      */
        RS = 1;         /*数据输出*/
        RW = 0;         /*写输出 */
        DataPort = DataByte; /*数据输出到数据口 */
        E = 1;         /*写入到LCM*/
        _nop_();
        E = 0;
        _nop_();

void LcmClear( void )
{
        Page = 0;
        Col = 0;
        for(Page=0;Page<8;Page++)
                for(Col=0;Col<128;Col++)
                        WriteData(0);

void LcmInit( void )
{
    Delay(200);     //等待复位
        WriteCommandL(0x3f);    //开显示
        WriteCommandR(0x3f);
        
        WriteCommandL(0xc0);    //设置起始地址=0
        WriteCommandR(0xc0); 
        WriteCommandL(0x3f);    //开显示
        WriteCommandR(0x3f); 
        LcmClear();
        Col = 0;
        Page= 0;
        Locatexy();
}

uchar * uchartostr(uchar unm)
{
uchar x00,xx,x0,x,n;
x00=unm/100;
xx=unm%100;
x0=xx/10;
x=xx%10;
n=0;
if(x00!=0)
{ str[n]=x00+48; //值加48即为字符
    n++;
}
if(!(x00==0&x0==0))
{ str[n]=x0+48;
    n++;
}
str[n]=x+48;
n++;
str[n]='\0';
   return str;

}
void LcmPutAsc( uchar asc )
{
        uchar j;
        uint x;
        x = 5*(asc-32);
            for(j=0;j<5;j++)
                {
                        WriteData(ASC_5x7[x]);
                        x++;
                        Col++;
                }
            WriteData(0x00); 
            Col++;

}

void LcmPutstr( uchar row,uchar y,uchar * str )
{ unsigned char * x;
   x=str;
Page=row;
Col=y;
while(*x!='\0')
{ LcmPutAsc( *x );
    x++;
}

}

void Delay(uint MS)
{
        uchar us,usn;
        while(MS!=0)
        {
                usn = 2;        //for 12M
                while(usn!=0)
                {
                        us=0xf6;
                        while (us!=0){us--;};
                        usn--;
                }
                MS--;
        }
}

void Main( void )
{
        uchar last;
        LcmInit();
        LcmClear();
    dmsec(1);
    tmstart();
      dmsec(1000);
      last=tmrtemp();
      LcmPutstr( 4,76,uchartostr(last) );
    LcmPutstr( 2,42,"DS18B20" );
    LcmPutstr( 4,2,"Temperature" );
    LcmPutstr( 4,92,"'C" );
        LcmPutstr( 7,42,"" );
        while(1)
        {
      dmsec(1);
    tmstart();
    dmsec(1000);
    last=tmrtemp();
    LcmPutstr( 4,76,uchartostr(last) );
         //Delay(1000);
       
        }
}

unsigned char code ASC_5x7[]={
0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x4F, 0x00, 0x00, //
0x00, 0x07, 0x00, 0x07, 0x00, //
0x14, 0x7F, 0x14, 0x7F, 0x14, //
0x24, 0x2A, 0x7F, 0x2A, 0x12, //
0x23, 0x13, 0x08, 0x64, 0x62, //
0x36, 0x49, 0x55, 0x22, 0x50, //
0x00, 0x05, 0x03, 0x00, 0x00, //
0x00, 0x1C, 0x22, 0x41, 0x00, //
0x00, 0x41, 0x22, 0x1C, 0x00, //
0x14, 0x08, 0x3E, 0x08, 0x14, //
0x08, 0x08, 0x3E, 0x08, 0x08, //
0x00, 0x50, 0x30, 0x00, 0x00, //
0x08, 0x08, 0x08, 0x08, 0x00, //
0x00, 0x60, 0x60, 0x00, 0x00, //
0x20, 0x10, 0x08, 0x04, 0x02, //
0x3E, 0x51, 0x49, 0x45, 0x3E, //
0x00, 0x42, 0x7F, 0x40, 0x00, //
0x42, 0x61, 0x51, 0x49, 0x46, //
0x21, 0x41, 0x45, 0x4B, 0x31, //
0x18, 0x14, 0x12, 0x7F, 0x10, //
0x27, 0x45, 0x45, 0x45, 0x39, //
0x3C, 0x4A, 0x49, 0x49, 0x30, //
0x01, 0x01, 0x79, 0x05, 0x03, //
0x36, 0x49, 0x49, 0x49, 0x36, //
0x06, 0x49, 0x49, 0x29, 0x1E, //
0x00, 0x36, 0x36, 0x00, 0x00, //
0x00, 0x56, 0x36, 0x00, 0x00, //
0x08, 0x14, 0x22, 0x41, 0x00, //
0x14, 0x14, 0x14, 0x14, 0x14, //
0x00, 0x41, 0x22, 0x14, 0x08, //
0x02, 0x01, 0x51, 0x09, 0x06, //
0x32, 0x49, 0x79, 0x41, 0x3E, //
0x7E, 0x11, 0x11, 0x11, 0x7E, //
0x41, 0x7F, 0x49, 0x49, 0x36, //
0x3E, 0x41, 0x41, 0x41, 0x22, //
0x41, 0x7F, 0x41, 0x41, 0x3E, //
0x7F, 0x49, 0x49, 0x49, 0x49, //
0x7F, 0x09, 0x09, 0x09, 0x01, //
0x3E, 0x41, 0x41, 0x49, 0x7A, //
0x7F, 0x08, 0x08, 0x08, 0x7F, //
0x00, 0x41, 0x7F, 0x41, 0x00, //
0x20, 0x40, 0x41, 0x3F, 0x01, //
0x7F, 0x08, 0x14, 0x22, 0x41, //
0x7F, 0x40, 0x40, 0x40, 0x40, //
0x7F, 0x02, 0x0C, 0x02, 0x7F, //
0x7F, 0x06, 0x08, 0x30, 0x7F, //
0x3E, 0x41, 0x41, 0x41, 0x3E, //
0x7F, 0x09, 0x09, 0x09, 0x06, //
0x3E, 0x41, 0x51, 0x21, 0x5E, //
0x7F, 0x09, 0x19, 0x29, 0x46, //
0x26, 0x49, 0x49, 0x49, 0x32, //
0x01, 0x01, 0x7F, 0x01, 0x01, //
0x3F, 0x40, 0x40, 0x40, 0x3F, //
0x1F, 0x20, 0x40, 0x20, 0x1F, //
0x7F, 0x20, 0x18, 0x20, 0x7F, //
0x63, 0x14, 0x08, 0x14, 0x63, //
0x07, 0x08, 0x70, 0x08, 0x07, //
0x61, 0x51, 0x49, 0x45, 0x43, //
0x00, 0x7F, 0x41, 0x41, 0x00, //
0x02, 0x04, 0x08, 0x10, 0x20, //
0x00, 0x41, 0x41, 0x7F, 0x00, //
0x04, 0x02, 0x01, 0x02, 0x04, //
0x40, 0x40, 0x00, 0x40, 0x40, //
0x01, 0x02, 0x04, 0x00, 0x00, //
0x20, 0x54, 0x54, 0x54, 0x78, //
0x7F, 0x48, 0x44, 0x44, 0x38, //
0x38, 0x44, 0x44, 0x44, 0x28, //
0x38, 0x44, 0x44, 0x48, 0x7F, //
0x38, 0x54, 0x54, 0x54, 0x18, //
0x00, 0x08, 0x7E, 0x09, 0x02, //
0x0C, 0x52, 0x52, 0x4C, 0x3E, //
0x7F, 0x08, 0x04, 0x04, 0x78, //
0x00, 0x44, 0x7D, 0x40, 0x00, //
0x20, 0x40, 0x44, 0x3D, 0x00, //
0x00, 0x7F, 0x10, 0x28, 0x44, //
0x00, 0x41, 0x7F, 0x40, 0x00, //
0x7C, 0x04, 0x78, 0x04, 0x78, //
0x7C, 0x08, 0x04, 0x04, 0x78, //
0x38, 0x44, 0x44, 0x44, 0x38, //
0x7E, 0x0C, 0x12, 0x12, 0x0C, //
0x0C, 0x12, 0x12, 0x0C, 0x7E, //
0x7C, 0x08, 0x04, 0x04, 0x08, //
0x58, 0x54, 0x54, 0x54, 0x64, //
0x04, 0x3F, 0x44, 0x40, 0x20, //
0x3C, 0x40, 0x40, 0x3C, 0x40, //
0x1C, 0x20, 0x40, 0x20, 0x1C, //
0x3C, 0x40, 0x30, 0x40, 0x3C, //
0x44, 0x28, 0x10, 0x28, 0x44, //
0x1C, 0xA0, 0xA0, 0x90, 0x7C, //
0x44, 0x64, 0x54, 0x4C, 0x44, //
0x00, 0x08, 0x36, 0x41, 0x00, //
0x00, 0x00, 0x77, 0x00, 0x00, //
0x00, 0x41, 0x36, 0x08, 0x00, //
0x02, 0x01, 0x02, 0x04, 0x02, //
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //
};

实际运行后的效果图如下:

实际操作中发现时序并没有像所说的那么严格,我试着将12MHz的晶振跳到11.0592MHz时,也一样正常运行。

晶振在12MHz位置,如下图

晶振跳至11.0592MHz 如下图:

上张大图看看清楚吧!

自制单片机之七……扩展:DS18B20温度测量的更多相关文章

  1. 自制单片机之七……RS232串口

    在我的板子上其它的部分都已完成了,现在就剩下RS232串口了.串口对于单片机很重要,有了它就可以和PC通信了,可以用PC来控制你的单片机,也可以将你单片机上采集的数据传到PC上. 留的位置好像有点挤. ...

  2. 自制单片机之一------AT89S51最小系统制做

    C51最小系统电路在网上一搜一大把,大同小异.我略做改动后如图: 加一个11.0592MHZ的晶振是为了以后做串口通信时和PC有相同的波特率.可用短路帽切换.说说板子的布局:网上卖的最小系统都是把板子 ...

  3. 调试单片机内部扩展RAM

    51单片机内部只有128字节的RAM(8051),而8052有256字节的RAM,低128字节RAM直接或间接寻址都可以,高128字节RAM与SRF特殊功能寄存器共用地址,SFR只能直接寻址,高128 ...

  4. 自制单片机之八……USB-ISP下载线

    现在的笔记本包括台式机都渐渐地舍弃了并口.串口:很多网友也跟我说,台式没有并口了,下载线没法用了,让我帮他想想办法.看来做个USB-ISP下载线是势在必行了. 在网上搜了下,主要有两种方案,一种是用F ...

  5. 单片机温度控制系统DS18B20

    单片机温度控制系统核心 由895X系列单片机来控制来驱动18b20温度传感器模块,通过编写C语言代码,来实现对模块的控制驱动,不断的接收读取18b20传过来的温度信号.将传过来的高低位字节经过个人代码 ...

  6. 自制单片机之十八……无线通讯模块NRF24L01+

    (一)基础知识篇 今天刚调试好,先看图吧! 这张是AT89C2051控制NRF24L01+做发射调试. 看看NRF24L01细节吧! 这是LCD屏显示: AT89S52做接收测试: 正在接收时的显示: ...

  7. 自制单片机之十七……PC与单片机RS-232串口的通讯和控制

    这次我们来试着一步步的去掌握PC与单片机通过RS-232进行通讯和控制. 先说说我硬件的情况.我用的PC是个二手的IBM240小本本,十寸屏,赛扬400,机子很老了.但也有它的优点:1.串口,并口,P ...

  8. 自制单片机之十五……可串行驱动LCD12864的应用

    在网上搜了一下,ST7920控制器的LCD产品可以提供8位,4位并行和串行接口可选,并行的控制接口的LCD较多,前面的贴子也介绍过,我们在这儿不说了,这儿我们讲的是串口控制LCD12864. 买了块S ...

  9. 自制单片机之十三……时钟IC_DS1302

    在网上看了很久,发现初学者最有兴趣的就是DS1302时钟电路,也很自然,它是个做出来就让你觉得最实用的电路了,但实际上制做上并不简单,首先你要让你的显示部分(不管是数码管还是LCD)调试通过.然后把D ...

随机推荐

  1. Linux下创建、查看、提取和修改静态库(*.a)

    先说明一点,静态库文件是由多个目标文件打包而成的,在windows下静态库文件的后缀是.lib,而在linux下静态库文件的后缀是.a(a是archive的缩写,也就是文档文件). 废话少说,下面直接 ...

  2. RequireJS 2.0 新特性

    就在前天晚上RequireJS发布了一个大版本,直接从version1.0.8升级到了2.0.随后的几小时James Burke又迅速的将版本调整为2.0.1,当然其配套的打包压缩工具r.js也同时升 ...

  3. double精度的坑与BigDecimal

    近期经常接触支付相关的功能,在开发及测试过程中,开始金额都使用的是double类型,而近期新进的需求存在支付时打折的情况,也就是会出现如 1.23元的情况,那么这时候问题来了,如果是直接使用1.23进 ...

  4. bootstrap data

    bootstrap data 用法 <div data-role="page" data-last-value="43" data-hidden=&quo ...

  5. JAXB--学习1

    一.简介 JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生Java类的技术.该过程中,JAXB也提供了将XML实 ...

  6. Django之路由系统

    一.路由系统介绍 在django程序中,可以通过urls.py文件对所有的url进行任务的分配,根据路由规则的定义选择不同的业务处理函数进行处理 二.路由规则定义 1.路由规则代码如下,mysite/ ...

  7. IOS-连接

    http://blog.sina.com.cn/s/articlelist_2659739627_0_2.html

  8. 利用JasperReport+iReport进行Web报表开发

    用JasperReport+iReport进行Web报表开发 序言 在非常多实际的项目里,报表都是当中十分重要的组成部分,比如把查询结果以报表的形式呈现出来.这里所提到的报表可不是简单的二维表,而是拥 ...

  9. iOS 画音频波形曲线 根据音频数据版

    效果图 DrawView.h #import <UIKit/UIKit.h> @interface DrawView : UIView @property shortshort *draw ...

  10. HttpClient get返回String类型 JAVA

    public static String httpGet(String url) { // get请求返回结果 String strResult = ""; try { Defau ...