代码中的教程!如有错误,请指正
wdqd.c
/*这个是官方比赛时会给出的底层驱动,比赛时可以根据自己的写法补充*/ /*#include "reg52.h"
sbit DQ = P1^4; ///单总线接口
///单总线延迟函数 void Delay_OneWire(unsigned int t) //STC89C52RC { while(t--); }
//通过单总线向DS18B20写一个字节 void Write_DS18B20(unsigned char dat) { unsigned char i; for(i=0;i<8;i ) { DQ = 0; DQ = dat&0x01; Delay_OneWire(5); DQ = 1; dat >>= 1; } Delay_OneWire(5); }
//从DS18B读一个字节 unsigned char Read_DS18B20(void) { unsigned char i; unsigned char dat; for(i=0;i<8;i ) { DQ = 0; dat >>= 1; DQ = 1; if(DQ) { dat |= 0x80; } Delay_OneWire(5); } return dat; }
//DS18B20设备初始化 bit init_ds18b20(void) { bit initflag = 0; DQ = 1; Delay_OneWire(12); DQ = 0; Delay_OneWire(80); DQ = 1; Delay_OneWire(10); initflag = DQ; Delay_OneWire(5); return initflag; }*/ /*这是我补充的驱动代码仅供参考*/ /*DS18B20出厂时配置为12位,读取温度时读取16位,前5位为符号位,当前5位为1时,读取温度为负;当前5位为0时,读取温度为正。正时读取温度的方法是:将16进制数转换为10进制。负时读取温度的方法是:将16进制反后加1,再转换为10进制。例:0550H = 85 度,FC90H = -55 度。*/ #include "STC15F2K60S2.H"//建议用15的头文件代替,原来是reg52.h #include "wdqd.h"
void Delay_OneWire(unsigned int t);///一些非官方板使用劣质板ds18b20传感器,所以在最终使用之前,先声明延迟函数
sbit DQ = P1^四、//单总线接口
///单总线延迟函数
void Delay_OneWire(unsigned int t) { unsigned char i; while(t--){ for(i=0;i<12;i );//因为我们使用的是15的头文件,所以修改驱动,将延时增加11倍 } }
void Delay_us(void)///定义微秒延迟用于数据刷新 { unsigned char i;
i = 30; while (--i); }
///通过单总线DS18B20写一个字节 void Write_DS18B20(unsigned char dat) { unsigned char i; for(i=0;i<8;i ) { DQ = 0; DQ = dat&0x01; Delay_OneWire(5); DQ = 1; dat >>= 1; } Delay_OneWire(5);
} /*写操作 (1) 低电平0首先放置数据线。 (2) 延迟确定时间为15微秒。 (3) 按从低到高的顺序发送字节(一次只发送一个)。 (4) 延迟时间为45微秒。 (5) 将数据线拉到高电平。 (6) 重复(1)到(6)的操作,直到所有字节全部发送。 (7) 最后将数据线拉高。*/ //从DS18B读一个字节 unsigned char Read_DS18B20(void) { unsigned char i; unsigned char dat; for(i=0;i<8;i ) { DQ = 0; dat >>= 1; DQ = 1; Delay_us();//自己补充
if(DQ) { dat |= 0x80; } Delay_OneWire(5); } return dat; } /*读操作 (1)将数据线拉高1。 (2)延迟2微秒。 (3)将数据线拉低0 (4)延时3微秒。 (5)将数据线拉高“1”。 (6)延时5微秒。 (7)读数据线的状态得到1个状态位,并进行数据处理。 (8)延时60微秒。 */ //DS18B20初始化 bit init_ds18b20(void) { bit initflag = 0; DQ = 1; Delay_OneWire(12); DQ = 0;
Delay_OneWire(80); // 延时大于480us DQ = 1; Delay_OneWire(10); // 14 initflag = DQ; // initflag等于1初始化失败 Delay_OneWire(5); return initflag; } /*初始化 (1) 先将数据线置高电平“1”。 (2) 延时(该时间要求的不是很严格,但是尽可能的短一点) (3) 数据线拉到低电平“0”。 (4) 延时750微秒(该时间的时间范围可以从480到960微秒)。 (5) 数据线拉到高电平“1”。 (6) 延时等待(如果初始化成功则在15到60微秒时间之内产生一个由DS18B20所返回的低电平“0”。据该状态可以来确定它的存在,但是应注意不能无限的进行等待,不然会使程序进入死循环,所以要进行超时控制)。 (7) 若CPU读到了数据线上的低电平“0”后,还要做延时,其延时的时间从发出的高电平算起(第(5)步的时间算起)最少要480微秒。 (8) 将数据线再次拉高到高电平“1”后结束。 */ /*自己补充*/ //DS18B20温度采集程序:整数 unsigned int rd_temperature() { unsigned char L,H; init_ds18b20(); Write_DS18B20(0xcc);//跳过ROM指令 Write_DS18B20(0x44);//转换温度指令 Delay_OneWire(80); // 延时大于480us init_ds18b20(); Write_DS18B20(0xcc);//跳过ROM指令 Write_DS18B20(0xbe);//读温度指令
L = Read_DS18B20(); H = Read_DS18B20();
return (H<<8)+L; } //S:符号位 中7:整数 后4:小数 // 注:这段程序不唯一,个人习惯这样写,未经任何处理的原始数据(返回值为16位二进制数据) /*在主函数应用*/ //unsigned int T; //存放16位原始数据 //unsigned char T1,T2; //存放整数/小数 //T=rd_temperature(); //获取完整温度数据 //T1=T>>4&0x007f; //获取整数数据 //T2=T&0x000f*100/16; //获取小数 //最后通过取整取余显示
wdqd.h
#ifndef _WDQD_H #define _WDQD_H
//函数声明 全部声明 void Delay_OneWire(); void Delay_us(); void Write_DS18B20(); unsigned char Read_DS18B20(); bit init_ds18b20(); unsigned int rd_temperature(); #endif
main.c
#include <STC15F2K60S2.H> #include <intrins.h> #include <wdqd.h>
#define uc unsigned char #define ui unsigned int
ui temp; uc temp1,temp2;
uc code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff,0xc6};//0-9,-,关闭,C uc code tac[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; void hc138(uc n)//138译码器 { switch(n) { case 4:P2=(P2&0x1f)|0x80;break; case 5:P2=(P2&0x1f)|0xa0;break; case 6:P2=(P2&0x1f)|0xc0;break; case 7:P2=(P2&0x1f)|0xe0;break; } } void delay()//延时1毫秒 { unsigned char i, j;
_nop_(); _nop_(); _nop_(); i = 11; j = 190; do { while (--j); } while (--i); } void OutputSMG(uc gqb,uc yxl)//数码管输出函数 { hc138(6); P0=0x01<<yxl; hc138(7); P0=gqb; delay(); }
void OutputP0(uc add,uc dat)//输出函数 { hc138(add); P0=dat; } void Initsystem()//初始化 { OutputP0(4,0xff); OutputP0(5,0x00); OutputP0(6,0x00); OutputP0(7,0x00); } void SMGwd()//数码管功能温度 { temp=rd_temperature(); temp2=temp&0x000f;//获取小数 temp1=temp>>4;//获取整数 OutputSMG(tab[temp1/10],4); OutputSMG(tac[temp1%10],5); OutputSMG(tab[temp2/10],6); OutputSMG(tab[temp2%10],7); OutputSMG(tab[12],0); } void main()//主函数 { Initsystem(); rd_temperature(); while(1) { SMGwd(); }
}