AVR的DS18B20 温度采集示例程序(原发于2007-11-20)
来源:互联网 发布:seo博客资源 编辑:程序博客网 时间:2024/04/29 20:25
DS18B20 是 Dallas 的数字集成化温度采集芯片。其实早就想用用了。一直放在那里。最近朋友说调不出来,正好就看了一下,花了一天时间,看了数据手册,参考了一下别人的程序,写了一个测试程序。和大家一起分享。共同进步。
我用的是Mega128 , 接是的7.3728M的晶振,用了mega128的串口0。用PB2口与18B20连接.
程序在AVRStudio4.12sp4 + WinAVR20060421, Winxp环境下编译通过。
如果想要移到其他的AVR芯片上的话很简单,如下:
建义使用前看看DS18B20的英文手册,说得很清楚。中文的都是对DS1820来说明的。有些区别。
如果你想要了解 CRC 如何校验的,请参考 Maxim 的 AN27 应用手册(中文和英文都有)。呵呵。就说这么多了吧。下面是程序。
/*********************************************/
// DS18B20 温度采集示例程序
// 2007.11.20
// semilog
/*********************************************/
#include <avr/io.h> //引脚定义
#include <avr/interrupt.h> //中断服务宏
#include <util/delay.h> //延时的宏
#include <stdint.h> //数据类型宏
#include <avr/eeprom.h> //EEPROM存储器操作的宏
#include <stdlib.h>
#include <avr/pgmspace.h>
//××××××××××××引脚宏定义×××××××××××××
#define setbit(var, bit) ((var) |= (1 << (bit))) //把某一位置1
#define clrbit(var, bit) ((var) &=~(1 << (bit))) //把某一位清0
//18B20定义
#define SET_DQ (PORTB) |= (1 << (PB2)) // 18b20 高电平
#define CLR_DQ (PORTB) &=~(1 << (PB2)) // 18b20 低电平
#define DQ_IN (PINB)&(1<<(PB2)) // 18b20信号输入
#define SET_OUT (DDRB)|= (1<<(PB2)) //PB2定义成输出
#define SET_IN (DDRB)&=~(1<<(PB2)) //PB2定义成输入
/***********************变量定义***************************/
uint8_t u_flag=0;
// DS18B20 温度采集示例程序
// 2007.11.20
// semilog
/*********************************************/
#include <avr/io.h> //引脚定义
#include <avr/interrupt.h> //中断服务宏
#include <util/delay.h> //延时的宏
#include <stdint.h> //数据类型宏
#include <avr/eeprom.h> //EEPROM存储器操作的宏
#include <stdlib.h>
#include <avr/pgmspace.h>
//××××××××××××引脚宏定义×××××××××××××
#define setbit(var, bit) ((var) |= (1 << (bit))) //把某一位置1
#define clrbit(var, bit) ((var) &=~(1 << (bit))) //把某一位清0
//18B20定义
#define SET_DQ (PORTB) |= (1 << (PB2)) // 18b20 高电平
#define CLR_DQ (PORTB) &=~(1 << (PB2)) // 18b20 低电平
#define DQ_IN (PINB)&(1<<(PB2)) // 18b20信号输入
#define SET_OUT (DDRB)|= (1<<(PB2)) //PB2定义成输出
#define SET_IN (DDRB)&=~(1<<(PB2)) //PB2定义成输入
/***********************变量定义***************************/
uint8_t u_flag=0;
prog_uint8_t CRC_Code[256]= {
0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53
}; //定义256位CRC 校验码在 code 程序区
//××××××××××××函数申明×××××××××××××
void USART_init(void); //串口初始化
void INT_Init(void); //中断初级化
void Send_uint8_t(uint8_t dat); //发送一个字节
void Send_str(uint8_t *str); //发送字符串
uint8_t Init_18b20(void); //18b20初始化
uint8_t read_18b20(void); //读18b20温度
void write_18b20(uint8_t dat); //写18b20温度
/****************主程序***********************/
int main(void)
{
uint32_t temp;
uint8_t i,temp_l,temp_h,a,b,c,d,temp_flag;
uint8_t rom64[8],scr_pad[9];
uint8_t crc_temp;
USART_init();
INT_Init();
crc_temp=0;
temp_flag=0;
Init_18b20(); //初始化,然后读出温度值
write_18b20(0xCC); //发送ROM命令,不进行匹配
write_18b20(0x4E); //发送功能命令,写配置寄存器
write_18b20(0x02); // TH
write_18b20(0x80); // TL
write_18b20(0x7F); // Config :0x1F:9位, 0x3F:10位 ,0x5F:11位 ,0x7F:12位
// 所需时间: 93.75ms 187.75ms 375ms 750ms
Init_18b20(); //初始化,然后读出温度值
write_18b20(0x33); //发送ROM命令,读64-bit ROM 值
for(i=0; i<8; i++)
{
rom64[i]=read_18b20();
}
/*
for(i=0;i<8;i++) //查看ROM值, DS18b20的型号代码:28H
{
Send_uint8_t(rom64[i]);
}
*/
crc_temp = pgm_read_byte_near(&CRC_Code[rom64[0]]); //算第一个CRC码
for(i=1; i<7; i++) /*后面的CRC码:I = (当前CRC) EXOR (输入字)*/
{
crc_temp = pgm_read_byte_near(&CRC_Code[rom64[i]^crc_temp]);
}
if(crc_temp == rom64[7])
Send_str("ROM CRC较验成功");
else
Send_str("ROM CRC较验失败");
Send_uint8_t(0x0D);
Send_uint8_t(0x0A);
while(1)
{
nit_18b20(); //初始化18b20
write_18b20(0xCC); //发送ROM命令,不进行匹配
write_18b20(0x44); //启动18B20进行转换
for(i=0; i<50; i++) //延时等转换完成
{
_delay_ms(20);
}
Init_18b20(); //初始化,然后读出温度值
write_18b20(0xCC); //发送ROM命令,不进行匹配
write_18b20(0xBE); //发送功能命令,读出暂存寄存器中内容
for(i=0; i<9; i++)
{
scr_pad[i]=read_18b20(); //读出9位scratchpad 的值
}
//----------下面校验读出的值是否正确---------------
crc_temp = pgm_read_byte_near(&CRC_Code[scr_pad[0]]); //选算第一个CRC码
for(i=1; i<8; i++)
{
crc_temp = pgm_read_byte_near(&CRC_Code[scr_pad[i]^crc_temp]);
}
if( crc_temp==scr_pad[8] ) //如果结果正确则显示
{
if(scr_pad[1]&0x08)
{
scr_pad[1]=~scr_pad[1];
scr_pad[0]=~scr_pad[0];
SREG=SREG&(~(1<<SREG_C)); //清零 C 进位
scr_pad[0]++;
if(SREG&(1<<SREG_C)) //如果有进位,则高位加1
scr_pad[1]++;
}
temp = scr_pad[1];
temp = (temp << 8) + scr_pad[0];
temp = (temp*625)/1000; //如果直接乘0.625的话,因为用到浮点数,
//代码会曾加很多
a = temp/1000 +0x30;
b = (temp%1000)/100 +0x30;
c = (temp%100)/10 +0x30;
d = temp%10 + 0x30;
Send_str("当前温度:");
if(temp_flag) //发送温度符号
Send_uint8_t('-');
else
Send_uint8_t(' ');
if(a>0x30)
Send_uint8_t(a);
if((a!=0x30)|(b!=0x30))
Send_uint8_t(b);
Send_uint8_t(c);
Send_uint8_t('.');
Send_uint8_t(d);
}
else //结果不正确则提示错误
{
Send_str("发生错误,读出的结果不正确");
}
Send_uint8_t(0x0D);
Send_uint8_t(0x0A);
}
return(0);
}
//××××××××××××MCU初始化×××××××××××××
void USART_init(void) //初始化串口
{
UBRR0H=0;
UBRR0L=47; //设置波特率为9600,(使用外部7.3728M晶振)
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00); //8位数据,1位停止位,无校验
UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0); //接收使能,发送使能, 接收中断使能
}
void INT_Init(void) //中断初级化
{
EICRA = (1<<ISC01)|(1<<ISC11); //INT0 INT1 的中断触发方式为下降沿触发
EIMSK = (1<<INT1)|(1<<INT0); //开中断INT0 INT1
sei(); //全局中断使能
}
/****************** DS18b20操作 **************************/
uint8_t Init_18b20(void) //18b20初始化
{
uint8_t flg,i;
SET_OUT;
CLR_DQ;
for(i=0; i<10; i++) //拉低 500us
{
_delay_us(50);
}
SET_IN; //输入 释放
_delay_us(80);
if(DQ_IN) //等待回复
flg = 0;
else
flg = 1; //0表示初始化成功
for(i=0; i<4; i++) //回复的低电平在60到240US
{
_delay_us(60);
}
SET_OUT;
SET_DQ; //回到初始DQ=1;
return flg;
}
//-------------- 写18b20温度 --------------------
void write_18b20(uint8_t dat) //写18b20温度
{
uint8_t i;
SET_OUT; //控制脚定义成输出
for(i=0; i<8; i++)
{
CLR_DQ;
_delay_us(5);
if(dat&1) //写数据,从低位开始
{
SET_DQ; // bit=1
}
else
{
CLR_DQ; // bit=0
}
_delay_us(60); // wait for 60us ,total > 60us
SET_DQ; //再次拉高
delay_us(10); //写两个位之间的间隔
dat>>=1;
}
SET_DQ;
}
//--------------- 读18b20温度 -------------------
uint8_t read_18b20(void) //读18b20温度
{
uint8_t i, dat=0; // dat用于存储读到的数据
SET_OUT; //第一次拉低,设置引脚为输出
for(i=0; i<8; i++)
{
dat>>=1;
CLR_DQ;
_delay_us(5); //拉低5微秒
SET_IN; //定义成输入,读入状态
_delay_us(5); //等18b20响应
if(DQ_IN) //读状态,放入dat中
{
dat |=0x80; //放到最高位,左移
}
_delay_us(80); //wait for 60~120us
SET_DQ;
SET_OUT; //再次定义成输出
}
return dat;
}
/*******************串口操作***********************/
void Send_uint8_t(uint8_t dat) //发送一个字节
{
while(!(UCSR0A&(1<<UDRE0)));
UDR0= dat;
}
void Send_str(uint8_t * str) //发送字符串
{
while(*str!=0)
{
Send_uint8_t(*str);
str++;
}
}
//××××××××××××中断服务程序×××××××××××××
ISR(USART0_RX_vect) // USRAT0 接收中断服务子程序
{
uint8_t dat;
dat = UDR0;
if(dat=='A') u_flag=0;
if(dat=='B') u_flag=1;
if(dat=='C') u_flag=2;
}
//程序完
- AVR的DS18B20 温度采集示例程序(原发于2007-11-20)
- AVR-GCC Makefile 中文翻译并加上我的理解(原发于:2007-11-20)
- avr-gcc中关于delay延时函数的应用(原发于2007-11-16)
- 基于STM32与DS18B20的温度采集
- arm力天电子 lpc2148 基于DS18b20的温度采集实验程序详解
- DS18B20的程序(温度测量芯片)
- 基于DS18B20和LabVIEW的多路温度采集系统
- 在PC104下实现的DS18B20温度采集
- 嵌入式系统中volatile 的使用的意义(原发于2007-11-7)
- DS18B20的温度测量
- PIC16F877A驱动DS18B20温度采集芯片
- 嵌入式采集温度DS18B20-platform驱动
- 1wire总线的应用-DS18B20温度采集工芯片的应用.
- 基于51单片机多路温度采集系统 采用读取ds18b20的序列号进行测量
- S3C6410 DS18B20温度传感器驱动(四) --- 读取温度的应用程序
- Tcar:智能车之ds18b20温度传感器实现温度采集模块
- arduino + esp8266+ ds18b20 采集温度上传贝壳网
- Delphi中关于OleVariant 自动化变量的一点小小的认识(原发于2007-6-13)
- 一个靠谱的开源人脸标注训练识别程序
- 用eclipse编写mapreduce程序
- 需要证书
- 嵌入式系统中volatile 的使用的意义(原发于2007-11-7)
- IFRAME中SESSION无法保留
- AVR的DS18B20 温度采集示例程序(原发于2007-11-20)
- 稀疏表达:向量、矩阵与张量(上)
- 不能说のsecret 7
- QT下QTableWidget使用方法小结
- KMP(转载来自Matrix67原创)
- 防止内存泄露的几个良好的编码习惯
- HDU 4363 Draw and paint (DP)
- Android 数据存储
- 优先级队列几个应用详解