380 lines
8.2 KiB
C
380 lines
8.2 KiB
C
/**
|
|
******************************************************************************
|
|
* @file onewire.c
|
|
* @brief This file includes the HAL/LL driver for OneWire devices
|
|
******************************************************************************
|
|
*/
|
|
#include "onewire.h"
|
|
|
|
/**
|
|
* @brief The internal function is used to write bit
|
|
* @param OW OneWire HandleTypedef
|
|
* @param bit bit in 0 or 1
|
|
*/
|
|
void OneWire_WriteBit(OneWire_t* OW, uint8_t bit)
|
|
{
|
|
if(OW == NULL)
|
|
return;
|
|
#ifndef ONEWIRE_UART_H
|
|
__disable_irq();
|
|
if(bit)
|
|
{
|
|
/* Set line low */
|
|
OneWire_Pin_Level(OW, 0);
|
|
OneWire_Pin_Mode(OW, Output);
|
|
|
|
/* Forming pulse */
|
|
OneWire_Delay_us(ONEWIRE_WRITE_1_US);
|
|
|
|
/* Release line (pull up line) */
|
|
OneWire_Pin_Mode(OW, Input);
|
|
|
|
/* Wait for 55 us and release the line */
|
|
OneWire_Delay_us(ONEWIRE_COMMAND_SLOT_US - ONEWIRE_WRITE_1_US);
|
|
OneWire_Pin_Mode(OW, Input);
|
|
}else{
|
|
/* Set line low */
|
|
OneWire_Pin_Level(OW, 0);
|
|
OneWire_Pin_Mode(OW, Output);
|
|
|
|
/* Forming pulse */
|
|
OneWire_Delay_us(ONEWIRE_WRITE_0_US);
|
|
|
|
/* Release line (pull up line) */
|
|
OneWire_Pin_Mode(OW, Input);
|
|
|
|
/* Wait for 5 us and release the line */
|
|
OneWire_Delay_us(ONEWIRE_COMMAND_SLOT_US - ONEWIRE_WRITE_0_US);
|
|
OneWire_Pin_Mode(OW, Input);
|
|
}
|
|
__enable_irq();
|
|
#else
|
|
OneWireUART_ProcessBit(onewire_uart, bit);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief The function is used to read bit
|
|
* @retval bit
|
|
* @param OW OneWire HandleTypedef
|
|
*/
|
|
uint8_t OneWire_ReadBit(OneWire_t* OW)
|
|
{
|
|
if(OW == NULL)
|
|
return 0;
|
|
|
|
__disable_irq();
|
|
uint8_t bit = 0;
|
|
#ifndef ONEWIRE_UART_H
|
|
/* Line low */
|
|
OneWire_Pin_Level(OW, 0);
|
|
OneWire_Pin_Mode(OW, Output);
|
|
OneWire_Delay_us(ONEWIRE_READ_CMD_US);
|
|
|
|
/* Release line */
|
|
OneWire_Pin_Mode(OW, Input);
|
|
OneWire_Delay_us(ONEWIRE_READ_DELAY_US);
|
|
|
|
/* Read line value */
|
|
bit = OneWire_Pin_Read(OW);
|
|
|
|
/* Wait 50us to complete 60us period */
|
|
OneWire_Delay_us(ONEWIRE_COMMAND_SLOT_US - ONEWIRE_READ_CMD_US - ONEWIRE_READ_DELAY_US);
|
|
__enable_irq();
|
|
#else
|
|
bit = OneWireUART_ProcessBit(onewire_uart, 1);
|
|
#endif
|
|
/* Return bit value */
|
|
return bit;
|
|
}
|
|
|
|
/**
|
|
* @brief The function is used to write byte
|
|
* @param OW OneWire HandleTypedef
|
|
* @param byte byte to write
|
|
*/
|
|
void OneWire_WriteByte(OneWire_t* OW, uint8_t byte)
|
|
{
|
|
if(OW == NULL)
|
|
return;
|
|
|
|
#ifndef ONEWIRE_UART_H
|
|
uint8_t bit = 8;
|
|
/* Write 8 bits */
|
|
while (bit--) {
|
|
/* LSB bit is first */
|
|
OneWire_WriteBit(OW, byte & 0x01);
|
|
byte >>= 1;
|
|
}
|
|
#else
|
|
OneWireUART_ProcessByte(onewire_uart, byte);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief The function is used to read byte
|
|
* @retval byte from device
|
|
* @param OW OneWire HandleTypedef
|
|
*/
|
|
uint8_t OneWire_ReadByte(OneWire_t* OW)
|
|
{
|
|
if(OW == NULL)
|
|
return 0;
|
|
|
|
uint8_t byte = 0;
|
|
#ifndef ONEWIRE_UART_H
|
|
uint8_t bit = 8;
|
|
while (bit--) {
|
|
byte >>= 1;
|
|
byte |= (OneWire_ReadBit(OW) << 7);
|
|
}
|
|
#else
|
|
byte = OneWireUART_ProcessByte(onewire_uart, 0xFF);
|
|
#endif
|
|
|
|
return byte;
|
|
}
|
|
|
|
/**
|
|
* @brief The function is used to reset device
|
|
* @retval respond from device
|
|
* @param OW OneWire HandleTypedef
|
|
*/
|
|
uint8_t OneWire_Reset(OneWire_t* OW)
|
|
{
|
|
if(OW == NULL)
|
|
return 1;
|
|
|
|
#ifndef ONEWIRE_UART_H
|
|
/* Line low, and wait 480us */
|
|
OneWire_Pin_Level(OW, 0);
|
|
OneWire_Pin_Mode(OW, Output);
|
|
OneWire_Delay_us(ONEWIRE_RESET_PULSE_US);
|
|
|
|
/* Release line and wait for 70us */
|
|
OneWire_Pin_Mode(OW, Input);
|
|
OneWire_Delay_us(ONEWIRE_PRESENCE_WAIT_US);
|
|
|
|
/* Check bit value */
|
|
uint8_t rslt = OneWire_Pin_Read(OW);
|
|
|
|
/* Delay for 410 us */
|
|
OneWire_Delay_us(ONEWIRE_PRESENCE_DURATION_US);
|
|
#else
|
|
|
|
uint8_t rslt = 0;
|
|
if(OneWireUART_Reset(onewire_uart) == HAL_OK)
|
|
rslt = 0;
|
|
else
|
|
rslt = 1;
|
|
#endif
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/**
|
|
* @brief The function is used to search device
|
|
* @retval Search result
|
|
* @param OW OneWire HandleTypedef
|
|
*/
|
|
uint8_t OneWire_Search(OneWire_t* OW, uint8_t Cmd)
|
|
{
|
|
if(OW == NULL)
|
|
return 0;
|
|
|
|
uint8_t id_bit_number = 1;
|
|
uint8_t last_zero = 0;
|
|
uint8_t rom_byte_number = 0;
|
|
uint8_t search_result = 0;
|
|
uint8_t rom_byte_mask = 1;
|
|
uint8_t id_bit, cmp_id_bit, search_direction;
|
|
|
|
/* if the last call was not the last one */
|
|
if (!OW->LastDeviceFlag)
|
|
{
|
|
if (OneWire_Reset(OW))
|
|
{
|
|
OW->LastDiscrepancy = 0;
|
|
OW->LastDeviceFlag = 0;
|
|
OW->LastFamilyDiscrepancy = 0;
|
|
return 0;
|
|
}
|
|
|
|
// issue the search command
|
|
OneWire_WriteByte(OW, Cmd);
|
|
|
|
// loop to do the search
|
|
do {
|
|
// read a bit and its complement
|
|
id_bit = OneWire_ReadBit(OW);
|
|
cmp_id_bit = OneWire_ReadBit(OW);
|
|
|
|
// 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 < OW->LastDiscrepancy)
|
|
{
|
|
search_direction = ((OW->RomByte[rom_byte_number] & rom_byte_mask) > 0);
|
|
} else {
|
|
// if equal to last pick 1, if not then pick 0
|
|
search_direction = (id_bit_number == OW->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)
|
|
{
|
|
OW->LastFamilyDiscrepancy = last_zero;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* set or clear the bit in the ROM byte rom_byte_number
|
|
* with mask rom_byte_mask */
|
|
if (search_direction == 1)
|
|
{
|
|
OW->RomByte[rom_byte_number] |= rom_byte_mask;
|
|
} else {
|
|
OW->RomByte[rom_byte_number] &= ~rom_byte_mask;
|
|
}
|
|
|
|
// serial number search direction write bit
|
|
OneWire_WriteBit(OW, 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)
|
|
{
|
|
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))
|
|
{
|
|
/* search successful so set LastDiscrepancy, LastDeviceFlag,
|
|
* search_result */
|
|
OW->LastDiscrepancy = last_zero;
|
|
// check for last device
|
|
if (OW->LastDiscrepancy == 0) {
|
|
OW->LastDeviceFlag = 1;
|
|
}
|
|
search_result = 1;
|
|
}
|
|
}
|
|
|
|
/* if no device found then reset counters so next 'search' will be like a
|
|
* first */
|
|
if (!search_result || !OW->RomByte[0])
|
|
{
|
|
OW->LastDiscrepancy = 0;
|
|
OW->LastDeviceFlag = 0;
|
|
OW->LastFamilyDiscrepancy = 0;
|
|
search_result = 0;
|
|
}
|
|
|
|
return search_result;
|
|
}
|
|
|
|
/**
|
|
* @brief The function is used get ROM full address
|
|
* @param OW OneWire HandleTypedef
|
|
* @param ROM Pointer to device ROM
|
|
*/
|
|
void OneWire_GetDevRom(OneWire_t* OW, uint8_t *ROM)
|
|
{
|
|
for (uint8_t i = 0; i < 8; i++) {
|
|
*(ROM + i) = OW->RomByte[i];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief The function is used to initialize OneWire Communication
|
|
* @param OW OneWire HandleTypedef
|
|
*/
|
|
void OneWire_Init(OneWire_t* OW)
|
|
{
|
|
OneWire_Pin_Mode(OW, Output);
|
|
OneWire_Pin_Level(OW, 1);
|
|
OneWire_Delay_us(1000);
|
|
OneWire_Pin_Level(OW, 0);
|
|
OneWire_Delay_us(1000);
|
|
OneWire_Pin_Level(OW, 1);
|
|
OneWire_Delay_us(2000);
|
|
|
|
/* Reset the search state */
|
|
OW->LastDiscrepancy = 0;
|
|
OW->LastDeviceFlag = 0;
|
|
OW->LastFamilyDiscrepancy = 0;
|
|
OW->RomCnt = 0;
|
|
}
|
|
|
|
/**
|
|
* @brief The function is used selected specific device ROM
|
|
* @param OW OneWire HandleTypedef
|
|
* @param ROM Pointer to device ROM
|
|
*/
|
|
void OneWire_MatchROM(OneWire_t* OW, uint8_t *ROM)
|
|
{
|
|
OneWire_WriteByte(OW, ONEWIRE_CMD_MATCHROM);
|
|
|
|
for (uint8_t i = 0; i < 8; i++)
|
|
{
|
|
OneWire_WriteByte(OW, *(ROM + i));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief The function is used to access to all ROM
|
|
* @param OW OneWire HandleTypedef
|
|
*/
|
|
void OneWire_Skip(OneWire_t* OW)
|
|
{
|
|
OneWire_WriteByte(OW, ONEWIRE_CMD_SKIPROM);
|
|
}
|
|
|
|
/**
|
|
* @brief The function is used check CRC
|
|
* @param Addr Pointer to address
|
|
* @param ROM Number of byte
|
|
*/
|
|
uint8_t OneWire_CRC8(uint8_t *Addr, uint8_t Len)
|
|
{
|
|
uint8_t crc = 0;
|
|
uint8_t inbyte, i, mix;
|
|
|
|
while (Len--)
|
|
{
|
|
inbyte = *Addr++;
|
|
|
|
for (i = 8; i; i--)
|
|
{
|
|
mix = (crc ^ inbyte) & 0x01;
|
|
crc >>= 1;
|
|
crc ^= (mix) ? 0x8C : 0;
|
|
inbyte >>= 1;
|
|
}
|
|
}
|
|
return crc;
|
|
}
|