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

📄 1-wiresearch.c

📁 单线搜索算法,适合51系列单片机,硬件访问层使用IO模拟,在其他平台应用,需要更改硬件层,已在89s52上测试通过
💻 C
字号:
根据网上源码更改的,搜索算法来自美信应用笔记,全部调试通过


/************************************************************
DQ为数据口,
*22.1184M晶振,上拉4.7k电阻  其他系列晶振需要按比例调整TA-TJ

*************************************************************/

#include <at89x52.h>
#include<intrins.h> 
#define uchar unsigned char
#define uint  unsigned int
//部分延时宏
/*-------------------------------------
以下时序部分需要根据晶振改变
*/
#define  TA  delay(1)  //6us
#define  TB  delay(11)  //64us
#define  TC  delay(10)    //60us
#define  TD   delay(2)    //10us
#define  TE   delay(2)    //9us
#define  TF   delay(9)    //55us
#define  TH  delay(80)    //480us
#define  TI  delay(11)     //70us
#define  TJ delay(70)       //410us

sbit DQ = P1^0;
bit  flag;
uchar  idata temp_buff[9]; //存储读取的字节,read scratchpad为9字节,read rom ID为8字节
uchar  idata ROM_NO[8];     //记录当前正在查找的ROM注册码的8字节缓冲器
uchar *p,*ID;
uchar crc_data;
char LastDiscrepancy;  //位指针 指明下次搜索从哪个值差异位开始  
char LastFamilyDiscrepancy;  //位指针  用来指明LastDiscrepancy是否是在ROM码中前8位家族码内和其位置
char LastDeviceFlag;  //指明前一次搜索到的已是最后一个器件的标志位  
unsigned char crc8;


code uchar  CrcTable [256]={
0,  94, 188,  226,  97,  63,  221,  131,  194,  156,  126,  32,  163,  253,  31,  65,
157,  195,  33,  127,  252,  162,  64,  30,  95,  1,  227,  189,  62,  96,  130,  220,
35,  125,  159,  193,  66,  28,  254,  160,  225,  191,  93,  3,  128,  222,  60,  98,
190,  224,  2,  92,  223,  129,  99,  61,  124,  34,  192,  158,  29,  67,  161,  255,
70,  24,  250,  164,  39,  121,  155,  197,  132,  218,  56,  102,  229,  187,  89,  7,
219,  133, 103,  57,  186,  228,  6,  88,  25,  71,  165,  251,  120,  38,  196,  154,
101,  59, 217,  135,  4,  90,  184,  230,  167,  249,  27,  69,  198,  152,  122,  36,
248,  166, 68,  26,  153,  199,  37,  123,  58,  100,  134,  216,  91,  5,  231,  185,
140,  210, 48,  110,  237,  179,  81,  15,  78,  16,  242,  172,  47,  113,  147,  205,
17,  79,  173,  243,  112,  46,  204,  146,  211,  141,  111,  49,  178,  236,  14,  80,
175,  241, 19,  77,  206,  144,  114,  44,  109,  51,  209,  143,  12,  82,  176,  238,
50,  108,  142,  208,  83,  13,  239,  177,  240,  174,  76,  18,  145,  207,  45,  115,
202,  148, 118,  40,  171,  245,  23,  73,  8,  86,  180,  234,  105,  55,  213, 139,
87,  9,  235,  181,  54,  104,  138,  212,  149,  203,  41,  119,  244,  170,  72,  22,
233,  183,  85,  11,  136,  214,  52,  106,  43,  117,  151,  201,  74,  20,  246,  168,
116,  42,  200,  150,  21,  75,  169,  247,  182,  232,  10,  84,  215,  137,  107,  53};
//

//函数声明部分
char OWSearch();



/************************************************************
*Function:延时处理
*parameter:
*Return:
*Modify:
*************************************************************/
//延时函数

void delay(unsigned int i)
{
 while(--i);
//时间等于(周期/晶振*2)*(2+i)
             //T=[2X + 4] * (12 / Fosc)  22.1184  0.5425
}
/************************************************************
*Function:18B20初始化
*parameter:
*Return:
*Modify:
*************************************************************/
uchar OWReset (void)
{
 unsigned char x=0;
 DQ = 1;    //DQ复位
 TC;  //稍做延时
 DQ = 0;    //单片机将DQ拉低
 TH; //精确延时 大于 480us
 DQ = 1;    //拉高总线
 TI;
 x=DQ;      //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
 TJ;
 return(x);
}
/************************************************************
*Function:单线读一位数据
*parameter:
*Return:
*Modify:
*************************************************************/

uchar ReadBit(void) 
{ 
 uchar result;

	DQ=0; // Drives DQ low
	TA;
	DQ=1; // Releases the bus
	TE;
	result = DQ; // Sample the bit value from the slave
	TF; // Complete the time slot and 10us recovery

	return result;
 } 

/************************************************************
*Function:单线读一位数据
*parameter:
*Return:
*Modify:
*************************************************************/

void WriteBit(uchar bitval) 
{ 

	if (bitval)
	{
		// Write '1' bit
	DQ=0; // Drives DQ low
	TA;
	DQ=1; // Releases the bus
	TB; // Complete the time slot and 10us recovery
	}
	else
	{
		// Write '0' bit
		DQ=0; // Drives DQ low
		TC;
		DQ=1; // Releases the bus
		TD;
	}
 } 


/************************************************************
*Function:单线写入一个字节
*parameter:
*Return:
*Modify:
*************************************************************/
void WriteByte (uchar dat)  //单字节写入
{
uchar loop;

	// Loop to write each bit in the byte, LS-bit first
	for (loop = 0; loop < 8; loop++)
	{
		WriteBit(dat & 0x01);

		// shift the data byte for the next bit
		dat >>= 1;
	}
}
/************************************************************
*Function:读单线的一个字节
*parameter:
*Return:
*Modify:
*************************************************************/
uchar ReadByte (void)     //读取单字节
{
uchar loop, result=0;

	for (loop = 0; loop < 8; loop++)
	{
		// shift the result to get it ready for the next bit
		result >>= 1;

		// if result is one, then set MS bit
		if (ReadBit())
			result |= 0x80;
	}
	return result;
}
/************************************************************
*Function:读多个字节18B20
*parameter:
*Return:
*Modify:
*************************************************************/
void read_bytes (uchar j)
{
  uchar i;
  for(i=0;i<j;i++)
  {
    *p = ReadByte();
    p++;
  }
}
/************************************************************
*Function:CRC校验
*parameter:
*Return:
*Modify:
*************************************************************/
uchar CRC (uchar *ArrayPoint, uchar ArrayLength)
{
    uchar i,crc_data=0;
   for(i=0;i<ArrayLength;i++)  //查表校验
     crc_data = CrcTable[crc_data^*(ArrayPoint+i)];
    return (crc_data);
}

/************************************************************
*Function:1第一次查找
*parameter:
*Return: TURE 找到设备,ROM ID 存放在ROM_NO数组 0 没有 找到设备 结束
*Modify:
*************************************************************/
char OWFirst()
{
   // reset the search state
   LastDiscrepancy = 0;
   LastDeviceFlag = 0;
   LastFamilyDiscrepancy = 0;

   return OWSearch();
}
/************************************************************
*Function:查找下一个
*parameter:
*Return: TURE 找到设备,ROM ID 存放在ROM_NO数组 0 没有 找到设备 结束
*Modify:
*************************************************************/
char OWNext()
{
   // leave the search state alone
   return OWSearch();
}


/************************************************************
*Function:1搜索单线上的设备
*parameter:
*Return: TURE 找到设备,ROM ID 存放在ROM_NO数组 0 没有 找到设备 结束
*Modify:
*************************************************************/
char OWSearch()
{
    char id_bit_number;    //记录当前搜索是1到64位ROM码中哪一位的量  
   char last_zero, rom_byte_number, search_result;
   char id_bit, cmp_id_bit;     //该位是搜索过程中所有应答器件的位及补码
   unsigned char rom_byte_mask, search_direction; 
     //位变量 其值用来指明搜索方向 具有此数据位规定值的所有器件继续响应搜索操作 其它器件转入等待状态直到下一次 1-Wire复位

   // initialize for search
   id_bit_number = 1;
   last_zero = 0;          //上次被写入 0的值差异位的位
   rom_byte_number = 0;
   rom_byte_mask = 1;
   search_result = 0;
   crc8 = 0;

   // 不是最后一次查找,复位再开始
   if (!LastDeviceFlag)
   {
      // 1-Wire reset
      if (OWReset())
      {
         // reset the search
         LastDiscrepancy = 0;
         LastDeviceFlag = 0;
         LastFamilyDiscrepancy = 0;
         return 0;    
      }

      // issue the search command 
      WriteByte(0xF0);  
      
      // loop to do the search
      do
      {
         // read a bit and its complement
         id_bit = ReadBit();
         cmp_id_bit = ReadBit();

         // check for no devices on 1-wire
         if ((id_bit == 1) && (cmp_id_bit == 1))
            break;
         else
         {
            // all devices coupled have 0 or 1
            if (id_bit != cmp_id_bit)
               search_direction = id_bit;  // bit write value for search
            else
            {
               // if this discrepancy if before the Last Discrepancy
               // on a previous next then pick the same as last time
               if (id_bit_number < LastDiscrepancy)
                  search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
               else
                  // if equal to last pick 1, if not then pick 0
                  search_direction = (id_bit_number == LastDiscrepancy);

               // if 0 was picked then record its position in LastZero
               if (search_direction == 0)
               {
                  last_zero = id_bit_number;

                  // check for Last discrepancy in family
                  if (last_zero < 9)
                     LastFamilyDiscrepancy = last_zero;
               }
            }

            // set or clear the bit in the ROM byte rom_byte_number
            // with mask rom_byte_mask
            if (search_direction == 1)
              ROM_NO[rom_byte_number] |= rom_byte_mask;
            else
              ROM_NO[rom_byte_number] &= ~rom_byte_mask;

            // serial number search direction write bit
            WriteBit(search_direction);

            // increment the byte counter id_bit_number
            // and shift the mask rom_byte_mask
            id_bit_number++;
            rom_byte_mask <<= 1;

            // 如果标记为0则转向 新的 SerialNum byte ,rom_byte_number and reset mask
            if (rom_byte_mask == 0)
            {
              crc8=CRC(ROM_NO,8);
                //(ROM_NO[rom_byte_number]);  // 计算CRC
                rom_byte_number++;
                rom_byte_mask = 1;
            }
         }
      }
      while(rom_byte_number < 8);  // 循环查找rom的0-7个字节

      // 如果搜索完成则
      if (!((id_bit_number < 65) || (crc8 != 0)))
      {
         // 搜索完成 设置 LastDiscrepancy,LastDeviceFlag,search_result
         LastDiscrepancy = last_zero;

         // 检查是否为最后一个设备
         if (LastDiscrepancy == 0)
            LastDeviceFlag = 1;
         
         search_result = 1;
      }
   }

   // 如果没有找到设备,则按第一次搜索方法进行
   if (!search_result || !ROM_NO[0])
   {
      LastDiscrepancy = 0;
      LastDeviceFlag = 0;
      LastFamilyDiscrepancy = 0;
      search_result = 0;
   }

   return search_result;

}
/************************************************************
*Function:操作用来检验已知 ROM 码的器件是否连接在 1-Wire 总线上
*parameter:
*Return: TURE 
*Modify:
*************************************************************/
//--------------------------------------------------------------------------
// Verify the device with the ROM number in ROM_NO buffer is present.
// Return 1  : device verified present
//        0 : device not present
//
char OWVerify()
{
   unsigned char rom_backup[8];
   char i,rslt,ld_backup,ldf_backup,lfd_backup;

   // keep a backup copy of the current state
   for (i = 0; i < 8; i++)
      rom_backup[i] = ROM_NO[i];
   ld_backup = LastDiscrepancy;
   ldf_backup = LastDeviceFlag;
   lfd_backup = LastFamilyDiscrepancy;

   // set search to find the same device
   LastDiscrepancy = 64;
   LastDeviceFlag = 0;

   if (OWSearch())
   {
      // check if same device found
      rslt = 1;
      for (i = 0; i < 8; i++)
      {
         if (rom_backup[i] != ROM_NO[i])
         {
            rslt = 0;
            break;
         }
      }
   }
   else
     rslt = 0;

   // restore the search state 
   for (i = 0; i < 8; i++)
      ROM_NO[i] = rom_backup[i];
   LastDiscrepancy = ld_backup;
   LastDeviceFlag = ldf_backup;
   LastFamilyDiscrepancy = lfd_backup;

   // return the result of the verify
   return rslt;
}
/************************************************************
*Function:操作就是用预置家族搜索状态,设置后 需要手动调用OWfirst
*parameter:
*Return: TURE 
*Modify:
*************************************************************/
//--------------------------------------------------------------------------
// Setup the search to find the device type 'family_code' on the next call
// to OWNext() if it is present.
//
void OWTargetSetup(unsigned char family_code)
{
   char i;

   // set the search state to find SearchFamily type devices
   ROM_NO[0] = family_code;
   for (i = 1; i < 8; i++)
      ROM_NO[i] = 0;
   LastDiscrepancy = 64;
   LastFamilyDiscrepancy = 0;
   LastDeviceFlag = 0;
}
void search()
{
OWFirst();

 if(LastDeviceFlag)
    {
   LCD_Write_String(0,0,"SEARCH DEVICE");
   //Array_Disp(0,1,ROM_NO,0,7);
  
    }
   else
    {
  
   OWNext();
   LCD_Write_String(0,0,"NO SEARCH DEVICE");
    }
}


⌨️ 快捷键说明

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