原创 DS18B20

2008-3-13 12:03 2006 5 5 分类: MCU/ 嵌入式

/********************************
  DS18B20测温程序
  文件名:main.c
  编译:CV1.25.4 由芯艺网站改写


软件缺点是单总线上只能挂一个DS18B20
*******************************/
#include< mega16.h>
#include


#define uint8_t  unsigned char
#define uint16_t unsigned int
#define uint32_t unsigned long int
#define UDRE 5


#define Clr_1Wire DDRB.2=1 //设置为输出,此时由于PORTB.2是低所以输出低
#define Set_1Wire DDRB.2=0//设置为输入,此时由于PORTB.2是低所以程高阻,


                                               //又因为外部有上拉电阻所以相当于设置总线为高
#define Get_1Wire PINB.2


#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


uint8_t rom_codes[8];



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


总线端口初始化


**********************/
void BusInit(void)
{
       PORTB.2=0;//此口总保持低
       DDRB.2=0; //初始化为输入,用外部上拉电阻保持总线的高电平
}


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


初始化串口,9600bps,8N1


**********************************/
void init_uart(void)
{
        UCSRA="0x00";
        UCSRB="0x08";
        UCSRC="0x86";
        UBRRH="0x00";
        UBRRL="0x47";
}



void put_c(uint8_t c) //发送采用查询方式
{
        while( !(UCSRA & (1< 

        UDR="c";
}


/*void put_s(unsigned char *ptr)
{
     while (*ptr)
    {
                  put_c(*ptr++);
    }
     put_c(0x0D);
     put_c(0x0A);  //结尾发送回车换行
}*/
//单总线复位
uint8_t ds18b20_reset(void)
{
            uint8_t ret="0";
            Clr_1Wire;
            delay_us(500);  //拉低总线至少480us
            Set_1Wire;
            delay_us(100);//释放总线后等待15-60us
            if((Get_1Wire)==0)//检测到DS18B20把总线拉低
            ret="1";        //复位成功
            delay_us(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; 
              delay_us(2);//此时>1us
             Set_1Wire;
             delay_us(4);//此时<15us
             if(Get_1Wire)
            data|=0x80; 
            delay_us(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;
                         delay_us(8);//8us
                         Set_1Wire; 
                         delay_us(55);//55us
                  }
                   else
                  {
                        Clr_1Wire; 
                        delay_us(55);//55us
                        Set_1Wire;
                       delay_us(20);//8us 
                    } 
                  data>>=1;
          }
}



uint8_t ds18b20_search(uint8_t cmd,uint8_t *point)

    uint8_t i="0";
   
    if(ds18b20_reset()==0)
    return 0;
    ds18b20_write(cmd);
    for(i=0;i<8;i++)
    {
     point=ds18b20_read();
    }
    return 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
  delay_ms(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中读的温度字节,计算实际温度值
char GetTemperature(uint8_t *t)
{
  char 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=(char)val;
 
  if(sflag)
    ret|=0x80;//变负数
   
  return ret;
}
//测试主函数
void main(void)
{
  uint8_t i;
  uint8_t tmp[2];//保存温度字节
  char tval;    //保存温度值
  init_uart();
  BusInit();  //单总线I/O口初始化
  if(Ds18b20Convert(tmp))//如果转换成功
  {
      put_c(tmp[0]);
      put_c(tmp[1]);
      tval="GetTemperature"(tmp);//计算实际温度值
      put_c(tval);
  }
  ds18b20_search(DS18B20_READ_ROM,rom_codes);
         for(i=0;i<8;i++)
        {
                put_c( rom_codes);
        }
}

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
5
关闭 站长推荐上一条 /3 下一条