Files
DS18B20_Library/DS18B20/onewire.c
Razvalyaev 586907b339 восстановление потеряной ветки...
- сделана привязка датчиков по индексу или по юзер байтам
2025-02-06 13:06:18 +03:00

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;
}