/** ****************************************************************************** * @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; }