AVR单片机读取DS18B20温度上传到串口程序

2019-10-22来源: 51hei关键字:AVR单片机  读取DS18B20  温度上传  串口程序

#include         
#include
#include    //中断函数头文件
//××××××××××××引脚宏定义×××××××××××××
//18B20定义
#define SET_DQ (PORTE) |= (1 << (PE7))      // 18b20 高电平
#define CLR_DQ (PORTE) &=~(1 << (PE7))      // 18b20 低电平
#define DQ_IN  (PINE) & (1<<(PE7))            // 18b20信号输入
#define SET_OUT (DDRE) |= (1<<(PE7))         //PA2定义成输出
#define SET_IN  (DDRE) &=~(1<<(PE7))         //PA2定义成输入

//常量声明
#define BAUD 9600
//全局变量声明
unsigned char Temp_H,Temp_L,OK_Flag;    //温度高位,低位,复位成功标志
//函数声明
void Delayus(unsigned int lus);         //us延时函数
void Delayms(unsigned int lms);        //ms延时函数
void Port_DS18b20(void);              //DS18B20端口配置
void Port_Init(void);   //端口初始化配置
void Usart_Init(void);  //USART寄存器设置
void Usart_PutChar(unsigned char cTXData);  //字节发送函数
void Usart_PutString(unsigned char *pcString); //字符串发送函数
unsigned char DS18B20_Init(void);   //DS18B20初始化
unsigned char Read_18b20(void);        //读18b20
void Write_18b20(unsigned char dat);   //写18b20
int main(void)            
{
unsigned char i;
unsigned int tempint,tempint1,tempint2,tempint3,tempint4;
                    //分别存储温度整数值,整数值的千,百,十,个位
unsigned int temppoint,temppoint1,temppoint2,temppoint3,temppoint4;  
                     //分别存储温度小数值,小数值的千,百,十,个位

Port_Init();    //端口初始化
Usart_Init();   //串口初始化
Port_DS18b20();   //DS18B20端口初始化

tempint = 0;   //变量初始化
temppoint=0;
Temp_H = 0;
Temp_L = 0;
OK_Flag = 0;

Usart_PutString("DS18B20 温度测量实验");
Usart_PutChar(0x0D);
Usart_PutChar(0x0A);  //结尾发送回车换行


sei();          //使能全局中断  

while(1)
{   
  /*
  if(DS18B20_Init())   //判断DS18B20复位是否成功
  {
   PORTB = 0x01;
  }
  else
  {
   PORTB = 0x02;
  }
  */
  cli();     //关中断
  
  DS18B20_Init();     //初始化DS18B20
  
  Write_18b20(0Xcc);  //发送ROM指令,跳过ROM匹配
  
  Write_18b20(0X44);  // 发送温度转换命令 
  
  for(i=0;i<50;i++)      //延时1S,等转换完成
  {
   Delayms(20);
  }
  
  DS18B20_Init();    //初始化DS18B20
  
  Write_18b20(0Xcc);  //发送ROM指令,跳过ROM匹配
  
  Write_18b20(0Xbe);  //发送读取暂存器指令
   
  Temp_L = Read_18b20(); //获得温度的低位
  
  Temp_H = Read_18b20(); //获得温度的高位
   
  if(Temp_H & 0x08)   //判断温度的正负
  {   
   Temp_H = ~Temp_H;  //负温度。取反加1
   Temp_L = ~Temp_L;  //
  
   SREG |= ~(1 << SREG_C);  //清零进位位标志
   Temp_L++;                  //温度低字节加1
   if(SREG & (1 << SREG_C))  //有进位吗?
   {
    Temp_H++;           //有进位,则温度高字节加1
   }
  
  } 
   
  tempint = ((Temp_H << 4) & 0x70) | (Temp_L >> 4);     //获得温度的整数位 
  
  tempint1 = tempint / 1000;           //千位 
  tempint2 = tempint % 1000 / 100;     //百位
  tempint3 = tempint % 100 / 10;        //十位
  tempint4 = tempint % 10;              //个位
  
  temppoint = Temp_L & 0x0f;    //取出温度的小数位
  temppoint = (temppoint * 625);  //小数位乘以0.625得出温度的小数位值,在此扩大1000
                                    //倍,得出温度的4位小数位,显示的时候加小数点
   
  temppoint1 = temppoint / 1000;           //千位 
  temppoint2 = temppoint % 1000 / 100;     //百位
  temppoint3 = temppoint % 100 / 10;        //十位
  temppoint4 = temppoint % 10;              //个位
  
  Usart_PutString("当前环境温度为:");   //发送温度值到上位机
  
  if(!(tempint1))            //高位为零,则不显示
  {
   Usart_PutChar(' ');
   if(!(tempint2))
   {
    Usart_PutChar(' ');
   }
   else
   {
    Usart_PutChar(tempint2 + 0x30);
   }
   if(!(tempint3))
   {
    Usart_PutChar(' ');    
   }
   else 
   {
    Usart_PutChar(tempint3 + 0x30);
   }
   //Usart_PutChar(tempint4 + 0x30);
  }
  else
  {
   Usart_PutChar(tempint1 + 0x30);
   Usart_PutChar(tempint2 + 0x30);
   Usart_PutChar(tempint3 + 0x30);
  }
  Usart_PutChar(tempint4 + 0x30);
  Usart_PutChar('.');                 //显示小数点
  
  Usart_PutChar(temppoint1 + 0x30);    //显示小数位
  Usart_PutChar(temppoint2 + 0x30);
  Usart_PutChar(temppoint3 + 0x30);
  Usart_PutChar(temppoint4 + 0x30);

  Usart_PutChar(' ');           //不显示,空一格
  Usart_PutChar('o');           //显示温度的符号。由于实在找不到温度那个再上面的小o,
  Usart_PutChar('C');          //只好用普通的小写o来代替了。
  Usart_PutChar(0x0D);
  Usart_PutChar(0x0A);  //结尾发送回车换行 
        
  sei();          //开中断

  for(i=0;i<200;i++)      //延时4S,再进行温度转换
  {
   Delayms(20);
  }
}
}
//端口状态初始化设置函数
void Port_Init()
{
PORTD = 0X00;          //USART的发送接收端口分别为PD0和PD1
DDRD |= (1 << PD3);   //PD0为接收端口,置为输入口;PD1为发送端口,置为输出口
PORTB = 0x00;
DDRB = 0xff; 
}
void Port_DS18b20()
{
DDRE &= ~(1 << PE7);   // 输入模式(上电时为高电平)
    PORTE &= ~(1 << PE7);  // 输出锁存器写0,以后不再更改
}
//USART寄存器配置函数
void Usart_Init()
{
UCSR1A = 0X00; 
UCSR1C |= (1 << UCSZ11) | (1 << UCSZ10);  //异步,数据格式8,N,1
      
UBRR1L = (F_CPU / BAUD / 16 - 1) % 256;    //波特率设置
UBRR1H = (F_CPU / BAUD / 16 - 1) / 256;  
UCSR1B |= (1 << RXCIE1) | (1 << RXEN1) | (1 << TXEN1);    //发送使能

}
//字节发送函数
void Usart_PutChar(unsigned char cTXData)
{
while( !(UCSR1A & (1 << UDRE1)) );  //只有数据寄存器为空时才能发送数据
UDR1 = cTXData;                  //发送数据送USART I/O数据寄存器-UDR
}
//接收中断函数
ISR(USART1_RX_vect)
{
unsigned char Rev;
Rev = UDR1;              //从USART I/O数据寄存器-UDR中读出数据
Usart_PutChar(Rev);    //将接收到的数据发送
}

void Usart_PutString(unsigned char *pcString)
{
while (*pcString)
{
  Usart_PutChar(*pcString++);

}
//DS18B20初始化
unsigned char DS18B20_Init()

SET_OUT;   //PA2设置为输出口(相当于拉低数据线上的电平) 

Delayus(490);  //延时大于480us

SET_IN;     //输入 释放数据线(相当于拉高数据线上的电平)

Delayus(68); //延时大于60US,
  
//while(DQ_IN);     //可以用两个while()死循环来判断复位是否成功,当数据线被拉低,说明
//while(!(DQ_IN));  //18b20开始复位应答,当数据线变高,说明应答完毕

if(DQ_IN)   //判断DS18B20是否拉低数据线
{
  OK_Flag = 0;  // 数据线是高?复位失败
}
else
{
  OK_Flag = 1; // 数据线是低?复位成功
}
Delayus(422); //有复位应答信号后,应当再延时一段时间(480-68),以等待应答完毕

return OK_Flag;    //返回复位标志
}
//从DS18B20读取一个字节数据
unsigned char Read_18b20()
{
unsigned char i;   
unsigned char dat = 0;   // dat用于存储读到的数据,先清零 

for(i = 0;i < 8;i++)   //共读8位数据,构成一个字节
{  
  SET_OUT;    //定义为输出(拉低数据线)
  
  Delayus(2);   //拉低2微秒  
  
  SET_IN;        //定义成输入,读入数据(同时也相当于拉高数据线)
   
  Delayus(4);        //延时
  dat = dat >> 1;        //数据右移,读顺序:先低后高
  if(DQ_IN)       //读数据,
  {   
   dat |= 0x80;   //如果是高,置1,右移数据
  }
  Delayus(62);   //延时大于60us

return dat;     //返回读到的1字节数据
}
//向DS18B20写1字节数据
void Write_18b20(unsigned char dat)
{
unsigned char i; 

for(i = 0;i < 8;i++)  //写8次,一次写1位,先写低字节
{
  SET_OUT;         //拉低数据线2us,开始写数据
  Delayus(2);      //
  
  if(dat & 0x01)   //写数据
  {
   SET_IN;    //写1   
  }
  else
  {
   SET_OUT;   //写0   
  }
  dat >>= 1;      //数据右移1位,先写低位
  Delayus(62);       //延时大于60us 
   
  SET_IN;          //拉高数据线
  Delayus(2);   //写两位数据的时间间隔
  

}
//us级别的延时函数
void Delayus(unsigned int lus)
{
while(lus--)
{
  _delay_loop_2(4);      //_delay_loop_2(1)是延时4个时钟周期,参数为3则延时12
             //个时钟周期,本实验用12M晶体,则12个时钟周期为12/12=1us
    }
}
//ms级别的延时函数
void Delayms(unsigned int lms)
{
while(lms--)
{
  Delayus(1000);        //延时1ms
    }
}

关键字:AVR单片机  读取DS18B20  温度上传  串口程序 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic477944.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:avr单片机+RFID的门禁系统
下一篇:ATmeg16单片机+LCD12864温度检测显示程序(并行控制,不带字库)

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

AVR单片机红外遥控键值解码实验
AVR学习笔记十八、红外遥控键值解码实验  18.1 实例功能 红外线遥控是目前使用最广泛的一种通信和遥控手段。由于红外线遥控装置具有体积小、功耗低、功能强、成本低等特点,因而,继彩电、录像机之后,在录音机、音响设备、空凋机以及玩具等其它小型电器装置上也纷纷采用红外线遥控。工业设备中,在高压、辐射、有毒气体、粉尘等环境下,采用红外线遥控不仅完全可靠而且能有效地隔离电气干扰。 在这个实验中,我们采用红外线遥控器和一体化红外接收头来进行红外遥控键值解码的实验,本实例分为三个功能模块,分别描述如下: ● 单片机系统:利用 ATmega16单片机与一体化红外接收器组成红外接收电路。 
发表于 2019-11-11
AVR单片机红外遥控键值解码实验
AVR单片机跑马灯的仿真设计
简易的跑马灯设计。基于AVR单片机仿真原理图如下:单片机源程序如下:/********************************************************************                            汇诚科技*********************************************************************/#include <iom16v.h>
发表于 2019-11-11
AVR单片机跑马灯的仿真设计
关于AVR单片机,你了解多少?
什么是AVR单片机?AVR单片机有什么优点?为什么要选择AVR单片机?AVR单片机是ATMEL公司研制开发的一种新型单片机,它与51单片机、PIC单片机相比具有一系列的优点:1:在相同的系统时钟下AVR运行速度最快;2: 芯片内部的Flsah、EEPROM、SRAM容量较大;3:所有型号的Flash、EEPROM都可以反复烧写、全部支持在线编程烧写(ISP);4:多种频率的内部RC振荡器、上电自动复位、看门狗、启动延时等功能,零外围电路也可以工作;5:每个IO口都可以以推换驱动的方式输出高、低电平,驱动能力强;6:内部资源丰富,一般都集成AD、DA模数器;PWM;SPI、USART、TWI、I2C通信口;丰富的中断源等。目前支持
发表于 2019-11-09
AVR单片机经典使用经验
AVR具有上手入门快,开发方便简单的特点,但要充分体会和发挥AVR的优点,还需要应用工程师本身的硬软件设计开发能力的不断学习、实践提高。AVR与传统类型的单片机相比,除了必须能实现原来的一些基本的功能,其在结构体系、功能部件、性能和可靠性等多方面有很大的提高和改善。功能越好的器件,需要具备更高技术和能力的人来使用和驾驭它。就象一部好的F1赛车,只有具备高超技术的驾驶员才能充分体会到车的特点,并能最大限度的发挥出车的性能。“外行看热闹,内行看门道”,对于有一定基础的嵌入式和单片机系统设计开发的工程师,不妨先简单尝试一下AVR。开发环境与工具:PC+下载线+实际的系统板PC上的开发软件:AVR Studio(Free)汇编+汇编调试
发表于 2019-11-09
AVR单片机经典使用经验
avr单片机八位流水灯程序
八位流水灯程序单片机源程序如下:#include<iom16v.h>#define uint unsigned int#define uchar unsigned charvoid Delay_ms(uint k){         uint i,j;         for(;k>0;k--)                 for(i=142;i>0;i--)       
发表于 2019-11-08
avr单片机可演奏的电子琴仿真加源码
单片机电子琴仿真原理图如下avr单片机源程序如下://-----------------------------------------------------------------//  名称: 电子琴仿真//-----------------------------------------------------------------//  说明: 本例在键盘矩阵上模拟演奏电子琴,数码管显示键号.//        按下不同按键时将输出不同频率音符,按键长按时发出长音,//        短按时发出短音
发表于 2019-11-08
avr单片机可演奏的电子琴仿真加源码
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved