⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ʦ

📁 18b20的仿真实例
💻
字号:
//1602液晶显示程序,1602LCD的R/W读写端接地, 即始终只写, 不读数据
  //使用1602LCD显示DS18B20转换的温度值
  #include <reg52.H>
  #include <intrins.H>
  #include <math.H>
  
  #define uchar unsigned char
  #define uint unsigned int
  
 
 sbit RS = P2^1;    //数据/命令选择端(H/L)
 sbit LCDEN = P2^2; //使能端
 
 void delayUs()        //短延时
 {
     _nop_();
 }
 
 void delayMs(uint a)      //长延时
 {
     uint i, j;
     for(i = a; i > 0; i--)
        for(j = 100; j > 0; j--);
 }
 
 //第一行开始地址为0x80, 第二行开始地址为0xc0;
 //写命令:RS=0, RW=0;
 void writeComm(uchar comm)
 {
     RS = 0;    
     P1 = comm;
   LCDEN = 1;
     delayUs();
     LCDEN = 0;
     delayMs(1);
 }
 
 //写数据:RS=1, RW=0;
 void writeData(uchar dat)
{
     RS = 1;
     P1 = dat;
     LCDEN = 1;
     delayUs();
     LCDEN = 0;
     delayMs(1);
 }
 
 //初始化
 //显示模式, 固定指令为00111000=0x38, 16*2显示, 5*7点阵,8位数据接口
 //显示开/关及光标设置00001100=0x0c
 //指令1: 00001DCB : D:开显示/关显示(H/L); C:显示光标/不显示(H/L), B:光标闪烁/不闪烁(H/L)
 //指令2: 000001NS :
 //N=1, 当读/写一个字符后地址指针加1, 且光标也加1; N=0则相反
 //S=1, 当写一个字符, 整屏显示左移(N=1)或右移(N=0), 但光标不移动; S=0, 整屏不移动
 void init()
 {
 
     writeComm(0x38); //显示模式
     writeComm(0x0c); //开显示, 关光标
     writeComm(0x06); //写字符后地址加1, 光标加1
     writeComm(0x01); //清屏
 }
 
 void writeString(uchar * str, uchar length)
 {
     uchar i;
     for(i = 0; i < length; i++)
     {
         writeData(str[i]);
     }
 }
 
 /**//*****************************DS18B20*******************************/
 sbit ds = P3^7;
 //初始化DS18B20
 //让DS18B20一段相对长时间低电平, 然后一段相对非常短时间高电平, 即可启动
 void dsInit()
 {
     //对于11.0592MHz时钟, unsigned int型的i, 作一个i++操作的时间大于为8us
     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应答
    delayMs(1);    //延时1ms, 因为DS18B20会拉低DQ 60~240us作为应答信号
    writeByte(0xcc); //写入跳过序列号命令字 Skip Rom
    writeByte(0x44); //写入温度转换命令字 Convert T
}

//向DS18B20发送读取数据命令
void sendReadCmd()
{
    dsInit();
    dsWait();
    delayMs(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倍, 使显示时可显示小数点后两位, 并对小数点后第三进行4舍5入
    //如t=11.0625, 进行计数后, 得到value = 1106, 即11.06 度
    //如t=-11.0625, 进行计数后, 得到value = -1106, 即-11.06 度
    value = t * 100 + (value > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5
    return value;
}

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;
    writeComm(0xc0+3);
    if(v < 0)
    {
        writeString("- ", 2);
    }
    else
    {
        writeString("+ ", 2);
    }
    if(datas[0] != 0)
    {
        writeData('0'+datas[0]);
    }
    for(count = 1; count != 5; count++)
    {
        writeData('0'+datas[count]);
        if(count == 2)
        {
            writeData('.');
        }
    }
}
/**//*****************************DS18B20*******************************/

void main()
{
    
    uchar table[] = "Now Temperature:";
    delayMs(1);

    sendChangeCmd();
    init();
    writeComm(0x80);
    writeString(table, 16);
    while(1)
    {
        delayMs(1000); //温度转换时间需要750ms以上
        writeComm(0xc0);
        display(getTmpValue());
        sendChangeCmd();
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -