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

📄 ds18b20.c

📁 单片机c语言程序设计100例--基于PIC+PROTEUS
💻 C
字号:
//-----------------------------------------------------------------
//  名称: 多点DS18B20控制程序
//-----------------------------------------------------------------
#include <pic.h>
#include <string.h>
#include <stdio.h>
#include "DS18B20.h"
#include "LM044L.h"
//温度小数位对照表(不使用该表时,还可以通过计算法得到温度小数部分)
const INT8U df_Table[] = {0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9 };
INT8U  DS18B20_STATUS;                //器件状态,为0时在线,否则表示被拨出或无响应
INT8U  Temp_Value[2];                 //存放所读取的两字节温度数据
INT8U  ROMCODE[8];                    //存放搜索到的64位设备ROMCODE
INT8U  Level,Last_Level;              //当前分支点和上次搜索的最底层分支点
INT8U  DS_CNT;                        //搜索到的器件个数
INT8U  CRC;                           //校验变量
bit    bit_A,bit_B;                   //读ROMCODE的当前位原码与反码
bit    bj;                            //临时位变量  
extern INT8U LCD_Buffer[];            //液晶显示缓冲
float  Temp_i,Temp_f;                 //温度的整数与小数部分
//-----------------------------------------------------------------
// 延时nx100ms
//-----------------------------------------------------------------
void DelayX100ms(INT8U n)
{
   while (n--) __delay_ms(100);
}

//-----------------------------------------------------------------
// 从1-Wire总线读取1位
//-----------------------------------------------------------------
INT8U Read_Romcode_bit()
{    


}

//-----------------------------------------------------------------
// 搜索1-Wire总线上一只器件的64位ROMCODE
// 返回0表示搜索一个ROMCODE,否则表示无器件或搜索的ROMCODE最后校验出错
//-----------------------------------------------------------------
INT8U Search_ROM1()
{
   volatile INT8U i, j, k;
   RESET();                          //复位
   if (DS18B20_STATUS) return 0;     //无器件在线时返回
   Write_Byte(SERACH_ROM);           //发送ROM搜索命令
   for (i = 0; i < 64; i++)          //从0位开始索64位ROMCODE
   {  bit_A = Read_Romcode_bit();    //读取第i位的原码
      bit_B = Read_Romcode_bit();    //读取第i位的反码
      //---------------------------------------------------------11
      //读取的结果为"11"时,搜索结束,程序返回
      if (bit_A == 1 && bit_B == 1) return 1;
      //-----------------------------------------------------10或01
      //读取的结果为"10"或"01"时,表示所有从机的此位均为"0"或"1"
      //将此位保存到8字节共64位的数组ROMCODE中.
      //如果为0表示所有从机此位均为"0",故发送"0"使所有从机继续通信
      //如果为1表示所有从机此位均为"1",故发送"1"使所有从机继续通信
      else if (bit_A != bit_B) //两位为01或10
      {  



      }
      //---------------------------------------------------------00
      //读取的结果为"00"时,表示从机中此位同时有"0"与"1",在该层出现搜索分支
      else if (bit_A == 0 && bit_B == 0)
      {
         //"="=====================================================
         //当前搜索遇到的分支层位置等于前一搜索路径中最低的分支层位置
         if(i == Last_Level)
         {  



         }
         //">"=====================================================
         //当前搜索遇到的分支层低于前一趟搜索的最低分支层
         else if (i > Last_Level) 
         {  




         }
         //"<"=====================================================
         //当前搜索遇到的分支层高于上一次搜索的最低分支层
         //此时的“左右分支选择”决定于上一次ROMCODE搜索结果中的对应位
         else if (i < Last_Level)
         {  




         }
     } //完成1位搜索------------------------------------------------
   } //完成64位搜索-------------------------------------------------
   //对8字(64位)ROMCODE执行CRC8校验
   


   //CRC正确时返回0,否则返回1
   


}

//-----------------------------------------------------------------
// 转换并显示当前找到的器件的8字节(64位)ROMCODE
//-----------------------------------------------------------------
void Show_Romcode(INT8U r, INT8U c,INT8U *RID)
{
   INT8U i;  char buf[3]; 
   for (i = 0; i < 8; i++) //读取8字节(64位)光刻码,从低字节开始读取
   {  sprintf(buf,"%02X",ROMCODE[i]); //将当前字节转换为十六进制字符串
      //将各字节转换后的两个十六进制字符由后向前存入RomCodeString
      //各字节的两字符存入顺序依次是:(14,15)(12,13)(10,11)......(2,3)(0,1)


      //上面这一行还可以改成以下两行


   }
   LCD_Buffer[16] = '\0';
   LCD_ShowString(r,c,LCD_Buffer);//显示ROMCODE 
}

//-----------------------------------------------------------------
// 搜索1-Wire上挂载的所有器件的ROMCODE
//-----------------------------------------------------------------
INT8U Search_ALL_ROM()
{ 
   INT8U i; 
   DS_CNT = 0; //初始时搜索到的器件个数归0
   Level = 0;  //初始时设搜索分支层为0
   //开始搜索第一个器件之前将64位的ROMCODE清0
   for (i = 0; i < 8; i++) ROMCODE[i] = 0x00;
   //开始搜索所有在线器件的ROMCODE
   while(1)
   {
      //保存上次搜索遇到的最低分支层
      Last_Level = Level;
      //当前分支层暂设为0
      Level = 0; 
      //搜索一个新的ROMCODE,未找到或出错时退出
      if (Search_ROM1()) break;
      //转换并显示当前找到的器件的8字节(64位)ROMCODE
      Show_Romcode(2,0,ROMCODE);
      //仅保存DS18B20器件的ROMCODE
      //(限于EEPROM空间,本例仅最多只保存32个ROMCODE)
      if (DS_CNT < 32 && ROMCODE[0] == 0x28) 
      {  //将所找到的器件ROMCODE写入PIC EEPROM
         for (i = 0; i < 8; i++) 
         {  EEPROM_WRITE(DS_CNT * 8 + i,ROMCODE[i]); 
            while(WR);
         }    
         __delay_ms(100);  DS_CNT++; //累加所找到的总器件数
      }
      //显示当前找到的总器件数
      sprintf(LCD_Buffer,"Found:%d",DS_CNT);
      LCD_ShowString(1,0,LCD_Buffer); 
      //如果完成某次搜索后当前分支层仍为0则结束查找
      if (Level == 0) break;
      __delay_ms(100);
   }
   //将所搜索到的总器件数写入EEPROM 0xFF地址
   EEPROM_WRITE(0xFF,DS_CNT); while(WR);
   return DS_CNT; //返回所搜索到的器件总数
}

//-----------------------------------------------------------------
// 读取存放于8字节数组A中的ROMCODE的第i位(0/1)
//-----------------------------------------------------------------
INT8U Read_ROMCODE_Bit(INT8U A[],INT8U i)
{
   //得出64位ROMCODE中第i位所处的字节值,及该位的掩码字节k



}

//-----------------------------------------------------------------
// 将存放于8字节数组A中的ROMCODE的第i位设为0/1
//-----------------------------------------------------------------
void Save_ROMCODE_Bit(INT8U A[],INT8U i,INT8U b)
{    
   //先求出64位中的第i位所在的字节在数组中的索引j
   //再根据该位在此字节内8位中的位置(i % 8)再得出掩码字节k
   //例如要设第3位为1,则有k = 0x01 << 3 = 0B00001000.
   
 
   //相应位设为1或0
   

}

//-----------------------------------------------------------------
// 根据ROMCODE码读取温度数据
//-----------------------------------------------------------------
float Get_Temperature(char *rom_code)
{   
   float sign = 1;
   RESET();                      //复位
   ROMCODE_Match(rom_code);      //发ROMCODE匹配命令
   Write_Byte(CONVERT);          //温度转换命令   
   DelayX100ms(7);               //12位分辩率转换时间为750ms
   __delay_ms(50);
   RESET();                      //复位
   ROMCODE_Match(rom_code);      //发ROMCODE匹配命令
   Write_Byte(READ_SCRATCHPAD);  //读RAM命令
   Temp_Value[0] = Read_Byte();  //读取两字节温度数据
   Temp_Value[1] = Read_Byte();
   //如果为负数则取反加1,并设置负数标识
   //按技术手册说明,高5位为符号位,与上0xF8进行+/-判断   
   if ( (Temp_Value[1] & 0xF8) == 0xF8) 
   {  




   }   



}

//-----------------------------------------------------------------
// 发送匹配命令,并发送64位的ROMCODE
//-----------------------------------------------------------------
void ROMCODE_Match(INT8U ROMCODE[])
{    
   //先发送ROM匹配命令,然后发送64位的ROMCODE


}

//-----------------------------------------------------------------
// 向1-Wire总线写1字节
//-----------------------------------------------------------------
void Write_Byte(INT8U A)
{
   for (INT8U i = 0x01;i != 0x00; i <<= 1)
   {    
      if (A & i) Write_DQ_bit(1); else Write_DQ_bit(0);
   }
}

//-----------------------------------------------------------------
// 从1-Wire总线读取1字节
//-----------------------------------------------------------------
INT8U Read_Byte()        
{    
   INT8U i,d = 0x00;
   for (i = 0; i < 8; i++)
   {
      Read_Slot(); if (DQ == 1)  d |= (1<<i); __delay_us(52);
   }
   return d;
}

//-----------------------------------------------------------------
// 向1-Wire总线写1位0/1
//-----------------------------------------------------------------
void Write_DQ_bit(INT8U b)
{    
   DQ_DIR = 0;  DQ = 0;           //DQ输出   
   if (b) {  __delay_us(5);   DQ_DIR = 1;  __delay_us(72);  }
   else   {  __delay_us(82);  DQ_DIR = 1;  }
}

//-----------------------------------------------------------------
// 发送读时隙时序
//-----------------------------------------------------------------
void Read_Slot()        
{    
   DQ_DIR = 0; DQ = 0; NOP(); NOP(); DQ_DIR = 1; NOP(); NOP();
}

//-----------------------------------------------------------------
// 1-Wire总线复位
//----------------------------------------------------------------- 
void RESET()
{    


}

//-----------------------------------------------------------------
// CRC8校验函数 (基于该函数可得出256字节的校验码表,改用查表法进行校验)
// 校验多项式: x^8 + x ^ 5 + x ^ 4 + 1, 去高位后倒序:0x8C
//----------------------------------------------------------------- 
void CRC8(INT8U d)   
{



}

⌨️ 快捷键说明

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