3787|8

7

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

有关ATMEGA128和DS18B20的问题 [复制链接]

1芯积分
最近在做一个DS18B20测室温的程序,单片机是AVR的,也在网上查了很多资料,自己写了很多程序,然而一个也没调出来,感觉挺受挫的 ,又不想搁置,特来此寻找大神帮我看看我的程序,找到错误之处。新人没有多少芯币,还望不要嫌弃。下面是我的程序:/*******************************头文件**************************************/
#include
#include

/*******************************宏定义*************************************/
#define TEM_PORT PORTG
#define TEM_DDR DDRG
#define TEM_PIN PING

#define TEM_SDT 3

#define SET_TEM_SDT (TEM_PORT|=(1< #define CLR_TEM_SDT (TEM_PORT&=~(1<
#define SET_TEM_DDR (TEM_DDR|=(1< #define CLR_TEM_DDR (TEM_DDR&=~(1<
#define CHECK_TEM_SDT (TEM_PIN&(1<
/*************************************************************
**
**
**串口和液晶屏
**
**
*************************************************************/
/******************************uart0初始化*********************************/
void uart0_init(void)
{
        UCSR0B=0x00;                        //关闭UART00
        UCSR0A=0x00;                       //不使用倍速发送(异步)
        UCSR0C=0x06;    //数据位为8位
        UBRR0L=103;    //波特率9600
        UBRR0H=0x00;  //误差率0.156%
        UCSR0B=0x98; //发送接收使能,接收结束使能
}


/***************************uart0发送单字节数据****************************/
void putchar0(unsigned char c)
{
        while (!(UCSR0A&(1<         UDR0=c; //将要发送的数据装入UDR0寄存器
}

/*****************************LCD显示函数***********************************/
void LCD_display(unsigned char i,unsigned char j)
{
    putchar0(0x5A);
        putchar0(0xA5);
        putchar0(0x05);
        putchar0(0x82);
        putchar0(0x00);    //地址高位
        putchar0(i);       //地址低位
        putchar0(0x00);    //数据高位
        putchar0(j);       //数据低位
        WDR();
}

/*************************************************************
**
**
**延时函数
**
**
**************************************************************/
void delay2_1us(void)//延时1us
{
     NOP();
         NOP();
         NOP();
         NOP();
}

void delay1_1us(void)    //940ns
{
         NOP();
}

void delay1_nus(unsigned int n)       //N us延时函数
{   
   unsigned int i=0;   
   for(i=0;i    {
   delay1_1us();
   }   
}   

void delay10us(unsigned int n)       //n=10 ,10us延时函数
{   
   unsigned int i=0;   
   for(i=0;i    {
       NOP();
           NOP();
           NOP();
           NOP();
           NOP();
           NOP();
           NOP();
   }   
}   
void delay(unsigned int k)
{
        unsigned int n;
        n = 0;
        while(n         {
                n++;
        }
        return;
}

void delay6(unsigned char x,unsigned char y)
{
    unsigned char z;
        do{
             z = y;
                 do
                 {
                     ;
                 }
                 while(--z);
          }
          while(--x);
}


void delay5(unsigned int count) //count=13,1ms延时子函数
{
unsigned int i;
while(count)
{
i=200;
while(i>0)
i--;
count--;
}
}

void delay1(void)    //延时大约1秒(较精确)
{       
        unsigned int x;
        unsigned int y;
        for(x=0;x<1000;x++)
        {
                for(y=0;y<2286;y++)
                {
                        WDR();
                }
                WDR();
        }
}

/**************************************************************
** 函数名称: void init_1820(void)
** 功能描述: 18b20初始化
** 输 入: 无
** 全局变量: 无
** 调用模块: 无
** 说明:
** 注意:
**************************************************************/
void init_1820(void)  
{  
    TEM_DDR &=~ (1<         SET_TEM_DDR;      //设置数据端口为输出
    SET_TEM_SDT;
    CLR_TEM_SDT;  
    delay1_nus(600);  //480us以上(530us)
    SET_TEM_SDT;  
    CLR_TEM_DDR;  
    delay10us(10);
        delay10us(10);    //15~60us (20us)
    while(CHECK_TEM_SDT);  
    SET_TEM_DDR;  
    SET_TEM_SDT;  
    delay6(5,50);    //60~240us (97us)
}
/**************************************************************
** 函数名称: void write_1820(unsigned char data)
** 功能描述: 向18b20写入1B的数据
** 输 入: unsigned char data 要写入的数据
** 全局变量: 无
** 调用模块: 无
** 说明:
** 注意:
**************************************************************/
void write_1820(unsigned char data)  
{
    unsigned char i;  
    for(i=0;i<8;i++)  
    {  
       //SET_TEM_SDT;
           CLR_TEM_SDT;  //从高到低,产生写间隙
       if(data&(1<                 SET_TEM_SDT;  
       else  
         CLR_TEM_SDT;  
       delay6(2,60);     //15~60us (46us)
       SET_TEM_SDT;  
           data>>=1;
    }  
    SET_TEM_SDT;  
}
/**************************************************************
** 函数名称: unsigned char read_1820(void)
** 功能描述: 从18b20读出1B的数据
** 输 入: 无
** 全局变量: 无
** 调用模块: 无
** 说明:
** 注意:
**************************************************************/
unsigned char read_1820(void)  
{      
    unsigned char temp,k,n;  
    temp=0;  
    for(n=0;n<8;n++)  
    {
      //SET_TEM_DDR;           //设为输出
          CLR_TEM_SDT;  
          temp>>=1;
      SET_TEM_SDT;           //从高到低再到高,产生读间隙
      CLR_TEM_DDR;           //设为输入  
      k=CHECK_TEM_SDT;       //读数据,从低位开始  
      if(k)  
        temp|=(1<       else  
        temp&=~(1<       delay1_nus(100);       //60~120us(82us)      
      SET_TEM_DDR;           //设为输出
    }  
   return (temp);  
}
/**************************************************************
** 函数名称: unsigned char gettemp(void)
** 功能描述: 返回温度值
** 输 入: 无
** 全局变量:
** 调用模块: 无
** 说明:wmh为温度的高位,wml为温度的低位,返回值为温度值,范围0~99摄氏度,字符型
** 注意:
**************************************************************/
unsigned char gettemp(void)         //读取温度值
{  
     unsigned char temh,teml,wm0,wm1,wm2,wm3,wmh,wml,temp;
     init_1820();        //复位18b20  
     write_1820(0xCC);   // 跳过ROM
     write_1820(0x44);  // 温度变换

     init_1820();
     write_1820(0xCC);  // 跳过ROM
     write_1820(0xbe);  // 写暂存存储器
     teml=read_1820();  //读数据  
     temh=read_1820();  
     wm0=teml>>4;       //只要高8位的低四位和低8位的高四位,温度范围0~99
     wm1=temh<<4;
       
     wm2=wm1+wm0;        //16进制转10进制
     wm3=wm2/100;
     wmh=(wm2%100)/10;   //wmh是显示的高位,wml是显示的低位
     wml=(wm2%100)%10;
         temp=wmh*10+wml;
         
         return temp;
}


/**************************************************************
**
**
**主函数
**
**
***************************************************************/
void main(void)
{
unsigned char temp1=0;
init_1820();
while(1)
        {
                 temp1=gettemp();
                 LCD_display(0x0A,temp1);
        }
}



最新回复

正是因为存在中断,会影响时序,所以需要在单总线操作期间禁止中断。 我的程序中开始就关闭中断,完成后恢复中断状态 void OWI_WriteBit1(unsigned char pins) {   unsigned char intState;       // Disable interrupts.   intState = __save_interrupt();   cli();       // Drive bus low and delay.   OWI_PULL_BUS_LOW(pins);   _delay_us(OWI_DELAY_A_STD_MODE);       // Release bus and delay.   OWI_RELEASE_BUS(pins);   _delay_us(OWI_DELAY_B_STD_MODE);       // Restore interrupts.   __restore_interrupt(intState); }复制代码 你的代码中就没有相关的处理 void write_1820(unsigned char data)   {     unsigned char i;       for(i=0;i<8;i++)       {          //SET_TEM_SDT;            CLR_TEM_SDT;  //从高到低,产生写间隙        if(data&(1<<i))    //写数据,先写低位                 SET_TEM_SDT;          else            CLR_TEM_SDT;          delay6(2,60);     //15~60us (46us)        SET_TEM_SDT;              data>>=1;     }       SET_TEM_SDT;   }复制代码   详情 回复 发表于 2016-11-18 15:14
点赞 关注
 

回复
举报

1万

帖子

25

TA的资源

版主

沙发
 
问题应该在时序上,特别是使用循环进行延时时,与时钟频率有很大关系,如果不加注意,会出现很多问题。如果使用AVRGCC,有专门的延时函数,如果是ICC或者IAR,需要自己完成了。

建议特别看看下面两篇应用笔记:

AVR318:Dallas 1-Wire master on tinyAVR and megaAVR devices
http://www.atmel.com/images/atmel-2579-dallas-1wire-master-on-tinyavr-and-megaavr_applicationnote_avr318.pdf

MAXIM 126:用软件实现 1-Wire 通信
https://www.maximintegrated.com/cn/app-notes/index.mvp/id/126

在《AVR单片机专题精讲》一书中也专门介绍了单总线的使用技巧,可以参考。
 
 
 

回复

1万

帖子

25

TA的资源

版主

板凳
 
还可以在proteus中去仿真,效果不错。
 
 
 

回复

7

帖子

0

TA的资源

一粒金砂(中级)

4
 
dcexpert 发表于 2016-11-17 20:32
问题应该在时序上,特别是使用循环进行延时时,与时钟频率有很大关系,如果不加注意,会出现很多问题。如果 ...

我写的那些延时都是用示波器勾过得,数据应该是没错,我又分开写了读一位1  读一位0,写一位1,写一位0  的函数,然后读字节写字节时在调用   示波器有显示波形,也能看出两次复位和写命令后 还有一段波形,应该是读温度那部分,但是液晶屏上却没有读数显示

点评

如果不是很好的示波器,测这样us级的时间误差是比较大的,需要仔细测试看看。 还有因为时序的要求严格,通常在读写位时是需要关中断的。  详情 回复 发表于 2016-11-18 09:47
 
 
 

回复

1万

帖子

25

TA的资源

版主

5
 
Doris.Lee 发表于 2016-11-18 08:31
我写的那些延时都是用示波器勾过得,数据应该是没错,我又分开写了读一位1  读一位0,写一位1,写一位0   ...

如果不是很好的示波器,测这样us级的时间误差是比较大的,需要仔细测试看看。

还有因为时序的要求严格,通常在读写位时是需要关中断的。
 
 
 

回复

1万

帖子

25

TA的资源

版主

6
 
下面是我写的程序,可以参考,在实际芯片上运行过。使用AVRGCC,附带proteus仿真程序。



1-wire.zip (80.29 KB, 下载次数: 6)
 
 
 

回复

7

帖子

0

TA的资源

一粒金砂(中级)

7
 
dcexpert 发表于 2016-11-18 09:47
如果不是很好的示波器,测这样us级的时间误差是比较大的,需要仔细测试看看。

还有因为时序的要求严格 ...

我的程序其实是有中断的  ,但是我现在只想测试18B20,所以我只写了这一部分,其他部分都去掉了,所以没有中断存在,我用的ICCAVR,延时都是自己写的,也通过高低电平变化测过时间。

点评

正是因为存在中断,会影响时序,所以需要在单总线操作期间禁止中断。 我的程序中开始就关闭中断,完成后恢复中断状态 你的代码中就没有相关的处理  详情 回复 发表于 2016-11-18 15:14
 
 
 

回复

1万

帖子

25

TA的资源

版主

8
 
Doris.Lee 发表于 2016-11-18 13:21
我的程序其实是有中断的  ,但是我现在只想测试18B20,所以我只写了这一部分,其他部分都去掉了,所以没 ...

正是因为存在中断,会影响时序,所以需要在单总线操作期间禁止中断。

我的程序中开始就关闭中断,完成后恢复中断状态
  1. void OWI_WriteBit1(unsigned char pins)
  2. {
  3.   unsigned char intState;
  4.    
  5.   // Disable interrupts.
  6.   intState = __save_interrupt();
  7.   cli();
  8.    
  9.   // Drive bus low and delay.
  10.   OWI_PULL_BUS_LOW(pins);
  11.   _delay_us(OWI_DELAY_A_STD_MODE);
  12.    
  13.   // Release bus and delay.
  14.   OWI_RELEASE_BUS(pins);
  15.   _delay_us(OWI_DELAY_B_STD_MODE);
  16.    
  17.   // Restore interrupts.
  18.   __restore_interrupt(intState);
  19. }
复制代码


你的代码中就没有相关的处理

  1. void write_1820(unsigned char data)  
  2. {
  3.     unsigned char i;  
  4.     for(i=0;i<8;i++)  
  5.     {  
  6.        //SET_TEM_SDT;
  7.            CLR_TEM_SDT;  //从高到低,产生写间隙
  8.        if(data&(1<<i))    //写数据,先写低位
  9.                 SET_TEM_SDT;  
  10.        else  
  11.          CLR_TEM_SDT;  
  12.        delay6(2,60);     //15~60us (46us)
  13.        SET_TEM_SDT;  
  14.            data>>=1;
  15.     }  
  16.     SET_TEM_SDT;  
  17. }
复制代码


 
 
 

回复

7

帖子

0

TA的资源

一粒金砂(中级)

9
 
dcexpert 发表于 2016-11-18 15:14
正是因为存在中断,会影响时序,所以需要在单总线操作期间禁止中断。

我的程序中开始就关闭中断,完成 ...

我的程序中没有中断,原来18B20这部分只是我写的程序中的某一个功能 ,后来我单摘出来这部分写的程序
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表