单片机
返回首页

基于WinAVR的DS18B20源程序

2016-01-06 来源:eefocus

#ifndef _DS18B20_C_

#define _DS18B20_C_


#define DQ_18B20 (1<<3) // PD3
#define DQ_TO_0() (DDRD |= DQ_18B20) // PD3=’0′
#define DQ_TO_1() (DDRD &= ~DQ_18B20) // PD3=’float’
#define DQ_status() (PIND & DQ_18B20) // read PD3 pin


#ifndef CPU_CRYSTAL
#define CPU_CRYSTAL (11.0592)
#endif


#define wait_us(us)
_delay_loop_2((INT16U)((us)*CPU_CRYSTAL/4))


// 1个初始化模块
void ds18b20_config(void); // 配置端口

// 3个基本模块
BOOL ds18b20_reset(void); // 复位DS18B20
void ds18b20_write(INT8U dat); // 写字节到DS18B20
INT8U ds18b20_read(void); // 读字节从DS18B20

// 2个应用模块
void convert_T(void); // 启动温度转换
INT16U read_T(void); // 读取转换值


void ds18b20_config(void)
{
DDRD &= ~DQ_18B20; // 输入模式(上电时为高电平)
PORTD &= ~DQ_18B20; // 输出锁存器写0,以后不再更改
}


BOOL ds18b20_reset(void)
{
BOOL bus_flag;

DQ_TO_0(); // 设置1-wire总线为低电平(占领总线)…


wait_us(490); // 490us

cli(); // 下面这段时间要求比较严格,为保险起见,关中断
DQ_TO_1(); // 设置1-wire总线为高电平(释放总线)


wait_us(67.5); // 最佳时间: 60us+7.5us!(忙延时,只是一种策略)

// 探测总线上是否有器件
if(DQ_status()) bus_flag=FAIL; // 复位单总线但没有发现有器件在线
else bus_flag=SUCC; // 复位单总线并发现有器件在线

sei(); // 退出临界代码区(开中断)


wait_us(490-67.5); // 490-67.5us

return(bus_flag);
}


void ds18b20_write(INT8U dat)
{
INT8U count;

// 每个字节共8位,一次发一位
for(count=0; count<8; count++) {
cli(); // 保证绝对不会发生中断!
DQ_TO_0(); // 设置1-wire总线为低电平
wait_us(2); // about 2us

if(dat&0×01) DQ_TO_1(); // 并串转换,先低位后高位
else DQ_TO_0();
dat >>= 1; // 下一位做好准备

// 60us~120us(实际不能到120us, 因为其它语句也用时间了!)
wait_us(62); // 62us

DQ_TO_1();
sei(); // 恢复系统中断
wait_us(2); // 2us
}
}


INT8U ds18b20_read(void)
{
INT8U count,dat;

dat = 0×00; // 数据接收准备

// 每个字节共8位,一次收一位
for(count=0; count<8; count++) {
cli(); // 保证绝对不会发生中断!

// 从总线拉低到读总线状态,不能大于15us!
DQ_TO_0(); // 设置1-wire总线为低电平(拉低总线以同步)
wait_us(2); // 2us
DQ_TO_1(); // 设置1-wire总线为高电平(释放总线)
wait_us(4); // 4us
dat >>= 1;
if(DQ_status()) dat|=0×80; // 读取总线电平,先收低位再收高位

sei(); // 恢复系统中断
wait_us(62); // 必须大于60us
}
return(dat);
}


void convert_T(void)
{
if(ds18b20_reset()==SUCC) { // 如果复位成功
ds18b20_write(0xcc); // 跳过多器件识别
ds18b20_write(0×44); // 启动温度转换
}
}


INT16U read_T(void)
{
INT16U value=0;

if(ds18b20_reset()==SUCC) { // 如果复位成功
ds18b20_write(0xcc); // 跳过多器件识别
ds18b20_write(0xbe); // 读暂存器
value = (INT16U)ds18b20_read(); // 低字节
value += (INT16U)(ds18b20_read())<<8; // 高字节
}
return(value);
}

#endif

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • CCD图像传感器在微光电视系统中的应用

  • 一个简单的警笛电路图

  • 基于IC555的可变PWM振荡器电路

  • 优化电路板布局的简单方法

  • 如何使用LED驱动器LM3915制作振动计

  • 使用NE555和磁簧开关的橱柜照明电路

    相关电子头条文章