480 lines
11 KiB
C
480 lines
11 KiB
C
/**
|
|
******************************************************************************
|
|
* @file onewire.c
|
|
* @brief This file includes the HAL/LL driver for OneWire devices
|
|
******************************************************************************
|
|
*/
|
|
#include "onewire.h"
|
|
//#include "onewire_uart.h"
|
|
|
|
/**
|
|
* @brief The internal function is used as gpio pin mode
|
|
* @param OW OneWire HandleTypedef
|
|
* @param Mode Input or Output
|
|
*/
|
|
void OneWire_Pin_Mode(OneWire_t* OW, PinMode Mode)
|
|
{
|
|
// GPIOA->CRH &= ~((GPIO_CRH_CNF9 | GPIO_CRH_MODE9));
|
|
// GPIOA->CRH |= (2 << GPIO_CRH_CNF9_Pos);
|
|
#ifdef CMSIS_Driver
|
|
if(Mode == Input)
|
|
{
|
|
GPIOA->CRH &= ~((GPIO_CRH_CNF9 | GPIO_CRH_MODE9));
|
|
GPIOA->CRH |= (1 << GPIO_CRH_CNF9_Pos);
|
|
}else{
|
|
GPIOA->CRH &= ~((GPIO_CRH_CNF9 | GPIO_CRH_MODE9));
|
|
GPIOA->CRH |= (3 << GPIO_CRH_MODE9_Pos);
|
|
}
|
|
// HAL_GPIO_Init(OW->DataPort, &GPIO_InitStruct);
|
|
// static uint32_t pin_numb = 0;
|
|
// static int get_pin_numb = 1;
|
|
//
|
|
// if(get_pin_numb)
|
|
// {
|
|
// get_pin_numb = 0;
|
|
// for(int i = 0; i < 16; i++)
|
|
// {
|
|
// if((OW->DataPin >> i) == 0x1)
|
|
// pin_numb = i;
|
|
// }
|
|
// }
|
|
//
|
|
// uint32_t config = 0;
|
|
// __IO uint32_t *configregister; /* Store the address of CRL or CRH register based on pin number */
|
|
// uint32_t registeroffset; /* offset used during computation of CNF and MODE bits placement inside CRL or CRH register */
|
|
// uint32_t iocurrent;
|
|
//
|
|
// if(Mode == Input)
|
|
// {
|
|
// config = 0;
|
|
// }else{
|
|
// config = GPIO_SPEED_FREQ_HIGH;
|
|
// }
|
|
// /* Check if the current bit belongs to first half or last half of the pin count number
|
|
// in order to address CRH or CRL register*/
|
|
// configregister = (OW->DataPin < GPIO_PIN_8) ? &OW->DataPort->CRL : &OW->DataPort->CRH;
|
|
// registeroffset = (OW->DataPin < GPIO_PIN_8) ? (pin_numb << 2u) : ((pin_numb - 8u) << 2u);
|
|
// /* Apply the new configuration of the pin to the register */
|
|
// MODIFY_REG((*configregister), ((GPIO_CRL_MODE0 | GPIO_CRL_CNF0) << registeroffset), (config << registeroffset));
|
|
#else
|
|
#ifdef LL_Driver
|
|
if(Mode == Input)
|
|
{
|
|
LL_GPIO_SetPinMode(OW->DataPort, OW->DataPin, LL_GPIO_MODE_INPUT);
|
|
}else{
|
|
LL_GPIO_SetPinMode(OW->DataPort, OW->DataPin, LL_GPIO_MODE_OUTPUT);
|
|
}
|
|
#else
|
|
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
|
GPIO_InitStruct.Pin = OW->DataPin;
|
|
if(Mode == Input)
|
|
{
|
|
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
|
}else{
|
|
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
|
}
|
|
HAL_GPIO_Init(OW->DataPort, &GPIO_InitStruct);
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief The internal function is used as gpio pin level
|
|
* @param OW OneWire HandleTypedef
|
|
* @param Mode Level: Set/High = 1, Reset/Low = 0
|
|
*/
|
|
void OneWire_Pin_Level(OneWire_t* OW, uint8_t Level)
|
|
{
|
|
#ifdef CMSIS_Driver
|
|
if (Level != GPIO_PIN_RESET)
|
|
{
|
|
OW->DataPort->BSRR = OW->DataPin;
|
|
}
|
|
else
|
|
{
|
|
OW->DataPort->BSRR = (uint32_t)OW->DataPin << 16u;
|
|
}
|
|
#else
|
|
#ifdef LL_Driver
|
|
if(Level == 1)
|
|
{
|
|
LL_GPIO_SetOutputPin(OW->DataPort, OW->DataPin);
|
|
}else{
|
|
LL_GPIO_ResetOutputPin(OW->DataPort, OW->DataPin);
|
|
}
|
|
#else
|
|
HAL_GPIO_WritePin(OW->DataPort, OW->DataPin, Level);
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief The internal function is used to read data pin
|
|
* @retval Pin level status
|
|
* @param OW OneWire HandleTypedef
|
|
*/
|
|
uint8_t OneWire_Pin_Read(OneWire_t* OW)
|
|
{
|
|
#ifdef CMSIS_Driver
|
|
return ((OW->DataPort->IDR & OW->DataPin) != 0x00U) ? 1 : 0;
|
|
#else
|
|
#ifdef LL_Driver
|
|
return ((OW->DataPort->IDR & OW->DataPin) != 0x00U) ? 1 : 0;
|
|
#else
|
|
return HAL_GPIO_ReadPin(OW->DataPort, OW->DataPin);
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @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)
|
|
{
|
|
#ifndef ONEWIRE_UART_H
|
|
if(bit)
|
|
{
|
|
/* Set line low */
|
|
OneWire_Pin_Level(OW, 0);
|
|
OneWire_Pin_Mode(OW, Output);
|
|
|
|
/* Forming pulse */
|
|
DwtDelay_us(ONEWIRE_WRITE_1_US);
|
|
|
|
/* Release line (pull up line) */
|
|
OneWire_Pin_Mode(OW, Input);
|
|
|
|
/* Wait for 55 us and release the line */
|
|
DwtDelay_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 */
|
|
DwtDelay_us(ONEWIRE_WRITE_0_US);
|
|
|
|
/* Release line (pull up line) */
|
|
OneWire_Pin_Mode(OW, Input);
|
|
|
|
/* Wait for 5 us and release the line */
|
|
DwtDelay_us(ONEWIRE_COMMAND_SLOT_US - ONEWIRE_WRITE_0_US);
|
|
OneWire_Pin_Mode(OW, Input);
|
|
}
|
|
#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)
|
|
{
|
|
uint8_t bit = 0;
|
|
#ifndef ONEWIRE_UART_H
|
|
/* Line low */
|
|
OneWire_Pin_Level(OW, 0);
|
|
OneWire_Pin_Mode(OW, Output);
|
|
DwtDelay_us(ONEWIRE_READ_CMD_US);
|
|
|
|
/* Release line */
|
|
OneWire_Pin_Mode(OW, Input);
|
|
DwtDelay_us(ONEWIRE_READ_DELAY_US);
|
|
|
|
/* Read line value */
|
|
bit = OneWire_Pin_Read(OW);
|
|
|
|
/* Wait 50us to complete 60us period */
|
|
DwtDelay_us(ONEWIRE_COMMAND_SLOT_US - ONEWIRE_READ_CMD_US - ONEWIRE_READ_DELAY_US);
|
|
#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)
|
|
{
|
|
#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)
|
|
{
|
|
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)
|
|
{
|
|
#ifndef ONEWIRE_UART_H
|
|
/* Line low, and wait 480us */
|
|
OneWire_Pin_Level(OW, 0);
|
|
OneWire_Pin_Mode(OW, Output);
|
|
DwtDelay_us(ONEWIRE_RESET_PULSE_US);
|
|
|
|
/* Release line and wait for 70us */
|
|
OneWire_Pin_Mode(OW, Input);
|
|
DwtDelay_us(ONEWIRE_PRESENCE_WAIT_US);
|
|
|
|
/* Check bit value */
|
|
uint8_t rslt = OneWire_Pin_Read(OW);
|
|
|
|
/* Delay for 410 us */
|
|
DwtDelay_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)
|
|
{
|
|
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);
|
|
DwtDelay_us(1000);
|
|
OneWire_Pin_Level(OW, 0);
|
|
DwtDelay_us(1000);
|
|
OneWire_Pin_Level(OW, 1);
|
|
DwtDelay_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;
|
|
}
|