• 无所不为
    了解作者
  • C/C++
    开发工具
  • 3KB
    文件大小
  • rar
    文件格式
  • 0
    收藏次数
  • 10 积分
    下载积分
  • 0
    下载次数
  • 2021-01-09 06:08
    上传日期
读温度模块DS18B20(STC15Fxxxx)C语言程序
DS18B20.rar
  • DS18B20.c
    7.4KB
内容介绍
#define MAIN_Fosc 11059200L //定义主时钟 #include "STC15Fxxxx.H" #include <intrins.h> /* use _nop_() function */ #define OUT 0 #define IN 1 u16 qqq; u16 temp=0; // 定义一个变量,存储温度值 sbit DQ=P1^6; unsigned char xdata temp_data[2]={0x00,0x00};//读出温度暂放 char xdata Dis_play[8]={0,0,0,0,0,0,0,0}; /****************************/ void delayus(u16 us) { u16 i; for(i=0;i<(us);i++){ } } /******************************************************************************************* 一、初始化 在初始化序列期间,总线控制器拉低总线并保持480us(改延时可以在480~960us之间,但需要在480us以内释放总线) 以发出一个复位脉冲,然后释放总线,进入接收状态(等待DS18B20应答)。总线释放后,单总线由上拉电阻拉到高电平。 当DS18B20探测到I/O引脚上的上升沿后,等待15-60us,然后其以拉低总线60-240us的方式发出存在脉冲。至此,初始化时序完毕。   DS18B20的时序及代码解析   初始化代码,初始化代码写至此,其实我们便可以用数码管显示来检验初始化是否成功(即DS18B20有应答), 数码管显示”0“,初始化失败,显示”1“,则初始化成功。 **********************************************************************************************/ u8 DS18B20_init(void) { u8 ack=1; DQ=0;//主机拉低总线 delayus(395);//延时495us DQ=1;//释放总线,同时IO口产生的上升沿能被DS18B20所检测到 delayus(50); //延时大于60us,确保接下来DS18B20能发出60~240us的存在脉冲应答 //在此60~240us之内DQ被DS18B20所占用,若存在,则其会发送一个低电平信号, //DQ被DS18B20拉低,则ack为0,反之为1 ack=DQ; delayus(140);//延时达240us,让DS18B20释放总线 DQ=1; return ack; } /************************************************************************************************** 二、DS18B20的写时序   主机在写时隙向DS18B20写入数据,其中分为写”0”时隙,和写”1”时隙。总线主机使用写“1”时间隙向DS18B20写入逻辑1, 使用写“0”时间隙向DS18B20写入逻辑0.所有的写时隙必须有最少60us的持续时间,相邻两个写时隙必须要有最少1us的恢复时间。 两种写时隙都通过主机拉低总线产生(见下图)为了产生写1时隙。在拉低总线后主机必须在15μs内释放总线。在总线被释放后, 由于上拉电阻将总线恢复为高电平。为了产生写”0”时隙,在拉低总线后主机必须继续拉低总线以满足时隙持续时间的要求(至少60μs)。   在主机产生写时隙后,DS18B20会在其后的15~60us的一个时间段内采样单总线(DQ)。在采样的时间窗口内,如果总线为高电平, 主机会向DS18B20写入1;如果总线为低电平,主机会向DS18B20写入0。   综上所述,所有的写时隙必须至少有60us的持续时间。相邻两个写时隙必须要有最少1us的恢复时间。所有的写时隙(写0和写1) 都由拉低总线产生。   DS18B20的时序及代码解析   DS18B20的写时序代码 :写字节函数、由低位至高位,向DS18B20写入一个字节的数据。无返回值,形参byte是待写入的字节数据, 读取8次,移位8次,保证每位都传输至DQ。 ****************************************************************************************************/ void DS18B20_write_byte(u8 byte) { u8 i; u8 j=0; for(i=0;i<8;i++) { DQ=0;//拉低总线,产生写时隙 //j++;//大于1us的延时 NOP2();//15us之内释放总线 DQ=1; // j++;//适当延时用 NOP2(); DQ=byte & 0x01;//将字节低位写入单总线 delayus(30);//在15~60us内等待DS18B20来采集信号 DQ=1;//释放总线 byte>>=1;//每次将要读取的数据位移至最低位, NOP2(); //if(j>16)j=0; } } /******************************************************************************************************** 三、DS18B20的读时序   主机发起读时序时,DS18B20仅被用来传输数据给控制器。因此,总线控制器在发出读暂存器指令[0xBE]或读电源 模式指令[0xB4]后必须立刻开始读时序,DS18B20可以提供请求信息。除此之外,总线控制器在发出发送温度转换指令[0x44] (或召回EEPROM指令[0xB8])之后读时序,详见DS18B20 的芯片手册上的功能指令。   所有读时序必须最少60us,包括两个读周期间至少1us的恢复时间。当总线控制器把数据线从高电平拉到低电平时, 读时序开始,数据线必须至少保持1us,然后总线被释放。DS18B20 通过拉高或拉低总线上来传输”1”或”0”。当传输逻辑”0”结束后, 总线将被释放,通过上拉电阻回到上升沿状态。从DS18B20输出的数据在读时序的下降沿出现后15us 内有效。因此, 总线控制器在读时序开始后必须停止把I/O口驱动为低电15us,以读取I/O口状态。   DS18B20的时序及代码解析   DS18B20的读时序的代码 :读字节函数、由低位至高位,读取DS18B20所采集到的数据。带返回值,可结合前面的写时序, 对写、读数据函数进行检验(后面会提到检验过程及效果)byte 是读取到的字节数据。其中,此函数读取8次,移位7次(实际移位8次)。 **********************************************************************************************************/ u8 DS18B20_read_write(void) { u8 i; u8 byte;//byte为要接收到的数据 u8 j=0; for(i=0;i<8;i++) { //产生读时序 DQ=0; // j++;//简单延时 NOP2(); DQ=1;//释放总线,有从机DS18B20占用 byte>>=1; //先进行移位 NOP2();//j++; if(DQ!=0)//让DS18B20占用总线,发出采集到的信号 byte |=0x80;//若DQ=1,则让当前byte最高位为1,在下次循环中移位至次高位,最后达到从低位到高位接收的目的; //若DQ=0,则可跳过此语句,直接在下次循环对byte 进行移位补0。以上操作15us以内完成 delayus(30);//延时60us DQ=1; NOP2(); //if(j>16)j=0; } return byte; } /*************************************************************** 启动一次 18B20 温度转换,返回值-表示是否启动成功 ****************************************************************/ u8 Start18B20(void) { u8 ack; ack = DS18B20_init(); //执行总线复位,并获取 18B20 应答 if (ack == 0){ //如 18B20 正确应答,则启动一次转换 DS18B20_write_byte(0xCC); //跳过 ROM 操作 DS18B20_write_byte(0x44); //启动一次温度转换 } return ack; //ack==0 表示操作成功 } /**************************************************************** 读取 DS18B20 转换的温度值,返回值-表示是否读取成功 ****************************************************************/ u8 Get18B20Temp(u16 *temp) { u8 ack; unsigned char LSB, MSB; //16bit 温度值的低字节和高字节 ack = DS18B20_init(); //执行总线复位,并获取 18B20 应答 if (ack == 0){ //如 18B20 正确应答,则读取温度值 DS18B20_write_byte(0xCC); //跳过 ROM 操作 DS18B20_write_byte(0xBE); //发送读命令 LSB = DS18B20_read_write(); //读温度值的低字节 MSB = DS18B20_read_write(); //读温度值的高字节 *temp = ((int)MSB << 8) + LSB; //合成为 16bit 整型数 } return ack; //ack==0 表示操作应 } /*************温度数据处理*****************/ void tem_deal(u16 tem) { fp32 t; t=tem; if(tem>6348) // 温度值正负判断 { tem=65536-tem; tem = tem*6.25; Dis_play[0]=tem/10000; //百位 Dis_play[1]=tem%10000/1000; //十位 Dis_play[2]=tem%1000/100; //个位 Dis_play[4]=tem%100/10; Dis_play[0]='-'; //负号 /* if(Dis_play[1]==0)Dis_play[0]=' '; else Dis_play[1]+=0x30; //十位 Dis_play[2]+=0x30; //个位 Dis_play[4]=Dis_play[3]+0x30; Dis_play[3]=0x2E; //小数点 Dis_play[5] =0xdf; Dis_play[6] ='C';*/ } else { tem = tem*6.25; //减去误差2度 Dis_play[0]=tem/10000; //百位 Dis_play[1]=tem%10000/1000; //十位 Dis_play[2]=tem%1000/100; //个位 Dis_play[3]=tem%100/10; /* if(Dis_play[0]==0)Dis_play[0]=' '; else Dis_play[0]+=0x30; //百位 if((Dis_play[0]==' ')&&(Dis_play[1]==0)){ Dis_play[1]=' '; }else Dis_play[1]+=0x30; //十位 Dis_play[2]+=0x30; Dis_play[4]=Dis_play[3]+0x30;//小数显示 Dis_play[3] ='.';//个位加小数点 Dis_play[5] =0xdf; Dis_play[6] ='C';*/ } } //////////////////////////////////////END///////////////////////////////
评论
    相关推荐