立即注册 登录
返回首页

uid:261715的个人空间

日志

2017-12-18

已有 452 次阅读2017-12-18 15:22

;单片机DS18B20温度计C语言程序 (2008-09-27 17:01:06)

;标签:ds18b20c语言程序   

 

  #include<reg51.h>

  #include<intrins.h>

  #include <math.H>  //要用到取绝对值函数abs()

//通过DS18B20测试当前环境温度, 并通过数码管显示当前温度值, 目前显示范围: -55~ +125

  sbit wela = P2^7;  //数码管位选

  sbit dula = P2^6;  //数码管段选

  sbit ds = P2^2;

  int tempValue;

 

 //0-F数码管的编码(共阳极)

 unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,

    0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};

 //0-9数码管的编码(共阳极), 带小数点

 unsigned char code tableWidthDot[]={0x40, 0x79, 0x24, 0x30,

 

0x19, 0x12, 0x02,0x78, 0x00, 0x10};

 //延时函数, 对于11.0592MHz时钟, i=10,则大概延时10ms.

 void delay(unsigned int i)

 {

  unsigned int j;

   while(i--)

    {

        for(j = 0; j < 125; j++);

    }

 }

 

//初始化DS18B20

 //DS18B20一段相对长时间低电平, 然后一段相对非常短时间高电平, 即可启动

 void dsInit()

 {

   //对于11.0592MHz时钟, unsigned int型的i, 作一个i++操作的时间大于?us

   unsigned int i;

   ds = 0;

    i = 100;   //拉低约800us, 符合协议要求的480us以上

    while(i>0) i--;

    ds = 1;    //产生一个上升沿, 进入等待应答状态

     i = 4;

   while(i>0) i--;

 }

 

 void dsWait()

 {

     unsigned int i;

     while(ds);

    while(~ds);  //检测到应答脉冲

    i = 4;

    while(i > 0) i--;

}

 

//DS18B20读取一位数据

//读一位, DS18B20一小周期低电平, 然后两小周期高电平,

//之后DS18B20则会输出持续一段时间的一位数据

bit readBit()

{

    unsigned int i;

   bit b;

   ds = 0;

  i++;   //延时约8us, 符合协议要求至少保持1us

  ds = 1;

  i++; i++;  //延时约16us, 符合协议要求的至少延时15us以上

   b = ds;

    i = 8;

    while(i>0) i--;  //延时约64us, 符合读时隙不低于60us要求

   return b;

}

 

//读取一字节数据, 通过调用readBit()来实现

unsigned char readByte()

{

   unsigned int i;

     unsigned char j, dat;

    dat = 0;

   for(i=0; i<8; i++)

   {

        j = readBit();

       //最先读出的是最低位数据

       dat = (j << 7) | (dat >> 1);

    }

    return dat;

}

 

//DS18B20写入一字节数据

void writeByte(unsigned char dat)

{

 unsigned int i;

   unsigned char j;

    bit b;

  for(j = 0; j < 8; j++)

   {

       b = dat & 0x01;

       dat >>= 1;

       //"1", DQ拉低15us, 15us~60us内将DQ拉高, 即完成写1

        if(b)

       {

            ds = 0;

           i++; i++;  //拉低约16us, 符号要求15~60us

            ds = 1;  

           i = 8; while(i>0) i--;  //延时约64us, 符合写时隙不低于60us要求

       }

      else  //"0", DQ拉低60us~120us

           ds = 0;

            i = 8; while(i>0) i--;  //拉低约64us, 符号要求

            ds = 1;

           i++; i++;  //整个写0时隙过程已经超过60us, 这里就不用像写1那样, 再延时64us

     

    }

}

 

//DS18B20发送温度转换命令

void sendChangeCmd()

{

   dsInit();    //初始化DS18B20, 无论什么命令, 首先都要发起初始化

   dsWait();   //等待DS18B20应答

   delay(1);    //延时1ms, 因为DS18B20会拉低DQ 60~240us作为应答信号

    writeByte(0xcc); //写入跳过序列号命令字 Skip Rom

   writeByte(0x44); //写入温度转换命令字 Convert T

}

 

//DS18B20发送读取数据命令

void sendReadCmd()

{

   dsInit();

   dsWait();

   delay(1);

   writeByte(0xcc); //写入跳过序列号命令字 Skip Rom

   writeByte(0xbe); //写入读取数据令字 Read Scratchpad

}

 

//获取当前温度值

int getTmpValue()

{

    unsigned int tmpvalue;

   int value; //存放温度数值

  float t;

    unsigned char low, high;

   sendReadCmd();

    //连续读取两个字节数据

  low = readByte();

  high = readByte();

    //将高低两个字节合成一个整形变量

    //计算机中对于负数是利用补码来表示的

    //若是负值, 读取出来的数值是用补码表示的, 可直接赋值给int型的

 

value

    tmpvalue = high;

    tmpvalue <<= 8;

    tmpvalue |= low;

   value = tmpvalue;

 

    //使用DS18B20的默认分辨率12, 精确度为0.0625, 即读回数据的最低位代表0.0625

   t = value * 0.0625;

    //将它放大100, 使显示时可显示小数点后两位, 并对小数点后第三进行45

   //t=11.0625, 进行计数后, 得到value = 1106, 11.06

   //t=-11.0625, 进行计数后, 得到value = -1106, -11.06

    value = t * 100 + (value > 0 ? 0.5 : -0.5); //大于00.5, 小于00.5

   return value;

}

 

unsigned char const timeCount = 3; //动态扫描的时间间隔

//显示当前温度值, 精确到小数点后一位

//若先位选再段选, 由于IO口默认输出高电平, 所以当先位选会使数码管出现乱码

void display(int v)

{

    unsigned char count;

   unsigned char datas[] = {0, 0, 0, 0, 0};

   unsigned int tmp = abs(v);

    datas[0] = tmp / 10000;

   datas[1] = tmp % 10000 / 1000;

   datas[2] = tmp % 1000 / 100;

    datas[3] = tmp % 100 / 10;

    datas[4] = tmp % 10;

   if(v < 0)

    {

       //关位选, 去除对上一位的影响

       P0 = 0xff;

       wela = 1; //打开锁存, 给它一个下降沿量

       wela = 0;

       //段选

      P0 = 0x40; //显示"-"

       dula = 1;  //打开锁存, 给它一个下降沿量

      dula = 0;

 

       //位选

      P0 = 0xfe;

       wela = 1; //打开锁存, 给它一个下降沿量

        wela = 0;

      delay(timeCount);

    }

    for(count = 0; count != 5; count++)

    {

        //关位选, 去除对上一位的影响

       P0 = 0xff;

      wela = 1; //打开锁存, 给它一个下降沿量

       wela = 0;

        //段选

        if(count != 2)

      {

     

               P0 = table[datas[count]];  //显示数字

        }

       else

        {

            P0 = tableWidthDot[datas[count]]; //显示带小数点数字

       }

        dula = 1;  //打开锁存, 给它一个下降沿量

        dula = 0;

 

        //位选

        P0 = _crol_(0xfd, count); //选择第(count + 1) 个数码管

       wela = 1; //打开锁存, 给它一个下降沿量

       wela = 0;

       delay(timeCount);

    }

}

 

void main()

{

  unsigned char i;

 

   while(1)

    {

        //启动温度转换

       sendChangeCmd();

       //显示5

        for(i = 0; i < 40; i++)

        {

           display(tempValue);

     }

        tempValue = getTmpValue();

    }


路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

返回顶部