单线挂载16个DS18B20传感器51程序

2019-03-24 16:55发布

最近做个项目,需要采集16个DS18B20的信息并显示,I/O口有限于是采用单线传输的方式,找了相关资料,但很多地方看不懂,获取序列号和自动匹配这地方一头雾水,求完整程序和获取序列号处的解析。

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
3条回答
doublezz
1楼-- · 2019-03-24 23:56
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P3^7;//ds18b20与单片机连接口
sbit RS=P3^0;
sbit RW=P3^1;
sbit EN=P3^2;
unsigned char code str1[]={"              "};
unsigned char code str2[]={"              "};
uchar fCode[8];
uchar data disdata[5];
uint tvalue;//温度值
uchar tflag;//温度正负标志

/*************************lcd1602程序**************************/
void delay1ms(unsigned int ms)//延时1毫秒(不够精确的)
{
    unsigned int i,j;
    for(i=0;i<ms;i++)
    for(j=0;j<100;j++);
}

void wr_com(unsigned char com)//写指令//
{
   delay1ms(1);
   RS=0;
   RW=0;
   EN=0;
   P2=com;
   delay1ms(1);
   EN=1;
   delay1ms(1);
   EN=0;
}

void wr_dat(unsigned char dat)//写数据//
{
   delay1ms(1);;
   RS=1;
   RW=0;
   EN=0;
   P2=dat;
   delay1ms(1);
   EN=1;
   delay1ms(1);
   EN=0;
}

void lcd_init()//初始化设置//
{
   delay1ms(15);
  wr_com(0x38);delay1ms(5);
  wr_com(0x08);delay1ms(5);
  wr_com(0x01);delay1ms(5);
  wr_com(0x06);delay1ms(5);
  wr_com(0x0c);delay1ms(5);
}
void display(unsigned char *p)//显示//
{
    while(*p!='')
    {
       wr_dat(*p);
       p++;
       delay1ms(1);
    }
}

void init_play()//初始化显示
{
    lcd_init();
    wr_com(0x80);
    display(str1);
    wr_com(0xc0);
    display(str2);
   }

/******************************ds1820 *********************/
void delay_18B20(unsigned int i)//延时1微秒
{
   while(i--);
}

void ds1820rst()/*ds1820复位*/
{
    uchar x=0;
    DQ = 1;          //DQ复位
    delay_18B20(4); //延时
    DQ = 0;          //DQ拉低
    delay_18B20(100); //精确延时大于480us
    DQ = 1;          //拉高
    delay_18B20(40);
}

uchar ds1820rd()/*读数据*/
{
    uchar i=0;
    uchar dat = 0;
    for (i=8;i>0;i--)
    {   
        DQ = 0; //给脉冲信号
        dat>>=1;
        DQ = 1; //给脉冲信号
        if(DQ)
        dat|=0x80;
       delay_18B20(10);
    }
    return(dat);
}
void ds1820wr(uchar wdata)/*写数据*/
{
    uchar i=0;
    for (i=8; i>0; i--)
    {
       DQ = 0;
       DQ = wdata&0x01;
       delay_18B20(10);
       DQ = 1;
       wdata>>=1;
   }
}

read_temp()/*读取温度值并转换*/
{
    uchar a,b;
    ds1820rst();   
    ds1820wr(0xcc);//*跳过读序列号*/
    ds1820wr(0x44);//*启动温度转换*/
    ds1820rst();   
    ds1820wr(0xcc);//*跳过读序列号*/
    ds1820wr(0xbe);//*读取温度*/
    a=ds1820rd();
    b=ds1820rd();
    tvalue=b;
    tvalue<<=8;
    tvalue=tvalue|a;
    if(tvalue<0x0fff)
    tflag=0;
    else
    {
        tvalue=~tvalue+1;
        tflag=1;
    }
    tvalue=tvalue*(0.625);//温度值扩大10倍,精确到1位小数
    return(tvalue);
}


/*******************************************************************/
void ds1820disp()//温度值显示
{   
     uchar flagdat;
     disdata[0]=tvalue/1000+0x30;//百位数
     disdata[1]=tvalue%1000/100+0x30;//十位数
     disdata[2]=tvalue%100/10+0x30;//个位数
     disdata[3]=tvalue%10+0x30;//小数位
     if(tflag==0)
     flagdat=0x20;//正温度不显示符号
     else
       flagdat=0x2d;//负温度显示负号:-

     if(disdata[0]==0x30)
     {
         disdata[0]=0x20;//如果百位为0,不显示
        if(disdata[1]==0x30)
        {
            disdata[1]=0x20;//如果百位为0,十位为0也不显示
        }
    }
    wr_com(0xc0);
    wr_dat(flagdat);//显示符号位
    wr_com(0xc1);
    wr_dat(disdata[0]);//显示百位
    wr_com(0xc2);
    wr_dat(disdata[1]);//显示十位
    wr_com(0xc3);
    wr_dat(disdata[2]);//显示个位
    wr_com(0xc4);
    wr_dat(0x2e);//显示小数点
    wr_com(0xc5);
    wr_dat(disdata[3]);//显示小数位
}
void DispCode()
{
    unsigned char i,temp;

   ds1820rst();
   ds1820wr(0x33);
   for (i=0;i<8;i++)
  {
      fCode[i]=ds1820rd();
}
wr_com(0x80+0x40);
for (i=0;i<8;i++)
{
      temp = fCode[i]>>4; //显示高四位
      if (temp<10)
      wr_dat(temp + 0x30);
  else
    wr_dat(temp + 0x37);
    temp = fCode[i]&0x0f;//显示低四位
  if (temp<10)
    wr_dat(temp+ 0x30);
  else
    wr_dat(temp + 0x37);
}
}
/********************主程序***********************************/
void main()
{
    init_play();//初始化显示
    DispCode();   //系列号显示
    delay1ms(1000);

   while(1)
   {
        //read_temp();//读取温度
        //ds1820disp();//显示
   }
}
////////////////////
这是网上找到的读序列的程序,前面 RS RW EN这三个管脚是干什么的?能细说一下整体流程吗?
ABSWITCH
2楼-- · 2019-03-25 04:01
doublezz 发表于 2018-12-26 15:58
#include
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P3^7;//ds18b20与单片机连接 ...

//下面是测试过的DS18B20的程序

uchar shuju[2];
uchar i;
int t = 0;

sbit DQ = P1^0; //óÃóú′®¿ú·¢Ëí¼°1¤×÷×′ì¬Ö¸ê¾

BYTE TPH; //′æ·ÅζèÖμμĸß×Ö½ú
BYTE TPL; //′æ·ÅζèÖμμÄμí×Ö½ú

void DelayXus(BYTE n);
void DS18B20_Reset();
void DS18B20_WriteByte(BYTE dat);
BYTE DS18B20_ReadByte();

void delay(uint x)//Ñóê±
{
  uint a,b;
    for(a=0;a<200;a++)
  for(b=x;b>0;b--);
}

uchar get_AD_result(uchar channel)
{
      uchar AD_finished = 0; // ′æ′¢ A/D ×a»»±êÖ¾
      ADC_DATA = 0;
      ADC_CONTR = channel; // Ñ¡Ôñ A/D μ±Ç°í¨μà?
                        //ê1êäèëμçÑ1′ïμ½Î趨
      ADC_CONTR |= 0x88; //1000,1000 áî ADC_START = 1, Æô¶ˉA/D ×a»»
      delay(1);
      AD_finished = 0;
      while ( AD_finished == 0 ) // μè′yA/D ×a»»½áêø
             { AD_finished = (ADC_CONTR & 0x10); //0001,0000, ADC_FLAG ==12aêÔA/D×a»»½áêø·ñ
      }
     ADC_CONTR &=0x80; //10000000 áî ADC_START = 0, 1رÕA/D ×a»»
      return (ADC_DATA); // ·μ»Ø A/D ×a»»½á1û
}

int get_temper()//¶áζè′«¸DÆ÷
{
        unsigned int temp;
        unsigned int wen;

        DS18B20_Reset(); //é豸¸′λ
        DS18B20_WriteByte(0xCC); //ìø1yROMÃüáî
        DS18B20_WriteByte(0x44); //¿aê¼×a»»Ãüáî
        while (!DQ); //μè′y×a»»íê3é

        DS18B20_Reset(); //é豸¸′λ
        DS18B20_WriteByte(0xCC); //ìø1yROMÃüáî
        DS18B20_WriteByte(0xBE); //¶áÔY′æ′æ′¢Æ÷Ãüáî
        TPL = DS18B20_ReadByte(); //¶áζèμí×Ö½ú
        TPH = DS18B20_ReadByte(); //¶áζè¸ß×Ö½ú

/*        temp=(TPH<<8)|TPL; //oÏ2¢
        if(TPH>200) temp=~temp+1;
        wen=(temp*6/10)+(temp*2/100)+(temp*5/1000); //×a»»*/
        if(!t){
                temp = TPL;
                t = 1;
        }
        else{
                temp = TPH;
                t = 0;
        }
        return(temp); //·μ»Øζè
}       

/**************************************
Ñóê±X΢Ãë(STC12C5A60S2@5.2M)
2»í¬μÄ1¤×÷»·¾3,Dèòaμ÷Õû′Ëoˉêy
′ËÑóê±oˉêyêÇê1óÃ1TμÄÖ¸áîÖüÆú½øDD¼ÆËã,óë′«í3μÄ12TμÄMCU2»í¬
**************************************/
void DelayXus(BYTE n)
{
        while (n--)
        {
        _nop_();
        }
}

void inint_ser()//3õê¼»ˉ′®¿ú,2¨ìØÂê9600
{
    TMOD=0x20;
    TH1=0xfd;
    TL1=0xfd;
        REN=1;
    TR1=1;          
        ES=1;
    EA=1;
        SM0=0;
        SM1=1;
        PCON=0X80;
}

/**************************************
¸′λDS18B20,2¢¼ì2aé豸êÇ·ñ′æÔú
**************************************/
void DS18B20_Reset()
{
        CY = 1;
        while (CY)
        {
                DQ = 0; //Ëí3öμíμçƽ¸′λDÅoÅ
                DelayXus(180); //Ñóê±Öáéù480us
                DelayXus(180);
                DQ = 1; //êí·Åêy¾YÏß
                DelayXus(40); //μè′y60us
                CY = DQ; //¼ì2a′æÔúÂö3å
                DelayXus(200); //μè′yé豸êí·Åêy¾YÏß
                DelayXus(150);
        }
}

/**************************************
′óDS18B20¶á1×Ö½úêy¾Y
**************************************/
BYTE DS18B20_ReadByte()
{
        BYTE i;
        BYTE dat = 0;

        for (i=0; i<8; i++) //8λ¼ÆêyÆ÷
        {
                dat >>= 1;
                DQ = 0; //¿aê¼ê±¼äƬ
                DelayXus(0); //Ñóê±μè′y
                DQ = 1; //×¼±¸½óêÕ
                DelayXus(0); //½óêÕÑóê±
                if (DQ) dat |= 0x80; //¶áè¡êy¾Y
                DelayXus(40); //μè′yê±¼äƬ½áêø
        }

        return dat;
}

/**************************************
ÏòDS18B20D′1×Ö½úêy¾Y
**************************************/
void DS18B20_WriteByte(BYTE dat)
{
        char i;

        for (i=0; i<8; i++) //8λ¼ÆêyÆ÷
        {
                DQ = 0; //¿aê¼ê±¼äƬ
                DelayXus(0); //Ñóê±μè′y
                dat >>= 1; //Ëí3öêy¾Y
                DQ = CY;
                DelayXus(40); //μè′yê±¼äƬ½áêø
                DQ = 1; //»Ö¸′êy¾YÏß
                DelayXus(0); //»Ö¸′Ñóê±
        }
}

void send_data(uchar x)
{

    ES=0;   
    SBUF=shuju[x];
        delay(20);
    while(!TI);
        TI=0;       
        ES=1;
}

void send_dataA()
{

    ES=0;   
    SBUF=0xAA;
        delay(20);
    while(!TI);
        TI=0;       
        ES=1;
}

void send_dataB()
{

    ES=0;   
    SBUF=0xBB;
        delay(20);
    while(!TI);
        TI=0;       
        ES=1;
}

void main()
{  
        int k;
        inint_ser();

           P1M0=0XFF;
           P1M1=0xFF;
           P1=0XFF;
           while(1)
           {
                send_dataA();
                for(k = 0;k < 2;k++)
                {
                          shuju[k]=get_temper();
                          send_data(k);
                }
                send_dataB();
                delay(100);
        }
}
dcexpert
3楼-- · 2019-03-25 07:33
 精彩回答 2  元偷偷看……

一周热门 更多>