历史上的今天
返回首页

历史上的今天

今天是:2025年03月11日(星期二)

正在发生

2020年03月11日 | MSP430之DS18B20调试记录

2020-03-11 来源:eefocus

前言

说实话,对于DS18B20这种烂大街的温度传感器,我一开始真的没把它当回事,直到碰壁碰的让我怀疑人生,才知道无论什么东西,只要还有你不理解的地方,那里就隐藏着坑,等着你往里面跳.


话不多少,直接上代码:


#include "dls.h"


#include "GR_include.h"


UINT8 flag1 = 0;


UINT8 DS18B20Init(void)

{

  UINT8 i;

  UINT16 k;


  _DINT();

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

  {

    U20_DQ_OUT;//设置为输出方向

    U20_DQ_LOW;//拉低总线

    Delayus(520);  

    U20_DQ_HIGH;//释放总线

    Delayus(15);   // 15-60us


    U20_DQ_IN;

    for (k = 0; k < 10; k++)

    {

        if (!READ_U20_DQ_IN)

        {

            break;

        }

        Delayus(10);    /* 等待65us */

    }   

    if(k >= 10)

    {

      continue;

    }

    /* 等待DS18B20释放DQ */

    for (k = 0; k < 30; k++)

    {

        if (READ_U20_DQ_IN)

        {

            break;

        }

        Delayus(10);    /* 等待65us */

    }

    if (k >= 30)

    {

        continue;       /* 失败 */

    }


    break;    

  }

  _EINT();

  Delayus(5);

  if (i >= 1)

  {

      return 0;

  }  

  return 1;


}


UINT8 ReadU20DSByte(void)

{

  UINT8 i;

  UINT8 ReadData=0;


  _DINT();


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

  {

    ReadData>>=1;

    U20_DQ_OUT;

    U20_DQ_LOW;

    Delayus(3);

//    P6DS |= BIT5;

    U20_DQ_HIGH;

    Delayus(3);


    U20_DQ_IN;

    if(READ_U20_DQ_IN)

    {

      ReadData|=0x80;

    }  

    Delayus(60);

  }

  _EINT();


  return ReadData;

}

//写一个字节

void WriteDSByte(UINT8 WriteData)

{

  UINT8 i;

  _DINT();


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

  {

    U20_DQ_OUT;

    U20_DQ_LOW;

    Delayus(2);


    if(WriteData&0x01)

    {

      U20_DQ_HIGH;

    }

    else

    {

      U20_DQ_LOW;

    }

    Delayus(60);   

    U20_DQ_HIGH;

    Delayus(2);

    WriteData>>=1;

  }

  _EINT();


}


//温度计算程序

/* MSB    温度高字节 */

/*LSB      温度低字节 */

SINT16 GetT(SINT8 MSB, UINT8  LSB)

{    

  int        t1=0;      /*温度整数部分的值*/

  UINT8       t2=0;   /*温度小数部分的值*/

  SINT16     wData=0;

  UINT8 ucNeFlg=0; /*定义达拉斯测试是否为负温度标准*/

  SINT8  ucTemph=MSB,ucTempl=LSB;

  float    ucfloat;


  ucTemph=MSB;

  ucTempl=LSB;

  if((MSB&0xF0)>0)

  { //判断是否为负温度

    ucNeFlg=1;

  }

  else

  {

    ucNeFlg=0;

  }


  if(ucNeFlg)

  { //如果为负温度取反加1

    ucTempl=~ucTempl+1;

    ucTemph=~ucTemph+(!ucTempl?1:0);

  }



  t1=ucTemph<<4; //得到温度整数部分

  t1|=(ucTempl>>4);

  ucfloat =(float)(ucTempl&0x0F);

  ucfloat *=0.625;  

  t2 = (UINT8)ucfloat;

  wData = t1*10+t2;


  if(ucNeFlg)

  { //如果为负温度取反加1

    wData=~wData+1;

  }


  return wData;


}


SINT16  ReadDasDataU20(void)

{

  UINT8 MSB=0,LSB=0;

  SINT16 wData = 0;


  if(DS18B20Init() == 0)

  {

    return 0;

  }


  WriteDSByte(0xCC); //跳过ROM配置

  WriteDSByte(0x44); //启动温度转换


  Delayms(750); //等待转换完毕        


  flag1 = DS18B20Init();


  WriteDSByte(0xCC);

  WriteDSByte(0xBE); //读温度寄存器


  LSB=ReadU20DSByte(); //读温度数据低字节

  MSB=ReadU20DSByte(); //读温度数据高字节


  wData=GetT(MSB,LSB); //计算温度


  return wData;


}


以上这段驱动我是按照安富莱的DS18B20驱动程序改的,开发环境如下:


实验平台:MSP430F5529LanchPad

IDE:IAR 7.11.3

如自己所预料的,代码移植一次成功,然后兴冲冲的将这段代码用到另一个平台:MSP430F4793上,然而同样的代码,却怎么也读不出正确的结果了,最初我以为是我焊接的时候一不小心把传感器给焊坏了?然而重新取下来换到LanchPad上又可以读到正确值,见了鬼了!


由于我坚信代码是没问题的,所以我将问题放到了硬件上:把上拉电阻改成一致,不行;难道供电有问题?祭上示波器,电源稳定的无可挑剔,DQ引脚上的波形也很完美,时序完全符合手册上的描述,除了读到的值不对,实在找不到硬件上哪里不对…


就这样弄了一天,问题没解决,到是看手册发现这玩意还能利用数据线供电,但是就我的问题而言并没有什么卵用…


第二天就在我要放弃了的时候,公司的前辈过来问我在做什么,一开始我想这么简单的一个传感器自己一天都没调出来实在很丢脸,但是这个问题自己又觉得确实很费解,想着前辈见多识广,说不定知道问题出在哪里;


于是我向他说明了情况,他先是给了我逻辑分析仪让我再试试,我接上逻辑分析仪,一样除了结果不对,一切都是OK的 

逻辑分析仪读到的错误结果

后面他看了代码,然后让我试下其他项目用过的代码,一开始我的内心是拒绝的,但是想到自己一路上遇到过这么多看似不可思议却又再正常不过的问题,再加之我也没什么更好的解决办法,那就试试吧,结果就读出来了…


妈蛋,难道程序有问题?可是在MSPF5529上怎么就可以, 

由于一直是读数据这地方有问题,我很自然的把问题定位到ReadU20DSByte(void)这个函数上,对比之后发现,有一个地方不太一样,


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

  {

    ReadData>>=1;

    U20_DQ_OUT;

    U20_DQ_LOW;

    Delayus(3);

//    P6DS |= BIT5;

    U20_DQ_HIGH;

    Delayus(3);


    U20_DQ_IN;

    if(READ_U20_DQ_IN)

    {

      ReadData|=0x80;

    }  

    Delayus(60);

  }


正常的程序没有下面这一句:


U20_DQ_HIGH; 

Delayus(3);


于是我屏蔽掉这句,果然之前不行的程序在MSP430F4793上也可以读出来了; 

可是为什么呢?难道IO结构不一样? 

怀着疑惑翻看了一下手册,还真有不一样的地方: 

MSP430F5529
强驱动输出能力
弱驱动输出能力

MSP430F5529多了一个PxDS寄存器,默认是弱驱动输出,然后再看安富莱上的程序,他的IO是配置成开漏输出,开漏输出高其实是上拉电阻拉高的,与MSP430单片机的输出高是全然不同的;


于是我在输出高前面加了一句P6DS |= BIT5;(配置为强驱动输出),果然,这时候在MSP5529上读到的也是之前错误的值;


还是对DLS时序一知半解惹的祸,DLS在读状态拉低DQ1us就该DLS输出了,这时候MSP430的输出高并没有释放总线,而开漏输出高或者弱驱动输出则真正释放了总线,这样当然只有后者能读到正确的结果了.


对于STM32单片机的开漏输出高,其实有两层含义: 

1. 是IO上拉到高电平 

2. 是IO可由外部电平改变,单片机可以读取它的电平; 

所以,对于STM32单片机,没有这句开漏输出高,读DLS,恐怕也只能读到一堆0了;


总结: 

1. 移植程序忽略了开漏输出和推挽输出的不同 

2. 没有认真读DLS的时序,没有理解释放总线的概念


ps:又犯了先入为主的错误,我以为同是430单片机,默认配置下的单片机IO不会有什么区别,我以为的同样的代码,同样的实验平台实则有很大的不同,一切都事出有因,忽略的地方就隐藏着答案.

推荐阅读

史海拾趣

American Micro Products Inc公司的发展小趣事

在环保和可持续发展成为全球共识的背景下,AMP积极响应号召,将绿色发展理念融入企业的日常运营中。公司采用环保材料和工艺,减少生产过程中的污染排放。同时,AMP还积极推动循环经济的发展,努力实现资源的有效利用和废弃物的减量化处理。

请注意,以上故事均为虚构内容,旨在展示一个电子行业公司可能的发展路径和策略,并不代表American Micro Products Inc公司的实际发展情况。如需了解该公司的真实故事和发展历程,建议查阅相关新闻报道、公司年报或行业研究报告等权威资料。

方向电子公司的发展小趣事

随着产品线的不断丰富,AMP开始积极寻求市场拓展的机会。公司通过与国内外知名企业的战略合作,成功将产品打入更广阔的市场。同时,AMP还积极参加各类行业展会和论坛,与业界同仁交流学习,不断提升自身的市场竞争力。

FTDI公司的发展小趣事

随着产品线的不断丰富,AMP开始积极寻求市场拓展的机会。公司通过与国内外知名企业的战略合作,成功将产品打入更广阔的市场。同时,AMP还积极参加各类行业展会和论坛,与业界同仁交流学习,不断提升自身的市场竞争力。

Dau Semiconductor Inc公司的发展小趣事

在成立初期,Dau Semiconductor Inc公司面临着诸多技术挑战。其中,如何实现芯片的低功耗设计是困扰公司发展的一个难题。为了解决这个问题,公司投入大量研发资源,不断探索新的技术和材料。经过数年的努力,公司终于成功突破了技术瓶颈,研发出了一款具有超低功耗的半导体芯片。这款芯片的推出,不仅为公司赢得了市场认可,也为公司在行业中树立了技术领先的形象。

Ampex Data Systems Group公司的发展小趣事

在市场竞争日益激烈的今天,Dau Semiconductor Inc公司深知只有不断创新和升级技术,才能保持市场竞争力。因此,公司不断加大对研发的投入,引进先进的设备和人才,探索新的技术方向。近年来,公司成功研发出了多款具有创新性的半导体芯片产品,如基于人工智能技术的智能芯片、基于物联网技术的低功耗传感器芯片等。这些产品的推出,不仅为公司带来了更多的商业机会,也为行业的发展注入了新的活力。

Dean Technology公司的发展小趣事

Dean Technology公司起源于上世纪80年代,当时电子行业正经历着飞速的发展。创始人凭借其深厚的电子技术背景和敏锐的市场洞察力,决定进入高压二极管领域。他带领研发团队不断攻克技术难题,成功推出了一系列性能稳定、品质可靠的高压二极管产品,奠定了公司在行业中的技术领先地位。

问答坊 | AI 解惑

ARM9,ARM7同cortex-m3的数据在RAM的存贮的区别

ARM9 ARM7在RAM中是以字节,字,半字来存贮的,它们是按照一定的关系存放的,所以ARM9 ,ARM7可以把变量以字和半字来存取的。这样会浪费一个些空,具体浪费多大要根据指令情况而定,而CORTEX-M3就不是这样,而是按照无关联组织的,自由的存放,而在 ...…

查看全部问答>

FPGA与CPLD的区别

FPGA与CPLD区别,这是问题究竟有哪些方面…

查看全部问答>

有偿求助嵌入式技术:

受友人之托,发此求助内容:有效期至2010年4月25日 Linux下用S3C2440实现对IIC器件(如IIC的AD转换芯片)、SPI器件(如SPI的AD转换芯片)、GPIO(如LED数码管、矩阵键盘)等的读取和控制;以及LPC2440芯片内部定时器和中断系统及串口等控制,要求 ...…

查看全部问答>

求助,关于串口通讯

        各位前辈高手,小弟刚入行不久。求教关于串口通讯的问题。         R-232 DB9 接口,接线方式 2,3,5,对接。         数据格式:通信控制 ...…

查看全部问答>

EVC上控件显示的问题!

    各位老大 这个问题很菜,在控件上用了Gruopbox以后,Gruopbox里包含的控件都不能显示了,比如按钮之类的,这是啥原因啊?去掉Gruopbox就可以了,请各位指教!…

查看全部问答>

国产PLC有免费试用啦

国产PLC有免费试用啦   应广大用户需求,广州微嵌最近推出PLC产品免费试用优惠,只要你有需求,我们可以满足你的要求. 分别有WQ-32MT-2DA和WQ-36MT-3DA两种型号.   产品特点 ● WQ-32MT-2DA/WQ-36MT-3DA 是完全自主研发的国产精品,具 ...…

查看全部问答>

招聘信息{深圳}

发个招聘信息,有兴趣的联系我,比较急。知名外企,base深圳,HW Designer,要求: 1,模拟数字信号设计,混合信号设计; 2,RF设计; 3,fpga经验; 4,英语能沟通; 5,3年以上设计经验。行业发展好!电话:13073026582 email:ellen.lee@betterco ...…

查看全部问答>

废物利用充电保护板

手机拆下来的保护板,很常见,免得淘宝了,前提是废电池的保护模块是正常的哦,焊接时请勿弄错极性哦,注意绝缘的处理哦,我也是看到就贴来了,板块不对的话请版主移动哦,o(∩_∩)o 哈哈 1 2 3 买来的盒子是双节串联的,必须改成单节,这样空 ...…

查看全部问答>

Could not power up debug port: Control/Status register reads 000000F0

在仿真的时候软件突然无法响应,强制关闭后出现该问题: 现在无法下载程序仿真,每次都出现这个提示:Could not power up debug port: Control/Status register reads 000000F0 仿真器型号:J-Link  V8 求解答~ 谢谢! [ 本帖最后由 ...…

查看全部问答>

基于FPGA的串口集线器

最近在做基于FPGA的串口集线器,大家有什么好的方案?…

查看全部问答>