📄 ow_comm.#3
字号:
//------------------------------------------------------------------------------------
//
// FILE NAME : ow_comm.c
// TARGET DEVICE : C8051F314
// CREATED ON : 07/14/06
// CREATED BY : Jzp
//
// Revision 1.0
// 功能描述:1-wire总线通信处理程序
// DQ -> P3.1
// 说明:本机中只支持两个从器件
//------------------------------------------------------------------------------------
#include <C8051F310.H>
#include "..\\inc\\define.h"
#define OW_COMM_GLOBALS
#include "..\\inc\\ow_comm.h"
//#define OW_DEBUG
//sbit DQ = P3^1;
// definitions
#define FALSE 0
#define TRUE 1
#define DS2762_FC 0X30
#define DS2415_FC 0Xa4
// method declarations
UCHAR ow_first();
UCHAR ow_next();
//UCHAR OWSearch();
UCHAR docrc8(UCHAR value);
void delay_us(UINT us);
//void find_ow_dev(void);
// global search state
UCHAR xdata ROM_NO[8];
UCHAR xdata LastDiscrepancy;
UCHAR xdata LastFamilyDiscrepancy;
UCHAR xdata LastDeviceFlag;
UCHAR xdata crc8;
//UCHAR xdata DevAddr[2][8]; // 存储从机地址
// global variable
SCHAR xdata BatVol[2]; // 精度4.88mV
SCHAR xdata BatCur[2]; // 精度15.625uV
UCHAR xdata RtcClk[4]; // 精度1s
// CRC TABLE
UCHAR code dscrc_table[] = {
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};
// 考虑到可位寻址资源有限,不要使用bit变量
/************************************************************
-----延时程序-----
功能: 延时us微妙
参数: us
说明: SYSCLK = 24.5MHZ,所以它的机器周期约为0.04us
//void delay_us(UINT us)
*************************************************************/
void delay_us(UINT us)
{
UINT i;
UCHAR j;
for(i = 0; i < us; i++)
{
for(j = 0; j < 2; j++); // 约1us<input type="text" <input type="text" >>
}
}
/************************************************************
-----1-wire总线复位程序-----
说明: 每次启动1-wire通信时,主机都要先复位总线
//UCHAR ow_reset(void)
*************************************************************/
UCHAR ow_reset(void)
{
// UINT i;
// UCHAR j;
bit ack_flag = 1;
DQ = 0;
delay_us(480); // 总线拉低480us
DQ = 1;
delay_us(40); // 总线释放50us 15us<t<60us
ack_flag = DQ; // 读取从设备应答脉冲
delay_us(300); // NOTICE: 必须等待完成一个周期,否则会出错
if(ack_flag)
return 0; // 无响应,表示总线上无设备
else
return 1; // 有响应,表示总线上有设备
}
/************************************************************
-----1-wire总线写入1bit位程序-----
说明:
//void ow_bit_wr(UCHAR level)
*************************************************************/
void ow_bit_wr(UCHAR level)
{
DQ = 0;
delay_us(15); // 拉低总线15us
if(level)
DQ = 1;
else
DQ = 0;
delay_us(40); // 保持45us
DQ = 1;
delay_us(2); // 释放总线至少1us
}
/************************************************************
-----1-wire总线读入1bit位程序-----
说明:
//UCHAR ow_bit_rd(void)
*************************************************************/
UCHAR ow_bit_rd(void)
{
UCHAR retbit;
DQ = 0;
delay_us(1); // 拉低总线1us
DQ = 1;
delay_us(15); // 释放总线保持15us
retbit = DQ; // 读取总线数据
delay_us(45); // NOTICE:等待一个读时隙完成,否则会出错
DQ = 1;
delay_us(1); // 释放总线至少1us
return retbit;
}
/************************************************************
-----1-wire总线写入1字节程序-----
说明: 字节写入顺序为低位在前
//void ow_byte_wr(UCHAR wdata)
*************************************************************/
void ow_byte_wr(UCHAR wdata)
{
UCHAR i;
UCHAR bitval = 0;
for(i = 0; i < 8; i++)
{
if((wdata >> i)&0x01)
bitval = 1;
else
bitval = 0;
ow_bit_wr(bitval);
}
}
/************************************************************
-----1-wire总线读出1字节程序-----
说明: 字节读出顺序为低位在前
//UCHAR ow_byte_rd()
*************************************************************/
UCHAR ow_byte_rd(void)
{
UCHAR i;
UCHAR bitval = 0;
UCHAR rdata = 0x00;
for(i = 0; i < 8; i++)
{
// shift_val = 0x80;
bitval = ow_bit_rd();
if(bitval == 1)
rdata = rdata|(0x01<<i);
}
return rdata;
}
/************************************************************
-----1-wire总线读出1字节程序-----
说明: 字节读出顺序为低位在前
//UCHAR ow_byte_rd()
*************************************************************/
ow_comm(void)
{
if(ow_reset() == 1) // 有1-wire器件存在
{
}
}
/************************************************************
-----1-wire总线主机获取总线上所有器件地址的程序-----
说明: 字节读出顺序为低位在前
//UCHAR ow_seach_dev()
*************************************************************/
//--------------------------------------------------------------------------
// Find the 'first' devices on the 1-Wire bus
// Return TRUE : device found, ROM number in ROM_NO buffer
// FALSE : no device present
//
UCHAR ow_first()
{
// reset the search state
LastDiscrepancy = 0;
LastDeviceFlag = FALSE;
LastFamilyDiscrepancy = 0;
return OWSearch();
}
//--------------------------------------------------------------------------
// Find the 'next' devices on the 1-Wire bus
// Return TRUE : device found, ROM number in ROM_NO buffer
// FALSE : device not found, end of search
//
UCHAR ow_next()
{
// leave the search state alone
return OWSearch();
}
//--------------------------------------------------------------------------
// Perform the 1-Wire Search Algorithm on the 1-Wire bus using the existing
// search state.
// Return TRUE : device found, ROM number in ROM_NO buffer
// FALSE : device not found, end of search
//
UCHAR OWSearch()
{
UCHAR id_bit_number;
UCHAR last_zero, rom_byte_number, search_result;
UCHAR id_bit, cmp_id_bit;
UCHAR rom_byte_mask, search_direction;
// initialize for search
id_bit_number = 1;
last_zero = 0;
rom_byte_number = 0;
rom_byte_mask = 1;
search_result = 0;
crc8 = 0;
// if the last call was not the last one
if (!LastDeviceFlag)
{
// 1-Wire reset
if (!ow_reset())
{
// reset the search
LastDiscrepancy = 0;
LastDeviceFlag = FALSE;
LastFamilyDiscrepancy = 0;
return FALSE;
}
// issue the search command
ow_byte_wr(0xF0);
// loop to do the search
do
{
// read a UCHAR and its complement
id_bit = ow_bit_rd();
cmp_id_bit = ow_bit_rd();
// 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; // UCHAR 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 UCHAR 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 UCHAR
ow_bit_wr(search_direction);
// increment the byte counter id_bit_number
// and shift the mask rom_byte_mask
id_bit_number++;
rom_byte_mask <<= 1;
// if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
if (rom_byte_mask == 0)
{
docrc8(ROM_NO[rom_byte_number]); // accumulate the CRC
rom_byte_number++;
rom_byte_mask = 1;
}
}
}
while(rom_byte_number < 8); // loop until through all ROM bytes 0-7
// if the search was successful then
if (!((id_bit_number < 65) || (crc8 != 0)))
{
// search successful so set LastDiscrepancy,LastDeviceFlag,search_result
LastDiscrepancy = last_zero;
// check for last device
if (LastDiscrepancy == 0)
LastDeviceFlag = TRUE;
search_result = TRUE;
}
}
// if no device found then reset counters so next 'search' will be like a first
if (!search_result || !ROM_NO[0])
{
LastDiscrepancy = 0;
LastDeviceFlag = FALSE;
LastFamilyDiscrepancy = 0;
search_result = FALSE;
}
return search_result;
}
//--------------------------------------------------------------------------
// Calculate the CRC8 of the byte value provided with the current
// global 'crc8' value.
// Returns current global crc8 value
//
UCHAR docrc8(UCHAR value)
{
// See Application Note 27
// TEST BUILD
crc8 = dscrc_table[crc8 ^ value];
return crc8;
}
/************************************************************
-----1-wire总线主机获取总线上所有器件地址的程序-----
说明: 根据搜索算法查找所有器件的64位地址并存储于指定位置
并根据器件地址的家族号判断,总线上为何种设备
出口参数:
如果存在DS2762,HasDs2762 = 1
如果存在DS2415,HasDs2415 = 1
//void find_ow_dev(void)
*************************************************************/
UCHAR find_ow_dev(void)
{
UCHAR rslt,j;//,cnt;
SCHAR i; // i一定要为有符号数,否则会出错
for(j = 0; j < 2; j++)
{
if(j == 0)
rslt = ow_first();
else
rslt = ow_next();
if(rslt == 1) //
{
for (i = 7; i >= 0; i--)
g_romaddr[j].romaddr[i] = ROM_NO[i]; // 存储64bit地址
if(ROM_NO[0] == DS2762_FC) // 判断是何器件
HasDs2762 = 1;
else if(ROM_NO[0] == DS2415_FC)
HasDs2415 = 1;
}
else
break;
}
return j; // 返回数量
}
/************************************************************
-----1-wire总线主机查询DS2762寄存器的程序-----
说明: 写读取命令69H,0CH,读取电池输出电压
写读取命令69H,0EH,读取电池电流
//void read_ds2762(void)
*************************************************************/
void read_ds2762(void)
{
UCHAR i;
ow_reset(); // 一个完整的总线动作之前都要复位总线
ow_byte_wr(0x55); // 发送NET ADDRESS COMMAND(MATCHE NETWORK ADDRESS)
for(i = 0; i < 8; i++) // 发送前面搜索到的地址
{
if(g_romaddr[0].st_romaddr.familycode == DS2415_FC)
ow_byte_wr(g_romaddr[0].romaddr[i]);
else
ow_byte_wr(g_romaddr[1].romaddr[i]);
}
ow_byte_wr(0x69);
ow_byte_wr(0x00);
for(i = 0; i < 9; i++)
{
BatVol[i] = ow_byte_rd();
}
// for(i =0; i < 2; i++)
// {
// BatCur[i] = ow_byte_rd();
// }
ow_reset(); // 读完后要复位总线
}
/************************************************************
-----1-wire总线主机查询DS2415寄存器的程序-----
说明: 写读取命令66H,读取RTC CLOCK
写设置命令69H,0EH,读取电池电流
//void read_ds2415(void)
*************************************************************/
void read_ds2415(void)
{
UCHAR i;
ow_reset(); // 一个完整的总线动作之前都要复位总线
ow_byte_wr(0x55); // 发送NET ADDRESS COMMAND(MATCHE NETWORK ADDRESS)
for(i = 0; i <8; i++) // 发送前面搜索到的地址
{
if(g_romaddr[0].st_romaddr.familycode == DS2415_FC)
ow_byte_wr(g_romaddr[0].romaddr[i]);
else
ow_byte_wr(g_romaddr[1].romaddr[i]);
}
ow_byte_wr(0x66);
for(i = 0; i < 4; i++) // 接收4字节clock
{
RtcClk[i] = ow_byte_rd();
}
ow_reset(); // 读完后一定要复位,否则会一直读
}
/************************************************************
-----ONE WIRE 通信任务-----
功能: 主程序调用该任务,与ow器件通信
参数: 行列号(ex。0x31 表示第3行第1列)
//说明:
//void task_owcomm(void)
*************************************************************/
void task_owcomm(void)
{
if(gOwdevNum != 0)
{
if(HasDs2762 == 1)
{
read_ds2762();
}
if(HasDs2415 == 1)
{
read_ds2415();
}
}
}
// debug function
//#ifdef OW_DEBUG
void ow_test(void)
{
UCHAR i;
if(ow_reset())
{
ow_byte_wr(0x33); // issue READ ROM command
DQ = 1;
delay_us(3);
for(i = 0; i < 8; i++)
{
g_testaddr.romaddr[i] = ow_byte_rd();
}
}
}
//#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -