📄 1-wiresearch.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 + -