原创 CEPARK 51单片机DS18B20测试程序

2010-7-28 16:45 1696 9 9 分类: MCU/ 嵌入式
/**********************************************************************
* 文件名称: CEPARK 51 V2.0开发板
* 程序版本: V1.0
* 技术支持:http://bbs.cepark.com

*CEPARK 51实验板全套资料及其介绍!!!
http://bbs.cepark.com/viewthread.php?tid=34&fromuid=6136

* Cepark暑期51在线免费培训用程序---活动报名地址:
http://bbs.cepark.com/viewthread.php?tid=14228&fromuid=6136
**********************************************************************/
#include "STC89C51RC_RD_PLUS.H"

#define uchar unsigned char
#define uint unsigned int

uchar code C51BOX2[3] _at_ 0x43;   //仿真器用三字节空间

uchar code DispTab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
                      0x88,0x83,0xc6,0xa1,0x86,0x8e};    //段码0-9,a-f
uchar DispBuf[4];

uchar TempH,TempL;
uint Temp;
bit Presence;

sfr LedPort=0x80;       //P0口接段码
sbit Led0    =    P1^0; //LED控制脚
sbit Led1    =    P1^1;
sbit Led2    =    P1^2;
sbit Led3    =    P1^3;
sbit DataPort=P1^6;        //18B20的数据口

void uDelay(uchar DelayTime)          //延时子程序,入口参数每加1约加2us
{     while(--DelayTime);

}

void Hex2Bcd()    //HEX转BCD程序
{
    if(Presence==1)
        {  //如果没有检测到存在则显示“no”
        DispBuf[0]=0xab;
        DispBuf[1]=0xa3;
        DispBuf[2]=0xff;
        DispBuf[3]=0xff;
        }
    else
        {                        //分解后查表得到段码放入显示缓存
        Temp=TempH*256+TempL;      //数据合并成一个双字节数

        if((Temp>>12)==0xf)          //右移12位判断是否为负温度
            {Temp=0x10000-Temp;      //计算出负温度值
            DispBuf[0]=0xbf;}      //并将最左边数码管显示“-”号
        else DispBuf[0]=0xff;      //否则不显示

        TempH=Temp>>4;              //将小数点4位值移出后,得到整数部分放在TempH中
        Temp=(Temp&0x0f)*625;           //相与取出小数点四位,乘法得到小数点值
        DispBuf[3]=DispTab[Temp/1000];    //小数点位只取最高一位,后三位不显示

        DispBuf[2]=DispTab[TempH%10]&0x7f; //个位处理并点亮小数点
        TempH=TempH/10;     //取出百位、十位

        if(!TempH) DispBuf[1]=0xff;//百位和十位均为0则十位不显示。
            else DispBuf[1]=DispTab[TempH%10];

        if(DispBuf[0]==0xff)//正温度情况下
            {
            if(TempH/10) DispBuf[0]=DispTab[TempH/10];//百位有数值显示
            else DispBuf[0]=0xff;//为0不显示
            }
        }
}

void Display(uchar j)    //显示子程序
{
    for(;j>0;j--)
    {
        LedPort=DispBuf[0];
        Led0=0;
        uDelay(20);
        Led0=1;
        LedPort=DispBuf[1];
        Led1=0;
        uDelay(20);
        Led1=1;
        LedPort=DispBuf[2];
        Led2=0;
        uDelay(20);
        Led2=1;
        LedPort=DispBuf[3];
        Led3=0;
        uDelay(20);
        Led3=1;
    }
}

void Inti()
{
    DataPort=0;     //拉低
    uDelay(180);     //延时后拉高
    DataPort=1;
    uDelay(24);     //延时后读状态,如果存在,由18B20将端口拉低
    Presence=DataPort;//状态存入,用于后面显示判断
    uDelay(230);    //延时完成一周期时间
}

void WriteByte(uchar val)    //字节写入
{
 uchar i;
  for (i=8; i>0; i--)
  {
    DataPort = 0;
    uDelay(4);
    DataPort = val&0x01;
    uDelay(20);
    DataPort = 1;
    val=val/2;
  }
  uDelay(50);
}


uchar ReadByte()     //字节读取
{
uchar i;
uchar value=0;
    for (i=0;i<8;i++)//读入8字节
    {
        DataPort=0;    //拉低后再拉高,产生读间隙
        DataPort=1;
        uDelay(4); //延时后读入
        if(DataPort) value|=0x01<<i;
        uDelay(20); //延时完成一周期时间
    }
return (value);
}

void SetStep(uchar Dat)    //入口参数,1F-0.5度步进,3F-0.25度,5F-0.125度,7F-0.0625度
{
    Inti();
    WriteByte(0xcc);
    WriteByte(0x4e);
    WriteByte(0x15);  //写地址2—TH
    WriteByte(0x00);   //写地址3—TL
    WriteByte(Dat);  //地址4,保留区,用于小数后分辨率,1F,3F,5F,7F取值,值越大分辨率越高
    Inti();
    WriteByte(0xcc);
    WriteByte(0xbe);
    ReadByte();
    Inti();
    WriteByte(0xcc);
    WriteByte(0x48); //拷贝指令,发出后等6ms等待18B20将数据写入EEPROM,写结束再复位。
    uDelay(100);
    Inti();
    DataPort=1;
}

void GetTemp()       //温度获得子程序,返回值在TempH,TempL中
{
    Inti();                Display(8);//每执行一条指令补充显示,消除闪动
    WriteByte(0xcc);    Display(8);
    WriteByte(0x44);    Display(8);
    Inti();                Display(8);
    WriteByte(0xcc);    Display(8);
    WriteByte(0xbe);    Display(8);
    TempL=ReadByte();    Display(8);
    TempH=ReadByte();    Display(8);
}

void main(void)
{
    uDelay(100);
    Presence=1;
    SetStep(0x7f);
    GetTemp();Display(100); //发送第一个取温度指令后,要延时一段时间等待内部转换。(解决开机显示85度的问题。)
    while(1){GetTemp();Hex2Bcd();Display(50);}

}


PARTNER CONTENT

文章评论0条评论)

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