lusolzyy 发表于 2012-9-4 21:05:56

DS18B20问题

我是单片机新手,昨天开始编写DS18B20的驱动程序,现在碰到一点问题,希望高手指导一二!!

lusolzyy 发表于 2012-9-4 21:08:01

恩?为什么不能发程序??

lusolzyy 发表于 2012-9-4 21:10:48

/*****************************************************
This program was produced by the
CodeWizardAVR V2.05.5a Evaluation
Automatic Program Generator
?Copyright 1998-2011 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date    : 2012/9/4 星期二
Author: Freeware, for evaluation and
non-commercial use only
Company :
Comments:


Chip type               : ATmega16
Program type            : Application
AVR Core Clock frequency: 4.000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 256
*****************************************************/
#include <mega16.h>
#include <alcd.h>
#include <delay.h>
#define DQ_18b20 0x01//设置PDx口为数据总线接口
#define DQ_0() (DDRD.0=1)//数据总线拉低(占领总线)
#define DQ_1() (DDRD.0=0)//数据总线拉高(释放总线)
#define DQ_readbit PIND.0//读取数据总线上1bit的数据
/*************************** 将18b20与默认数据总线相连***************************/
void connect_18b20(void)
{
    DDRD.0=0; //将PDx口设置成输入模式
    PORTD.0=0;//上拉电阻设置无效
}
/****************************************************************************************/
/********************复位总线,检测有无芯片连接总线****************************/
unsigned char ds18b20_reset(void)
{
    unsigned charjudge_18b20;
   #asm("cli"); //关中断防干扰
    DQ_0(); //占领总线
   delay_us(500);//防止信号抖动(最短480us的低电平信号)
   DQ_1();//释放总线
   delay_us(68);//忙延时
   if( DQ_readbit)
            judge_18b20=0;//DS1820若不发出低电平脉冲则视作该线路上没有芯片安装
   else
            judge_18b20=1;//反之则检测到18b20安装
   #asm("sei");//开中断
   delay_us(440);//保证数据总线被释放
   return(judge_18b20);   
}
/****************************************************************************************/
/****************************写命令至DS18B20****************************************/
void ds18b20_write(unsigned char command)
{
      unsigned char count;//定义计数变量
       #asm("cli");//关中断
      for(count=0;count<8;count++)//一共写八位命令
      {
                DQ_0();//输入低电平信号
                delay_us(8);//在15us内输入信号
                if(command&0x01)
                        DQ_1();//高平为1,低平为0
                command>>=1;//为下一次写命令移位
                delay_us(62);
                DQ_1();//恢复高平            
      }
      #asm("sei");//开中断   
}
/****************************************************************************************/
/*********************************从DS18B20读命令***********************************/
unsigned char ds18b20_read(void)
{
      unsigned char data=0x00,count;//定义读数据变量,计数变量
      #asm("cli");//关中断
      for(count=0;count<8;count++)
      {
                DQ_0();//拉低电平
                delay_us(2);//保证在15us前拉高
                DQ_1();//进入读数据状态
                data>>=1;//移位写下一个数据
                if(DQ_readbit)
                  data|=0x80;//若为1则写入最高位
                delay_us(65);
      }
      #asm("sei");//恢复中断
      return(data);      
}
/****************************************************************************************/
/*********************************读温度函数******************************************/
unsigned char temp_read(void)
{
      unsigned char t=0;//定义温度变量t
      if(ds18b20_reset())//如果初始化成功
      {
                ds18b20_write(0xcc);//跳过序列号识别
                ds18b20_write(0x44);//启动温度转换
                delay_us(100);
                ds18b20_reset();//初始化
                ds18b20_write(0xcc);//跳过序列号识别
                ds18b20_write(0xbe);//读暂存器
                delay_us(100);
                t=ds18b20_read();//读低字节
                t+=(ds18b20_read())<<8;
      }
      return (t);
}
/****************************************************************************************/

void main(void)
{
unsigned char temparature=0x00,display;
PORTA=0x00;
DDRA=0x00;
PORTB=0x00;
DDRB=0x00;
PORTC=0x00;
DDRC=0x00;
PORTD=0x00;
DDRD=0x00;

TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

MCUCR=0x00;
MCUCSR=0x00;

TIMSK=0x00;

UCSRB=0x00;

ACSR=0x80;
SFIOR=0x00;


ADCSRA=0x00;

SPCR=0x00;

TWCR=0x00;

lcd_init(16);
connect_18b20();//将PD0与总线相连
while (1)
      {
            unsigned char i;
            unsigned char test;
            test=ds18b20_reset()+48;
            temparature=temp_read() ;
            for(i=0;i<12;i++)
            {
                  if(temparature&0x01)
                  display=49;
                  else
                  display=48;
                  temparature>>=1;
            }
            lcd_clear();
            lcd_gotoxy(0,0);
            lcd_puts(display);
            lcd_gotoxy(0,1);
            lcd_putchar(test);
            lcd_gotoxy(1,1);
            delay_ms(500);
      }
}

lusolzyy 发表于 2012-9-4 21:12:35

用的是单线窃电的模式,在PD0口上拉一250的电阻接5V电源,但是在LCD上显示均为0,调了很久也不行,不知道哪里出问题啊,现在挺着急!!
希望高手能够指点一二!

wye11083 发表于 2012-9-4 21:27:05

很简单,循环的延时问题。1-Wire对时序要求非常严格,必须完全按时序来。

lusolzyy 发表于 2012-9-4 21:35:06

wye11083 发表于 2012-9-4 21:27 static/image/common/back.gif
很简单,循环的延时问题。1-Wire对时序要求非常严格,必须完全按时序来。

我猜想也是时序问题,但是根据datasheet上的时序来做还是不行啊,调了很多次多不行

wye11083 发表于 2012-9-4 21:40:47

坛里有人测试过,那种延时1us都直接上5us了,非常不稳定。不要用。

lusolzyy 发表于 2012-9-4 21:44:27

wye11083 发表于 2012-9-4 21:40 static/image/common/back.gif
坛里有人测试过,那种延时1us都直接上5us了,非常不稳定。不要用。

那延时最好用什么做比较好?

wye11083 发表于 2012-9-4 22:26:16

你先试验再说吧。总能找到方法。

lusolzyy 发表于 2012-9-9 17:23:31

wye11083 发表于 2012-9-4 22:26 static/image/common/back.gif
你先试验再说吧。总能找到方法。

我找到问题的原因了,是因为我之前在protues里的时钟设定问题,用示波器测出来的,以后不能再犯这种低级错误了!
页: [1]
查看完整版本: DS18B20问题