原创 ds18B20的c51程序

2008-4-11 09:23 6131 7 7 分类: MCU/ 嵌入式
下面是ds18b20的程序,ds18b20是dallas公司的1-wire温度传感器,本来程序并没有什么复杂的,但是由于1-wire最总线时序的要求非常严格,我去年调试的时候居然花了1个星期才搞定。我把代码贴在这里,供大家参考。不过还是提醒下,如果你用的mcu主频与我的不一样,则要小心调整里面的延迟等函数,使得满足1-wire的时序(我用的是11.0592MHZ)
//FileName:ds18b20.h
#ifndef __LZP_DS18B20_H_
#define __LZP_DS18B20_H_
#include "reg52.h"
sfr P4=0xe8;
sbit SPK=P4^0;

//命令定义
#define CONVERT        0x44
#define RDSCRATCH      0xbe
#define WRSCRATCH      0x4e
#define CPSCRATCH      0x48
#define RECALLE2       0xb8
#define RDPWR          0xb4
//ROM Function Command
#define RDROM          0x33
#define MATCHROM       0x55
#define SKIPROM        0xcc
#define SCROM          0xf0
#define ALARROM        0xec

sbit DS18B20_DQ=P4^1;

void write_command(unsigned char cmd);
unsigned char read_byte(void);

unsigned char reset_pulse(void);
void convert(void);
void get_temperature_data(unsigned char *temp);
void ds18b20_config();
 void read_ds18b20_id(unsigned char *id);
#endif

//FileName:ds18b20.c
///////////////////////////////////////////////////////////
//DS18B20基于DAllas公司的1-wire总线
//关于1-wire总线协议的具体内容,请参看ds18b20的datasheet
//另外www.maxim-ic.com.cn上有很多技术白皮书可以参考
//google上可以找到更多资料
//////////////////////////////////////////////////////////

#include "ds18b20.h"
#include "delay.h"
#include "intrins.h"
//初始化
unsigned char  reset_pulse(void)
{
    unsigned char flag=0;
    DS18B20_DQ=1;
    _nop_();
    DS18B20_DQ=0;
    //拉低约600us(必须在480us--960us之间)
    delay_us(40);
    DS18B20_DQ=1;
    //delay_us(2);
    delay_us(12);
    //检测DS18B20应答
//    while(DS18B20_DQ);
    //while(!DS18B20_DQ);
    //delay_us(1);
    if(DS18B20_DQ)
        flag=0;
    else
        flag=1;
    //DS18B20_DQ=1;
    return flag;
}

/*从ds18b20读一个字节
* ds18b20返回的数据是LSB的,即最低位先发,最高位最后发
*/
unsigned char read_byte(void)
{
    unsigned char i,j,tmp;
    tmp=0;
    //DS18B20_DQ=1;
    for(i=0;i<8;i++)
    {
        tmp>>=1;
        //j=read_bit();
        DS18B20_DQ=1;
    _nop_();
    _nop_();
    DS18B20_DQ=0;//产生一个下降沿,开始一个读time slot(时隙)
    //根据ds18b20的1-wire协议要求,必须延时至少1us
    _nop_();
    _nop_();
//    _nop_();
    //释放总线
    DS18B20_DQ=1;
    //根据ds18b20的1-wire协议要求,必须延时至少15us
    //这样读到的数据才有效
//    delay_us(2);
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
if(DS18B20_DQ)
        tmp|=0x80;
        delay_us(10);
    }
    return tmp;
   
}

void write_command(unsigned char cmd)
{
    unsigned char i;
   
    for(i=0;i<8;i++)
    {
        DS18B20_DQ=1;
        if(cmd&0x01)//write 1 time slot
        {
            DS18B20_DQ=0;//产生下降沿,开始一个write 1 time slot
            //_nop_();
            DS18B20_DQ=1;//释放总线
            //delay_40us(1);
            delay_us(5);//delay at least 60us
        }
        else{//write 0 time slot
            DS18B20_DQ=0;//产生下降沿,开始一个write 0 time slot
        //    delay_40us(1);
            delay_us(5);//保持最少60us
            DS18B20_DQ=1;
        }
        cmd>>=1;
    //    _nop_();
    }
    DS18B20_DQ=1;
}
//启动一次温度测量
void convert(void)
{
    reset_pulse();
    //delay_ms(1);
    write_command(SKIPROM);
    write_command(CONVERT);
    delay_ms(10);
    //while(!read_bit());
    //while(!DS18B20_DQ);//wait for convert complete
}

void get_temperature_data(unsigned char *temp)
{
    reset_pulse();
//    delay_ms(1);
    write_command(SKIPROM);
    write_command(RDSCRATCH);
    temp[0]=read_byte();//低字节
    temp[1]=read_byte();//高字节kqqe
    reset_pulse();//终止继续传输后续字节
}
void ds18b20_config(void)
{
    reset_pulse();
   
//    delay_ms(1);
    write_command(SKIPROM);
    write_command(WRSCRATCH);
    write_command(0x19);
    write_command(0x1a);
    write_command(0x7f);
    reset_pulse();
    write_command(SKIPROM);
    write_command(0x48);
    reset_pulse();
    write_command(SKIPROM);
    write_command(0xb8);
 }

 void read_ds18b20_id(unsigned char *id)
 {
     unsigned char i;
     reset_pulse();
    write_command(0x33);
    for(i=0;i<8;i++)
    {
        id=read_byte();
    }
}

//FileName:delay.h
#ifndef __LZP_DELAY_H_
#define __LZP_DELAY_H_
//sfr RCAP2L = 0xCA;
//sfr RCAP2H = 0xCB;
#define TRUE   1
#define FALSE   0
//设置波特率
#define OSC_FREQ                11059200L

#define BAUD_115200             256 - (OSC_FREQ/192L)/115200L   // 255
#define BAUD_57600              256 - (OSC_FREQ/192L)/57600L    // 254
#define BAUD_38400              256 - (OSC_FREQ/192L)/38400L    // 253
#define BAUD_28800              256 - (OSC_FREQ/192L)/28800L    // 252
#define BAUD_19200              256 - (OSC_FREQ/192L)/19200L    // 250
#define BAUD_14400              256 - (OSC_FREQ/192L)/14400L    // 248
#define BAUD_9600               256 - (OSC_FREQ/192L)/9600L     // 244
// Timer2
#define RCAP2_50us             65536L - OSC_FREQ/80000L
#define RCAP2_1ms              65536L - OSC_FREQ/4000L

void delay_ms(unsigned int num);
void delay_40us(unsigned char num);
void delay_us(unsigned char num);

#endif

//FileName:delay.c
#include "delay.h"
#include "reg52.h"


void delay_ms(unsigned int num)
{
     RCAP2H = (RCAP2_1ms>>8);
    RCAP2L=(RCAP2_1ms&0x00ff);
    TH2=(RCAP2_1ms>>8);;
    TL2=(RCAP2_1ms&0x00ff);;
   
      ET2 = 0;     // Disable timer2 interrupt
      T2CON = 0x04;    // 16-bit auto-reload, clear TF2, start timer
 
      while (num--)
      {
        while (!TF2);
        TF2 = FALSE;
      }
      TR2 = FALSE;
}

void delay_40us(unsigned char num)
{
    RCAP2H=(RCAP2_50us>>8);
    RCAP2L=(RCAP2_50us&0x00ff);
    TH2=(RCAP2_50us>>8);
    TL2=(RCAP2_50us&0x00ff);
    ET2=0;
    T2CON=0x04;
    while(num--)
    {
        while(!TF2)
            TF2=FALSE;
    }
    TR2=FALSE;
}

void delay_us(unsigned char num)
{
    unsigned char i;
    for (i=0;i<num;i++)
    {
    }
}

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
7
关闭 站长推荐上一条 /3 下一条