历史上的今天
返回首页

历史上的今天

今天是:2024年11月25日(星期一)

正在发生

2019年11月25日 | 利用AVR单片机设计的DS18B20测温程序

2019-11-25 来源:51hei

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

  DS18B20测温程序

  文件名:main.c

  编译:WinAVR-20070122


  硬件环境:CA-M8X   打开的开关如下

            S6(1,2,5,6,7)   - 外部4MHz晶振和595接口

            J8(EN-SEG)      - 数码管显示允许

            S7(4)          - 连接PC1 与DS18B20数据口

            (在CA-M8X 上DS18B20为非总线供电)

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

#include

#include

#include


#include "seg.h"  //声明数码管显示接口函数


#define CLR_1WIRE_BUS DDRC|=_BV(PC1) //设置为输出,此时由于PORTC1是低所以输出低

#define SET_1WIRE_BUS DDRC&=~_BV(PC1)//设置为输入,此时由于PORTC1是低所以程高阻,又因为外部有上拉电阻所以相当于设置总线为高

#define GET_1WIRE_BUS PINC&_BV(PC1) 


#define DS18B20_READ_ROM 0x33

#define DS18B20_MATCH_ROM 0X55

#define DS18B20_SKIP_ROM 0XCC

#define DS18B20_SEARCH_ROM 0XF0

#define DS18B20_ALARM_SEARCH_ROM 0XEC

#define DS18B20_WRITE_RAM 0X40

#define DS18B20_READ_RAM 0XBE

#define DS18B20_COPY_RAM 0X48 

#define DS18B20_CONVERT_TEM 0X44

#define DS18B20_EECALL_EEPROM 0XB8

#define DS18B20_READ_POWER_SUPPLY 0XB4


//总线端口初始化

void BusInit(void)

{

  PORTC&=~_BV(PC1);//此口总保持低

  DDRC&=~_BV(PC1); //初始化为输入,用外部上拉电阻保持总线的高电平

}


//由于系统时钟为4MHz,一个_delay_loop_2正好延时一us

#define DelayUs(x) _delay_loop_2(x)


void DelayMs(uint16_t t)

{

  uint16_t i;

  for(i=0;i    _delay_loop_2(250 * 4);

}


//单总线复位

uint8_t ds18b20_reset(void) 

  uint8_t ret=0;

  CLR_1WIRE_BUS; 

  DelayUs(500);  //拉低总线至少480us

  SET_1WIRE_BUS; 

  DelayUs(100);//释放总线后等待15-60us

  if((GET_1WIRE_BUS)==0)//检测到DS18B20把总线拉低

    ret=1;        //复位成功

  DelayUs(1000);//等待器件释放总线

  return ret;


//单总线读一字节

uint8_t ds18b20_read(void) 

  uint8_t data=0; 

  uint8_t i=0; 

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

  { 

    data>>=1; 

    CLR_1WIRE_BUS; 

    DelayUs(2);//此时>1us 

    SET_1WIRE_BUS; 

    DelayUs(4);//此时<15us 

    if(GET_1WIRE_BUS) 

      data|=0x80; 

    DelayUs(60);//此时>60us 

  } 

  return(data); 

}

//单总线写一字节

void ds18b20_write(uint8_t data) 

  uint8_t i=0; 

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

  { 

    if(data&0x01)

    { 

      CLR_1WIRE_BUS; 

      DelayUs(8);//8us 

      SET_1WIRE_BUS; 

      DelayUs(55);//55us 

    } 

    else 

    { 

      CLR_1WIRE_BUS; 

      DelayUs(55);//55us 

      SET_1WIRE_BUS; 

      DelayUs(20);//8us 

    } 

    data>>=1; 

  } 


//执行转换

uint8_t Ds18b20Convert(uint8_t *t) 

  //发送转换命令

  if(ds18b20_reset()==0)

    return 0;

  ds18b20_write(DS18B20_SKIP_ROM); //忽略地址匹配,总线上只有一个器件时,或对总线所有器件操作

  ds18b20_write(DS18B20_CONVERT_TEM);//开始转换命令

  

  //等待转换完成,ds18b20默认转换精度为12位,此时最大转换时间为750ms

  DelayMs(1000);

  

  //读温度字节

  if(ds18b20_reset()==0)

    return 0; 

  ds18b20_write(DS18B20_SKIP_ROM); //忽略地址匹配

  ds18b20_write(DS18B20_READ_RAM); //读RAM命令

  t[0]=ds18b20_read(); 

  t[1]=ds18b20_read();

  

  return 1;

}


//根据DS18B20中读的温度字节,计算实际温度值

int8_t GetTemperature(uint8_t *t)

{

  int8_t ret;

  uint32_t  val;

  uint16_t tmp=(t[1]*256)+t[0];

  uint8_t sflag=0;


  if((t[1]&0xf8)==0xf8) //若负温度,从补码转换(取反加一)

  {

    sflag=1;

    tmp=~tmp;

    tmp++;

  }

  tmp&=0x07ff;    //确保前5位为0

  

  //乘0.0625操作,为此本函数只适用于DS18B20 12位转换(默认)时

  val=((uint32_t)tmp)*625;

  val/=10000;

  

  ret=(int8_t)val;

  

  if(sflag)

    ret|=0x80;//变负数

    

  return ret;

}


//测试主函数

int main(void)

{

  uint8_t tmp[2];//保存温度字节

  int8_t tval;    //保存温度值

  

  SegInit();//数码管初始化

  SegNumberOut(0,0);//显示 0

  BusInit();  //单总线I/O口初始化


  while(1)

  {

    if(Ds18b20Convert(tmp))//如果转换成功

    {

      tval=GetTemperature(tmp);//计算实际温度值

      if(tval>=0)

        SegNumberOut(tval,0);//十进制显示温度值

      else

        SegNumberOut(0,0);//数码管无法显示负数,只能显示0

    }

  }

  return 0;

}



seg.c文件:



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

  74HC95驱动的数码管显示模块

  文件名:seg.c

  编译:WinAVR-20070122


  硬件环境:CA-M8X   打开的开关如下

            S6(1,2,5,6,7)   - 外部4MHz晶振和595接口

            J8(EN-SEG)      - 数码管显示允许

  

  芯艺设计室 2004-2007  版权所有 

  转载请保留本注释在内的全部内容

  WEB: http://www.chipart.cn

  Email: changfutong@sina.com

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


#include

#include

#include


#include "seg.h"


#define SER_PORT  PORTD

#define SER_DAT  PD4

#define SER_RCK  PD5

#define SER_SCK  PD6


//显示码(可从chipart.cn下载生成工具)

static uint8_t g_aDisplayBuf[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};


//向595 写一字节

static void ser_out(uint8_t dat)

{

  uint8_t i;


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

  {

    if(dat&0x80)

      SER_PORT|=_BV(SER_DAT);

    else

      SER_PORT&=~_BV(SER_DAT);

      

    //产生移位脉冲    

    SER_PORT|=_BV(SER_SCK);

    SER_PORT&=~_BV(SER_SCK);

    dat<<=1;

  }

}

//数码管显示数(0~255)

//num :显示的数   hex:是否用十六进制显示

void SegNumberOut(uint8_t num,uint8_t hex)

{

  uint8_t buf[2];//发送显示码缓冲区

  uint8_t temp;

  

  if(hex) //十六进制

  {

    buf[0]=g_aDisplayBuf[num>>4];//高位

    buf[1]=g_aDisplayBuf[num&0x0f];//低位

  }

  else//十进制

  {

    buf[1]=g_aDisplayBuf[num%10];

    temp=num%100;

    buf[0]=g_aDisplayBuf[temp/10];

    temp=num/100;

    

    if(temp>0)

      buf[1]|=0x80; //第一个数码管小数点表示百位1

    if(temp>1)

      buf[0]|=0x80;//两个数码管小数点表示百位2

  }

  

  //串行发送数据

  ser_out(buf[0]);

  ser_out(buf[1]);


  //产生锁存脉冲

  SER_PORT|=_BV(SER_RCK);

  SER_PORT&=~_BV(SER_RCK);

}


void SegInit(void)

{

  //595控制I/O初始化

  DDRD=_BV(SER_DAT)|_BV(SER_SCK)|_BV(SER_RCK);  

  SER_PORT&=~_BV(SER_SCK);

  SER_PORT&=~_BV(SER_RCK);

}


推荐阅读

史海拾趣

问答坊 | AI 解惑

先楫官方工程师干货:HPM6000电源管理系统功能和特性、功耗实测

作者:先楫应用工程师全立   本文介绍了HPM6000电源管理系统功能和特性,低功耗管理系统的功能和特性,低功耗应用开发的示例,最后基于HPM6300EVK开发板测试验证了HPM6300 MCU在各个电源模式下的功耗指标,方便用户快速评估和上 ...…

查看全部问答>

EEPROM擦写频率

EEPROM擦写频率   EEPROM擦写频率怎么理解?怎么根据擦写频率选择EEPROM还是flash?比如如下这个案列   每100ms采集一次数据,每秒存20个字节(实际使用清空EEPROM存储的数据是每周清除三次,这个是否也是擦写频率的一种?) ...…

查看全部问答>

产业升级|机智云工业DTU助力纺织行业智能化改造

本帖最后由 毛球大大 于 2022-11-9 19:51 编辑   作为第四次工业革命的重要基石,工业互联网为产业数字化提供了关键基础设施支撑和产业生态基础,成为数字经济创新发展的关键支撑。工业互联网的应用场景正在由销售、物流等 ...…

查看全部问答>

Qorvo:新的 “Matter” 协议是智能家居物联网市场增长的关键

预计今年晚些时候,连接物联网设备的新 Matter 标准将最终确定。如果您正在研究任何类型的智能家居解决方案,那么您有充分的理由对新的 “Matter”协议将为 Wi-Fi (和其他连接技术)带来的改变感到兴奋。  Qorvo 表示,“ ...…

查看全部问答>

最新发布的Matter技术小解

什么是Matter Matter 是智能家居无线连接技术的一种开放标准协议,可使家庭设备可以与任何经过Matter认证的Matter生态系统产品互联互通。 Matter技术小解 Matter是一个应用层规范,能够在任何支持IPv6的设备上运行。最初规范中支持的网络 ...…

查看全部问答>

电压VSWR&反射系数Γ

反射系数Γ,回波损耗RL和电压驻波比VSWR。但是这三个名词描述的其实是一个意思:反射波和入射波之间的关系。 反射系数Γ,回波损耗RL和电压驻波比VSWR之间的关系如下: 既然是一个意思,居然用了三个名词来描述,也足见反射在射频设 ...…

查看全部问答>

e络盟限时福利|《e选》---晒单

看到eeworld负责人发的e络盟有活动,赶紧上去看看,果然有活动,刚好最近DIY有需要用到电容,就买了几颗1000uF 35V和680uF 25V的电容,都是PANASONIC的,SF快递上海仓发货,三天就到了,非常快,哈哈,生命在于折腾,生命不息,折腾不止 &nb ...…

查看全部问答>

micropython新书《用 MicroPython 开发 Raspberry Pi Pico W》

本周发布了一本新书:用 MicroPython 开发 Raspberry Pi Pico W :Miguel Grinberg 用 Python 编程数字电路的简要介绍     欢迎阅读《用于 Raspberry Pi Pico W 的 MicroPython》,这本书将向您介绍令人兴奋的微控制器和小型互 ...…

查看全部问答>

Pimoroni银河独角兽开发板发布

Pimoroni银河独角兽开发板有一个巨大的 53 x 11 (583) RGB LED 矩阵,带有放大器和扬声器,核心是运行 Pimoroni 的 MicroPython 分支的 Raspberry Pi Pico W。 LED 可以在 14 位精度下以 300 fps 刷新。     技术指标: ...…

查看全部问答>

ROHM关于AC/DC的问答分享

Q、隔离型与非隔离型产品有何不同? A、隔离型的一次侧(AC线路)和二次侧(DC输出)是分离的,因此触电风险更低。而非隔离型的一次侧和二次侧是连接的,因此有触电的风险。 有些应用需要隔离型,有些则不需要。   Q、将IC的“NC ...…

查看全部问答>