论坛风格切换切换到宽版
  • 5451阅读
  • 4回复

关于DS18B20读写时序 [复制链接]

上一主题 下一主题
离线XLDZZ
 
发帖
443
只看楼主 倒序阅读 0楼 发表于: 2010-12-12
最近做温度计 采用ds18b20。可是读回来的数据全是0

主复位可读到18b20的存在回复脉冲,就是读不到温度

程序应该没问题的 上啦电阻采用4.7k电源5v,3,3v多不行
mcu采用ds18b20 10m晶振

程序如下
#include<pic.h>
__config(0x3b32);
#define uchar unsigned char
#define uint unsigned int
#define dq ra5
#define out() trisa5=0;dq=0
#define in() trisa5=1
uchar a1,a2,a3;
uint temper,i;
void init();
void delay(uint x);
void ds_reset();
void delayms(uint,uint,uchar);
void delayus(uint,uchar);
void get_tem();
void write_byte(uchar);
uchar read_byte();
const uchar table[]={0xd7,0x12,0xcb,0x5b,0x1e,0x5d,0xdd,0x13,0xdf,0x5f};
void dsp(uchar num1,uchar num2,uchar num3);
void sc();

void main()
{
init();
 
while(1)
  {
    get_tem();

    for(i=655;i>0;i--)
    {
      dsp(a1,a2,a3);
    }
    //in();
    //delay(1);//4.4
  //delayms(65535,65535,255);
  //delayus(100,120);
//delayus(100,90);//238
    //out();
    //delayms(65535,65535,255);
  //delayus(100,120);
    //delayus(100,90);//238
    /* delay(7);//16
    delay(23);//48
    delay(4);//10
    delay(3);//8.4
      delay(2);//6.4
      delay(1);//4.4
      delay(0);//2.6
        delay(5);//12
        delay(6);//14
        delay(14);//30
        delay(0);
          delay(0);
  */
  }
}







void ds_reset()
{
  uchar st=1;
  in();
  delay(0);

  while(st)
  {
  out();
  delayus(380,90);//延时742us
  in();//释放总线,拉高
  delay(10);
    if(dq==0)
    {
    st=0;
   
    }
    else
    st=1;
 
  }
delayus(200,200);//延时484us
}
void write_byte(uchar date)
{
  uchar i,temp;
    in();//释放总线,拉高
  delay(0);//延时2us
  out();//总线拉低
  delay(7);//延时16us
  for(i=8;i>0;i--)//发送8bit数据
    {
     
      temp=date&0x01;//01010101
     
      if(temp==1)
        {
          in();//释放总线,拉高
        delay(14);//延时30us
        }
      else      
        {
             out();
     delay(14);//延时30us      
        }
     date=date>>1;// 移1位
      in();//释放总线,拉高
     delay(0);//延时2us
       
     
      }
 
}
uchar read_byte()
{
  uchar i,date;
  static bit j;
  for(i=8;i>0;i--)
    {
      date=date>>1;
      in();//释放总线,拉高
      delay(0);
      out();
      delay(2);//6us
      in();//释放总线,拉高
      delay(1);//4us
      j=dq;
      if(j==1)
      date=date|0x80;//1000 0000
      delay(14);//30us
      }
    return (date);
}

void get_tem()
{
     uchar tem1,tem2,num;

     float aaa;
     ds_reset(); //复位
     write_byte(0xcc);//跳过rom
     write_byte(0x44);//温度转换
          delayms(65535,65535,255);//延时750ms

     ds_reset();
     write_byte(0xcc);
     write_byte(0xbe);
     tem1=read_byte();
     tem2=read_byte();
     if (tem1==0)
      {
            rd7=1;
      sc();
      }
     
      if (tem1==0)
      {
            rd6=1;
      sc();
      }
     aaa=(tem2*256+tem1)*6.25;
     temper=(int)aaa;
     if (temper==0)
      {
            rd7=1;
      sc();
      }
     
     a1=temper/1000;
     a2=temper%1000/10;
     a3=temper%100/10;

}
void init()

{

//trisa=0xff;
trisb=0;
trise=0;
trisd=0;
trisc=0;
porte=0;
portd=0;
portb=0;
porta=0;
porte=0x06;
delay(2);
porte=0;
cmcon=0x07;//关比较器


}
void int_init()
{
gie=0;//开总中断
adie-1;//开ad中断
peie=1;//开外围中段
tmr2ie=1;//开定时器2中断

t2con=0x2a;//前后分频5/1(5*4),定时器2电源关闭。
tmr2if=0;//清中断标志位
tmr2on=1;//开定时器2
pr2=0x01;//十进制数20(5*4*50=1000us)
}

void dsp(uchar num1,uchar num2,uchar num3)
{
portb=table[num1];//显示第一个数码管
portd=0x04;
sc();
delay(2);
portb=table[num2];//显示第二个数码管
portd=0x02;
sc();
delay(2);
portb=table[num3];//显示第三个数码管
portd=0x01;
sc();
delay(2);
}

void sc()//数据所存
{
porte=0;
delay(2);
porte=0x06;
delay(2);
porte=0;
delay(2);
}


void delay(uint x)//延时程序
{
uint a,b;
for(a=x;a>0;a--);
 
}
void delayus(uint x,uchar y)//双数据延时
{
  uint i;
  uchar j;
  for(i=x;i>0;i--);
  for(j=y;j>0;j--);
}
void delayms (uint x,uint y,uchar z)//三数据延时
{
  uint i;
  uint k;
  uchar j;
  for(i=x;i>0;i--)
  delay(4);
  for(j=y;j>0;j--);
  for(k=z;z>0;z--);
}
离线ba6iv
发帖
1286
只看该作者 1楼 发表于: 2010-12-12
我用的avr的mcu,不过c程序大致都差不多,你可以参考一下,已经试验成功的程序。
#include <iom16v.h>
#include <macros.h>


#define dq_in      ddra &= ~(1 << pa7)            /*设置输入*/
#define dq_out      ddra |= (1 << pa7)            /*设置输出*/
#define dq_clr      porta &= ~(1 << pa7)      /*置低电平*/
#define dq_set      porta |= (1 << pa7)            /*置高电平*/
#define dq_r      pina & (1 << pa7)            /*读了电平*/

unsigned char flag;                                    /*中断标志缓存*/
unsigned char ds18b20_id[8];

/*
延时函数

延时时间:i x 10 + 16us。
cpu频率为:1mhz。
*/
void delay_10us(unsigned char i) {

     if (i == 0) {
           return ;
           }
     while (i--) {
           nop();
           nop();
           nop();
           nop();
           }
}

/*ds18b20复位函数*/
unsigned char ds1820_reset(void) {

     unsigned char i;
     flag = sreg;                        /*中断保护*/
     cli();                                    /*关中断*/
     dq_out;
     dq_clr;
     delay_10us(49);                        /*延时500us(480-960)*/
     dq_set;
     dq_in;
     delay_10us(7);                        /*延时80us*/
     i = dq_r;
     delay_10us(49);                        /*延时500us(保持>480us)*/
     if (flag & 0x80) {                  /*恢复中断状态*/
           sei();
           }
     if (i) {
           return 0x00;
           }
     else {
           return 0x01;
           }
}

/*ds18b20字节读取函数*/
unsigned char ds1820_read_byte(void) {

     unsigned char i;
     unsigned char value = 0;
     flag = sreg;                        /*中断保护*/
     cli();                                    /*关中断*/
     for (i = 8; i != 0; i--) {
           value >>= 1;
           dq_out;
           dq_clr;
           nop();                              /*延时4us*/
           nop();
           nop();
           nop();
           dq_set;
           dq_in;
           nop();                              /*延时10us*/
           nop();
           nop();
           nop();
           nop();
           nop();
           nop();
           nop();
           nop();
           nop();
           if (dq_r) {
                 value|=0x80;
                 }
           delay_10us(5);                  /*延时60us*/
           }
     if (flag & 0x80) {                  /*恢复中断状态*/
           sei();
           }
     return(value);
}

/*ds18b20字节写入函数*/
void ds1820_write_byte(unsigned char value) {

     unsigned char i;
     flag = sreg;                        /*中断保护*/
     cli();                                    /*关中断*/
     for (i = 8; i != 0; i--) {
           dq_out;
           dq_clr;
           nop();                              /*延时4us*/
           nop();
           nop();
           nop();
           if (value & 0x01) {
                 dq_set;
                 }
           delay_10us(7);                  /*延时80us*/
           dq_set;                              /*位结束*/
           value >>= 1;
           }
     if (flag & 0x80) {                  /*恢复中断状态*/
           sei();
           }
}

/*启动ds1820转换*/
void ds1820_start(void) {

     ds1820_reset();
     ds1820_write_byte(0xcc);      /*勿略地址*/
     ds1820_write_byte(0x44);      /*启动转换*/
}

/*ds8b20读取温度信息*/
unsigned int ds1820_read_temp(void) {

     unsigned int i;
     unsigned char buf[9];

     ds1820_reset();
     ds1820_write_byte(0xcc);      /*勿略地址*/
     ds1820_write_byte(0xbe);      /*读取温度*/
     for (i = 0; i < 9; i++) {
           buf = ds1820_read_byte();
           }
     i = buf[1];
     i <<= 8;
     i |= buf[0];
     
     return i;
}


/*读取ds1820的id码,64位,保存在ds18b20_id[]中*/
void ds1820_read_id(void) {
     unsigned int i;
     
     ds1820_reset();
     ds1820_write_byte(0x33);      /*勿略地址*/
     for (i = 0; i < 8; i++) {
           ds18b20_id = ds1820_read_byte();
           }
}

ds18b20操作时时序很重要,包括延时函数都需要注意。
离线albert
发帖
4807
只看该作者 2楼 发表于: 2010-12-13
美信有1-wire的现成驱动,照着他们的写比较好,要不就拿示波器/逻辑分析仪跟踪时序
离线bg8ux
发帖
178
只看该作者 3楼 发表于: 2011-01-13
我最近用51单片机实现了18b20的测温程序,不是很麻烦啊,lz的搞定没?
离线XLDZZ
发帖
443
只看该作者 4楼 发表于: 2011-01-14
搞定了 这个我是犯了个粗心大意的毛病

端口初始化不完整造成的