восстановление потеряной ветки...

- сделана привязка датчиков по индексу или по юзер байтам
This commit is contained in:
2025-02-06 13:06:18 +03:00
parent e188fc4074
commit 586907b339
103 changed files with 100586 additions and 0 deletions

409
DS18B20/dallas_tools.c Normal file
View File

@@ -0,0 +1,409 @@
/**
******************************************************************************
* @file dallas_tools.c
* @brief Äðàéâåð äëÿ ðàáîòû ñ äàò÷èêàìè òåìïåðàòóðû DS18B20
* @author MicroTechnics (microtechnics.ru)
******************************************************************************
@details
Ýòîò ôàéë ñîäåðæèò ðåàëèçàöèþ ôóíêöèé äëÿ ðàáîòû ñ äàò÷èêîì DALLAS_HandleTypeDef
÷åðåç èíòåðôåéñ 1-Wire. Îí ïðåäîñòàâëÿåò ôóíêöèè äëÿ ÷òåíèÿ è çàïèñè
êîíôèãóðàöèè, âûïîëíåíèÿ èçìåðåíèé è îáðàáîòêè ïîëó÷åííûõ äàííûõ.
*****************************************************************************/
/* Includes ----------------------------------------------------------------*/
#include "dallas_tools.h"
/* Declarations and definitions --------------------------------------------*/
struct
{
DALLAS_HandleTypeDef outdoor;
DALLAS_HandleTypeDef indoor;
DALLAS_HandleTypeDef bathroom;
DALLAS_HandleTypeDef kitchen;
DALLAS_HandleTypeDef big_room;
DALLAS_HandleTypeDef small_room;
DALLAS_HandleTypeDef living_room;
DALLAS_HandleTypeDef basement;
}AllSens;
/* Functions ---------------------------------------------------------------*/
void Dallas_ReadAll(void)
{
HAL_StatusTypeDef result;
result = Dallas_StartConvertTAll(&OW, DALLAS_WAIT_BUS, 0);
result = Dallas_ReadTemperature(&AllSens.outdoor);
result = Dallas_ReadTemperature(&AllSens.indoor);
result = Dallas_ReadTemperature(&AllSens.bathroom);
result = Dallas_ReadTemperature(&AllSens.kitchen);
result = Dallas_ReadTemperature(&AllSens.big_room);
result = Dallas_ReadTemperature(&AllSens.small_room);
result = Dallas_ReadTemperature(&AllSens.living_room);
result = Dallas_ReadTemperature(&AllSens.basement);
}
void Dallas_FirstInit(void)
{
uint8_t mask = DALLAS_USER_BYTE_ALL;
OneWire_Init(&OW);
DS18B20_Search(&DS, &OW);
Dallas_SensorInitByInd(&OW, &AllSens.outdoor, 0);
Dallas_WriteUserBytes(&AllSens.outdoor, 1, NULL, mask);
Dallas_SensorInitByInd(&OW, &AllSens.indoor, 1);
Dallas_WriteUserBytes(&AllSens.indoor, 2, NULL, mask);
Dallas_SensorInitByInd(&OW, &AllSens.bathroom, 2);
Dallas_WriteUserBytes(&AllSens.bathroom, 3, NULL, mask);
Dallas_SensorInitByInd(&OW, &AllSens.kitchen, 3);
Dallas_WriteUserBytes(&AllSens.kitchen, 4, NULL, mask);
Dallas_SensorInitByInd(&OW, &AllSens.big_room, 4);
Dallas_WriteUserBytes(&AllSens.big_room, 5, NULL, mask);
Dallas_SensorInitByInd(&OW, &AllSens.small_room, 5);
Dallas_WriteUserBytes(&AllSens.small_room, 6, NULL, mask);
Dallas_SensorInitByInd(&OW, &AllSens.living_room, 6);
Dallas_WriteUserBytes(&AllSens.living_room, 7, NULL, mask);
Dallas_SensorInitByInd(&OW, &AllSens.basement, 7);
Dallas_WriteUserBytes(&AllSens.basement, 8, NULL, mask);
}
/**
* @brief Èíèöèàëèçèðóåò ñòðóêòóðó äàò÷èêà ïî èíäåêó
* @param onewire Óêàçàòåëü íà ñòðóêòóðó OneWire
* @param sensor Óêàçàòåëü íà ñòðóêòóðó äàò÷èêà
* @param UserBytes34 Ïîëüçîâàòåëüñêèå áàéòû 3 è 4, NULL äëÿ èãíîðà
* @param UserBytes12 Ïîëüçîâàòåëüñêèå áàéòû 1 è 2, NULL äëÿ èãíîðà
* @retval HAL Status
* @details ñòàðøèé áàéò - UserByte4/UserByte2, ìëàäøèé - UserByte3/UserByte1.
*/
HAL_StatusTypeDef Dallas_SensorInitByUserBytes(OneWire_t *onewire, DALLAS_HandleTypeDef *sensor, uint16_t UserBytes34, uint16_t UserBytes12)
{
HAL_StatusTypeDef result;
uint8_t UserByte1 = UserBytes12 & 0xFF;
uint8_t UserByte2 = UserBytes12 >> 8;
uint8_t UserByte3 = UserBytes34 & 0xFF;
uint8_t UserByte4 = UserBytes34 >> 8;
uint8_t UserByte12Cmp = 0;
uint8_t UserByte34Cmp = 0;
if(onewire == NULL)
return HAL_ERROR;
if(sensor == NULL)
return HAL_ERROR;
for(int i = 0; i < DS18B20_DEVICE_AMOUNT; i++)
{
UserByte12Cmp = 0; UserByte34Cmp = 0;
sensor->sensROM = &DS.DevAddr[i];
sensor->onewire = onewire;
/* Ïðîâåðêà ïðèñóòñòâóåò ëè âûáðàííûé äàò÷èê íà ëèíèè */
result = Dallas_IsConnected(sensor);
if (result != HAL_OK)
return result;
/* Ñðàâíåíèå UserByte1 è UserByte2, åñëè âûáðàíî */
if(UserBytes12 != NULL)
{
if( (sensor->scratchpad.tHighRegister == UserByte1) &&
(sensor->scratchpad.tLowRegister == UserByte2))
{
UserByte12Cmp = 1;
}
}/* Åñëè ðàâíåíèå UserByte1 è UserByte2 íå âûáðàíî, òî ñ÷èòàåì ÷òî îíè îäèíàêîâûå */
else
{
UserByte12Cmp = 1;
}
/* Ñðàâíåíèå UserByte3 è UserByte4, åñëè âûáðàíî */
if(UserBytes34 != NULL)
{
if( (sensor->scratchpad.UserByte3 == UserByte3) &&
(sensor->scratchpad.UserByte4 == UserByte4))
{
UserByte34Cmp = 1;
}
}/* Åñëè ðàâíåíèå UserByte3 è UserByte4 íå âûáðàíî, òî ñ÷èòàåì ÷òî îíè îäèíàêîâûå */
else
{
UserByte34Cmp = 1;
}
/* Åñëè íàøëè íóæíûé äàò÷èê - çàâåðøàåì ïîèñê */
if(UserByte12Cmp && UserByte34Cmp)
{
return HAL_OK;
}
}
/* Âîçâðàùàåì îøèáêó åñëè íå íàøëè */
return HAL_ERROR;
}
/**
* @brief Èíèöèàëèçèðóåò ñòðóêòóðó äàò÷èêà ïî èíäåêó
* @param onewire Óêàçàòåëü íà ñòðóêòóðó OneWire
* @param sensor Óêàçàòåëü íà ñòðóêòóðó äàò÷èêà
* @param sens_ind Ïîðÿäêîâûé íîìåð äàò÷èêà â ñòðóêòóðå
* @retval HAL Status
* @details Èíäåêñ - ýòî ïîðÿäêîâûé íîìåð äàò÷èêà â ñïèñêå íàéäåííûõ.
* Ò.å. êàêèì ïî ñ÷åòó ýòîò äàò÷èê áûë íàéäåí
*/
HAL_StatusTypeDef Dallas_SensorInitByInd(OneWire_t *onewire, DALLAS_HandleTypeDef *sensor, uint8_t sens_ind)
{
HAL_StatusTypeDef result;
if(onewire == NULL)
return HAL_ERROR;
if(sensor == NULL)
return HAL_ERROR;
sensor->sensROM = &DS.DevAddr[sens_ind];
sensor->onewire = onewire;
/* Ïðîâåðêà ïðèñóòñòâóåò ëè âûáðàííûé äàò÷èê íà ëèíèè */
result = Dallas_IsConnected(sensor);
if (result != HAL_OK)
return result;
return HAL_OK;
}
/**
* @brief Çàïóñêàåò èçìåðåíèå òåìïåðàòóðû íà âñåõ äàò÷èêàõ
* @param waitCondition Óñëîâèå îæèäàíèÿ çàâåðøåíèÿ ïðåîáðàçîâàíèÿ
* @retval HAL Status
*/
HAL_StatusTypeDef Dallas_StartConvertTAll(OneWire_t *onewire, DALLAS_WaitCondition waitCondition, uint8_t dallas_delay_ms)
{
HAL_StatusTypeDef result;
uint8_t rxDummyData;
// Îòïðàâêà êîìàíäû íà÷àëà ïðåîáðàçîâàíèÿ òåìïåðàòóðû
result = DS18B20_StartConvTAll(onewire);
if(result != HAL_OK)
{
return result;
}
// Îæèäàíèå çàâåðøåíèÿ ïðåîáðàçîâàíèÿ, ïóòåì ïðîâåðêè øèíû
if (waitCondition == DALLAS_WAIT_BUS)
{
result = DS18B20_WaitForEndConvertion(onewire);
return result;
}
// Îæèäàíèå çàâåðøåíèÿ ïðåîáðàçîâàíèÿ, ïóòåì çàäåðæêè
if (waitCondition == DALLAS_WAIT_DELAY)
{
uint32_t delayValueMs = 0;
switch (dallas_delay_ms)
{
case DALLAS_CONFIG_9_BITS:
delayValueMs = DALLAS_DELAY_MS_9_BITS;
break;
case DALLAS_CONFIG_10_BITS:
delayValueMs = DALLAS_DELAY_MS_10_BITS;
break;
case DALLAS_CONFIG_11_BITS:
delayValueMs = DALLAS_DELAY_MS_11_BITS;
break;
case DALLAS_CONFIG_12_BITS:
delayValueMs = DALLAS_DELAY_MS_12_BITS;
break;
default:
break;
}
HAL_Delay(delayValueMs);
}
return result;
}
/**
* @brief Èçìåðÿåò òåìïåðàòóðó íà äàò÷èêå
* @param sensor Óêàçàòåëü íà ñòðóêòóðó äàò÷èêà
* @param waitCondition Óñëîâèå îæèäàíèÿ çàâåðøåíèÿ ïðåîáðàçîâàíèÿ
* @retval HAL Status
*/
HAL_StatusTypeDef Dallas_ConvertT(DALLAS_HandleTypeDef *sensor, DALLAS_WaitCondition waitCondition)
{
HAL_StatusTypeDef result;
uint8_t rxDummyData;
/* Ïðîâåðêà ïðèñóòñòâóåò ëè âûáðàííûé äàò÷èê íà ëèíèè */
result = Dallas_IsConnected(sensor);
if (result != HAL_OK)
return result;
// Îòïðàâêà êîìàíäû íà÷àëà ïðåîáðàçîâàíèÿ òåìïåðàòóðû
result = DS18B20_StartConvT(sensor->onewire, (uint8_t *)sensor->sensROM);
if(result != HAL_OK)
{
return result;
}
// Îæèäàíèå çàâåðøåíèÿ ïðåîáðàçîâàíèÿ, ïóòåì ïðîâåðêè øèíû
if (waitCondition == DALLAS_WAIT_BUS)
{
result = DS18B20_WaitForEndConvertion(sensor->onewire);
if(result == HAL_TIMEOUT)
{
sensor->f.timeout_convertion_cnt++;
}
return result;
}
// Îæèäàíèå çàâåðøåíèÿ ïðåîáðàçîâàíèÿ, ïóòåì çàäåðæêè
if (waitCondition == DALLAS_WAIT_DELAY)
{
uint32_t delayValueMs = 0;
switch (sensor->scratchpad.ConfigRegister)
{
case DALLAS_CONFIG_9_BITS:
delayValueMs = DALLAS_DELAY_MS_9_BITS;
break;
case DALLAS_CONFIG_10_BITS:
delayValueMs = DALLAS_DELAY_MS_10_BITS;
break;
case DALLAS_CONFIG_11_BITS:
delayValueMs = DALLAS_DELAY_MS_11_BITS;
break;
case DALLAS_CONFIG_12_BITS:
delayValueMs = DALLAS_DELAY_MS_12_BITS;
break;
default:
break;
}
HAL_Delay(delayValueMs);
}
/* Íå ñ÷èòûâàåì òåìïåðàòóðó, åñëè íå âûáðàíî îæèäàíèå îêîí÷àíèÿ ïðåîáðàçîâàíèÿ */
if(waitCondition != DALLAS_WAIT_NONE)
{
result = Dallas_ReadTemperature(sensor);
}
return result;
}
/**
* @brief ×èòàåò ñîäåðæèìîå ïàìÿòè (scratchpad) äàò÷èêà DALLAS_HandleTypeDef
* @param sensor Óêàçàòåëü íà ñòðóêòóðó äàò÷èêà
* @retval HAL Status
*/
HAL_StatusTypeDef Dallas_ReadTemperature(DALLAS_HandleTypeDef *sensor)
{
HAL_StatusTypeDef result;
/* Ïðîâåðêà ïðèñóòñòâóåò ëè âûáðàííûé äàò÷èê íà ëèíèè */
result = Dallas_IsConnected(sensor);
if (result != HAL_OK)
return result;
result = DS18B20_CalcTemperature(sensor->onewire, (uint8_t *)sensor->sensROM, (uint8_t *)&sensor->scratchpad, &sensor->temperature);
if (result != HAL_OK)
{
sensor->f.read_temperature_err_cnt++;
return result;
}
return HAL_OK;
}
/**
* @brief Âûïîëíÿåò êîìàíäó èíèöèàëèçàöèè DALLAS_HandleTypeDef
* @param sensor Óêàçàòåëü íà ñòðóêòóðó äàò÷èêà
* @retval HAL Status
*/
HAL_StatusTypeDef Dallas_IsConnected(DALLAS_HandleTypeDef *sensor)
{
HAL_StatusTypeDef result;
result = DS18B20_ReadScratchpad(sensor->onewire, (uint8_t *)sensor->sensROM, (uint8_t *)&sensor->scratchpad);
if (result == HAL_OK)
{
sensor->isConnected = 1;
return HAL_OK;
}
else
{
if(sensor->isConnected == 1)
{
sensor->f.disconnect_cnt++;
}
sensor->isConnected = 0;
return HAL_BUSY; // èñïîëüçóþ busy, ÷òîáû îòëè÷àòü ñèòóàöèþ îò HAL_ERROR
}
}
/**
* @brief Çàïèñûâàåò ïîëüçîâàòåëüñêèå áàéòû
* @param sensor Óêàçàòåëü íà ñòðóêòóðó äàò÷èêà
* @param UserBytes12 Ïîëüçîâàòåëüñêèå áàéòû 1 è 2
* @param UserBytes34 Ïîëüçîâàòåëüñêèå áàéòû 3 è 4
* @param UserBytesMask Ìàñêà, êàêèå áàéòû çàïèñûâàòü, à êàêèå íåò
* @retval HAL Status
* @details ñòàðøèé áàéò - UserByte4/UserByte2, ìëàäøèé - UserByte3/UserByte1.
*/
HAL_StatusTypeDef Dallas_WriteUserBytes(DALLAS_HandleTypeDef *sensor, uint16_t UserBytes12, uint16_t UserBytes34, uint8_t UserBytesMask)
{
HAL_StatusTypeDef result = DS18B20_WriteUserBytes(sensor->onewire, (uint8_t *)sensor->sensROM, UserBytes12, UserBytes34, UserBytesMask);
if (result != HAL_OK)
{
sensor->f.read_temperature_err_cnt++;
return result;
}
result = DS18B20_ReadScratchpad(sensor->onewire, (uint8_t *)sensor->sensROM, (uint8_t *)&sensor->scratchpad);
if (result != HAL_OK)
{
sensor->f.read_temperature_err_cnt++;
return result;
}
return result;
}
///**
// * @brief ×èòàåò óíèêàëüíûé ROM-êîä äàò÷èêà DALLAS_HandleTypeDef
// * @param sensor Óêàçàòåëü íà ñòðóêòóðó äàò÷èêà
// * @retval HAL Status
// */
//HAL_StatusTypeDef Dallas_ReadRom(DALLAS_HandleTypeDef *sensor)
//{
// HAL_StatusTypeDef result = HAL_OK;
// uint8_t rxData[DALLAS_READ_ROM_RX_BYTES_NUM];
//
// DS18B20_ReadScratchpad(sensor->onewire, sensor->sensROM, (uint8_t *)&sensor->scratchpad);
//
//
// if (result == HAL_OK)
// {
// for (uint8_t i = 0; i < DALLAS_SERIAL_NUMBER_LEN_BYTES; i++)
// {
// sensor->sensROM[i] = rxData[DALLAS_SERIAL_NUMBER_OFFSET_BYTES + i];
// }
// }
// return result;
//}

144
DS18B20/dallas_tools.h Normal file
View File

@@ -0,0 +1,144 @@
/**
******************************************************************************
* @file : dallas_tools.h
* @brief : DALLAS driver
* @author : MicroTechnics (microtechnics.ru)
*****************************************************************************/
#ifndef DALLAS_TOOLS_H
#define DALLAS_TOOLS_H
/* Includes -----------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
#include "ds18b20.h"
#include "onewire.h"
#define DALLAS_USER_BYTE_1 (1<<0)
#define DALLAS_USER_BYTE_2 (1<<1)
#define DALLAS_USER_BYTE_3 (1<<2)
#define DALLAS_USER_BYTE_4 (1<<3)
#define DALLAS_USER_BYTE_12 (DALLAS_USER_BYTE_1|DALLAS_USER_BYTE_2)
#define DALLAS_USER_BYTE_34 (DALLAS_USER_BYTE_3|DALLAS_USER_BYTE_4)
#define DALLAS_USER_BYTE_ALL (DALLAS_USER_BYTE_12|DALLAS_USER_BYTE_34)
/* Declarations and definitions ---------------------------------------------*/
#define DALLAS_ROM_LEN_BYTES 8
#define DALLAS_SERIAL_NUMBER_LEN_BYTES 6
#define DALLAS_SERIAL_NUMBER_OFFSET_BYTES 1
#define DALLAS_SCRATCHPAD_T_LSB_BYTE_IDX 0
#define DALLAS_SCRATCHPAD_T_MSB_BYTE_IDX 1
#define DALLAS_SCRATCHPAD_T_LIMIT_H_BYTE_IDX 2
#define DALLAS_SCRATCHPAD_T_LIMIT_L_BYTE_IDX 3
#define DALLAS_SCRATCHPAD_CONFIG_BYTE_IDX 4
#define DALLAS_SCRATCHPAD_USER_BYTE_3_IDX 6
#define DALLAS_SCRATCHPAD_USER_BYTE_4_IDX 7
#define DALLAS_SCRATCHPAD_CRC_IDX 8
#define DALLAS_CONFIG_9_BITS 0x1F
#define DALLAS_CONFIG_10_BITS 0x3F
#define DALLAS_CONFIG_11_BITS 0x5F
#define DALLAS_CONFIG_12_BITS 0x7F
#define DALLAS_DELAY_MS_9_BITS 94
#define DALLAS_DELAY_MS_10_BITS 188
#define DALLAS_DELAY_MS_11_BITS 375
#define DALLAS_DELAY_MS_12_BITS 750
#define DALLAS_DELAY_MS_MAX DALLAS_DELAY_MS_12_BITS
#define DALLAS_9_BITS_DATA_MASK 0x7F8
#define DALLAS_10_BITS_DATA_MASK 0x7FC
#define DALLAS_11_BITS_DATA_MASK 0x7FE
#define DALLAS_12_BITS_DATA_MASK 0x7FF
#define DALLAS_SIGN_MASK 0xF800
#define DALLAS_T_STEP 0.0625
#define DALLAS_READ_ROM_RX_BYTES_NUM 8
#define DALLAS_READ_SCRATCHPAD_RX_BYTES_NUM 9
typedef struct
{
uint8_t TemperatureLSB;
uint8_t TemperatureMSB;
uint8_t tHighRegister;
uint8_t tLowRegister;
uint8_t ConfigRegister;
uint8_t reserved;
uint8_t UserByte3;
uint8_t UserByte4;
uint8_t ScratchpadCRC;
}DALLAS_ScratchpadTypeDef;
typedef struct
{
unsigned disconnect_cnt;
unsigned read_temperature_err_cnt;
unsigned timeout_convertion_cnt;
}DALLAS_FlagsTypeDef;
typedef struct
{
uint8_t isConnected;
#ifdef ONEWIRE_UART_H
UART_HandleTypeDef *uart;
#else
OneWire_t *onewire;
#endif
uint8_t (*sensROM)[DALLAS_ROM_LEN_BYTES];
DALLAS_ScratchpadTypeDef scratchpad;
float temperature;
DALLAS_FlagsTypeDef f;
}DALLAS_HandleTypeDef;
extern DALLAS_HandleTypeDef outdoor;
extern DALLAS_HandleTypeDef indoor;
extern DALLAS_HandleTypeDef bathroom;
extern DALLAS_HandleTypeDef kitchen;
extern DALLAS_HandleTypeDef big_room;
extern DALLAS_HandleTypeDef small_room;
extern DALLAS_HandleTypeDef living_room;
extern DALLAS_HandleTypeDef basement;
typedef enum
{
DALLAS_WAIT_NONE = 0x00,
DALLAS_WAIT_BUS = 0x01,
DALLAS_WAIT_DELAY = 0x02,
} DALLAS_WaitCondition;
/* Functions ---------------------------------------------------------------*/
void Dallas_Init(DALLAS_HandleTypeDef *sensor, UART_HandleTypeDef *huart);
void Dallas_ReadAll(void);
void Dallas_FirstInit(void);
HAL_StatusTypeDef Dallas_SensorInitByUserBytes(OneWire_t *onewire, DALLAS_HandleTypeDef *sensor, uint16_t UserBytes34, uint16_t UserBytes12);
HAL_StatusTypeDef Dallas_SensorInitByInd(OneWire_t *onewire, DALLAS_HandleTypeDef *sensor, uint8_t sens_ind);
HAL_StatusTypeDef Dallas_StartConvertTAll(OneWire_t *onewire, DALLAS_WaitCondition waitCondition, uint8_t dallas_delay_ms);
HAL_StatusTypeDef Dallas_ConvertT(DALLAS_HandleTypeDef *sensor, DALLAS_WaitCondition waitCondition);
HAL_StatusTypeDef Dallas_ReadTemperature(DALLAS_HandleTypeDef *sensor);
HAL_StatusTypeDef Dallas_ReadScratchpad(DALLAS_HandleTypeDef *sensor);
HAL_StatusTypeDef Dallas_WriteScratchpad(DALLAS_HandleTypeDef *sensor, uint8_t ExtendUserBytes);
HAL_StatusTypeDef Dallas_IsConnected(DALLAS_HandleTypeDef *sensor);
HAL_StatusTypeDef Dallas_ReadRom(DALLAS_HandleTypeDef *sensor);
HAL_StatusTypeDef Dallas_SkipRom(DALLAS_HandleTypeDef *sensor);
HAL_StatusTypeDef Dallas_WriteUserBytes(DALLAS_HandleTypeDef *sensor, uint16_t UserBytes12, uint16_t UserBytes34, uint8_t UserBytesMask);
#endif // #ifndef DALLAS_TOOLS_H

536
DS18B20/ds18b20.c Normal file
View File

@@ -0,0 +1,536 @@
/**
******************************************************************************
* @file ds18b20.c
* @brief This file includes the HAL/LL driver for DS18B20 1-Wire Digital
* Thermometer
******************************************************************************
*/
#include "ds18b20.h"
DS18B20_Drv_t DS;
OneWire_t OW;
/**
* @brief The function is used to check valid DS18B20 ROM
* @retval Return in OK = 1, Failed = 0
* @param ROM Pointer to ROM number
*/
HAL_StatusTypeDef DS18B20_IsValidAddress(uint8_t *ROM)
{
uint8_t check_family = (*ROM == DS18B20_FAMILY_CODE);
/* Calculate CRC */
uint8_t crc = OneWire_CRC8(ROM, 7);
uint8_t check_crc = (crc == ROM[7]);
/* Checks if first byte is equal to DS18B20's family code */
if(check_family && check_crc)
return HAL_OK;
else
return HAL_ERROR;
}
/**
* @brief The function is used to check valid DS18B20 ROM
* @retval Return in OK = 1, Failed = 0
* @param ROM Pointer to ROM number
*/
HAL_StatusTypeDef DS18B20_IsValid(uint8_t *ROM)
{
if(*ROM == DS18B20_FAMILY_CODE)
return HAL_OK;
else
return HAL_ERROR;
}
/**
* @brief The function is used to get resolution
* @retval Return value in 9 - 12
* @param OW OneWire HandleTypedef
* @param ROM Pointer to ROM number
*/
uint8_t DS18B20_GetResolution(OneWire_t* OW, uint8_t *ROM) {
uint8_t conf;
/* Check valid ROM */
if (DS18B20_IsValid(ROM) != HAL_OK)
return 0;
/* Reset line */
OneWire_Reset(OW);
/* Select ROM number */
OneWire_MatchROM(OW, ROM);
/* Read scratchpad command by onewire protocol */
OneWire_WriteByte(OW, DS18B20_CMD_READSCRATCHPAD);
/* Ignore first 4 bytes */
OneWire_ReadByte(OW);
OneWire_ReadByte(OW);
OneWire_ReadByte(OW);
OneWire_ReadByte(OW);
/* 5th byte of scratchpad is configuration register */
conf = OneWire_ReadByte(OW);
/* Return 9 - 12 value according to number of bits */
return ((conf & 0x60) >> 5) + 9;
}
/**
* @brief The function is used as set resolution
* @retval status in OK = 1, Failed = 0
* @param OW OneWire HandleTypedef
* @param ROM Pointer to ROM number
* @param Resolution Resolution in 9 - 12
*/
HAL_StatusTypeDef DS18B20_SetResolution(OneWire_t* OW, uint8_t *ROM,
DS18B20_Res_t Resolution)
{
uint8_t th, tl, conf;
/* Check valid ROM */
if (DS18B20_IsValid(ROM) != HAL_OK)
return HAL_ERROR;
/* Reset line */
OneWire_Reset(OW);
/* Select ROM number */
OneWire_MatchROM(OW, ROM);
/* Read scratchpad command by onewire protocol */
OneWire_WriteByte(OW, DS18B20_CMD_READSCRATCHPAD);
/* Ignore first 2 bytes */
OneWire_ReadByte(OW);
OneWire_ReadByte(OW);
th = OneWire_ReadByte(OW);
tl = OneWire_ReadByte(OW);
conf = OneWire_ReadByte(OW);
/* Set choosed resolution */
conf = Resolution;
/* Reset line */
OneWire_Reset(OW);
/* Select ROM number */
OneWire_MatchROM(OW, ROM);
/* Write scratchpad command by onewire protocol, only th, tl and conf
* register can be written */
OneWire_WriteByte(OW, DS18B20_CMD_WRITESCRATCHPAD);
/* Write bytes */
OneWire_WriteByte(OW, th);
OneWire_WriteByte(OW, tl);
OneWire_WriteByte(OW, conf);
/* Reset line */
OneWire_Reset(OW);
/* Select ROM number */
OneWire_MatchROM(OW, ROM);
/* Copy scratchpad to EEPROM of DS18B20 */
OneWire_WriteByte(OW, DS18B20_CMD_COPYSCRATCHPAD);
return HAL_OK;
}
/**
* @brief The function is used as start selected ROM device
* @retval status in OK = 1, Failed = 0
* @param OW OneWire HandleTypedef
* @param ROM Pointer to ROM number
*/
HAL_StatusTypeDef DS18B20_StartConvT(OneWire_t* OW, uint8_t *ROM)
{
/* Check if device is DS18B20 */
if(DS18B20_IsValid(ROM) != HAL_OK)
return HAL_ERROR;
/* Reset line */
OneWire_Reset(OW);
/* Select ROM number */
OneWire_MatchROM(OW, ROM);
/* Start temperature conversion */
OneWire_WriteByte(OW, DS18B20_CMD_CONVERT);
return HAL_OK;
}
/**
* @brief The function is used as start all ROM device
* @param OW OneWire HandleTypedef
*/
HAL_StatusTypeDef DS18B20_StartConvTAll(OneWire_t* OW)
{
/* Reset pulse */
OneWire_Reset(OW);
/* Skip rom */
OneWire_WriteByte(OW, ONEWIRE_CMD_SKIPROM);
/* Start conversion on all connected devices */
OneWire_WriteByte(OW, DS18B20_CMD_CONVERT);
return HAL_OK;
}
/**
* @brief The function is used as read temreature from device and store in selected
* destination
* @retval status in OK = 1, Failed = 0
* @param OW OneWire HandleTypedef
* @param ROM Pointer to ROM number
* @param Destination Pointer to return value
*/
HAL_StatusTypeDef DS18B20_CalcTemperature(OneWire_t* OW, uint8_t *ROM, uint8_t *Scratchpad, float *Destination)
{
uint16_t temperature;
uint8_t resolution;
int8_t digit, minus = 0;
float decimal;
/* Check if device is DS18B20 */
if (DS18B20_IsValid(ROM) != HAL_OK)
return HAL_ERROR;
/* First two bytes of scratchpad are temperature values */
temperature = Scratchpad[0] | (Scratchpad[1] << 8);
/* Reset line */
OneWire_Reset(OW);
/* Check if temperature is negative */
if (temperature & 0x8000) {
/* Two's complement, temperature is negative */
temperature = ~temperature + 1;
minus = 1;
}
/* Get sensor resolution */
resolution = Scratchpad[4];
/* Store temperature integer digits and decimal digits */
digit = temperature >> 4;
digit |= ((temperature >> 8) & 0x7) << 4;
/* Store decimal digits */
switch (resolution) {
case DS18B20_RESOLUTION_9BITS: {
decimal = (temperature >> 3) & 0x01;
decimal *= (float)DS18B20_DECIMAL_STEPS_9BIT;
} break;
case DS18B20_RESOLUTION_10BITS: {
decimal = (temperature >> 2) & 0x03;
decimal *= (float)DS18B20_DECIMAL_STEPS_10BIT;
} break;
case DS18B20_RESOLUTION_11BITS: {
decimal = (temperature >> 1) & 0x07;
decimal *= (float)DS18B20_DECIMAL_STEPS_11BIT;
} break;
case DS18B20_RESOLUTION_12BITS: {
decimal = temperature & 0x0F;
decimal *= (float)DS18B20_DECIMAL_STEPS_12BIT;
} break;
default: {
*Destination = 0;
return HAL_ERROR;
}
}
/* Check for negative part */
decimal = digit + decimal;
if (minus) {
decimal = 0 - decimal;
}
/* Set to pointer */
*Destination = decimal;
/* Return HAL_OK, temperature valid */
return HAL_OK;
}
uint8_t scratchpad_buff[8];
/**
* @brief The function is used as read scratchpad from device
* @retval status in OK = 1, Failed = 0
* @param OW OneWire HandleTypedef
* @param ROM Pointer to ROM number
* @param Destination Pointer to Scratchpad array
*/
HAL_StatusTypeDef DS18B20_ReadScratchpad(OneWire_t* OW, uint8_t *ROM, uint8_t *Scratchpad)
{
if(Scratchpad == NULL)
Scratchpad = scratchpad_buff;
/* Reset line */
OneWire_Reset(OW);
/* Select ROM number */
OneWire_MatchROM(OW, ROM);
/* Read scratchpad command by onewire protocol */
OneWire_WriteByte(OW, DS18B20_CMD_READSCRATCHPAD);
/* Get data */
for (int i = 0; i < 9; i++) {
/* Read byte by byte */
Scratchpad[i] = OneWire_ReadByte(OW);
}
/* Calculate CRC */
uint8_t crc = OneWire_CRC8(Scratchpad, 8);
/* Check if CRC is ok */
if (crc != Scratchpad[8]) {
/* CRC invalid */
return HAL_ERROR;
}
return HAL_OK;
}
/**
* @brief The function is used to wait for end of convertion
* @param OW OneWire HandleTypedef
*/
HAL_StatusTypeDef DS18B20_WaitForEndConvertion(OneWire_t* OW)
{
uint32_t tickstart = HAL_GetTick();
/* Wait until line is released, then coversion is completed */
while(OneWire_ReadBit(OW) == 0)
{
if(HAL_GetTick() - tickstart > DS18B20_DELAY_MS_MAX)
return HAL_TIMEOUT; // end of convertion has not come
}
return HAL_OK; // convertion done
}
/**
* @brief The function is used as set temperature alarm range on
* selected device
* @retval status in OK = 1, Failed = 0
* @param OW OneWire HandleTypedef
* @param ROM Pointer to ROM number
* @param Low Low temperature alarm, value > -55, 0 = reset
* @param High High temperature alarm,, value < 125, 0 = reset
*/
HAL_StatusTypeDef DS18B20_SetTempAlarm(OneWire_t* OW, uint8_t *ROM, int8_t Low,
int8_t High)
{
uint8_t tl, th, conf;
/* Check if device is DS18B20 */
if (DS18B20_IsValid(ROM) != HAL_OK)
return HAL_ERROR;
Low = ((Low < -55) || (Low == 0)) ? -55 : Low;
High = ((High > 125) || (High == 0)) ? 125 : High;
/* Reset line */
OneWire_Reset(OW);
/* Select ROM number */
OneWire_MatchROM(OW, ROM);
/* Read scratchpad command by onewire protocol */
OneWire_WriteByte(OW, DS18B20_CMD_READSCRATCHPAD);
/* Ignore first 2 bytes */
OneWire_ReadByte(OW);
OneWire_ReadByte(OW);
th = OneWire_ReadByte(OW);
tl = OneWire_ReadByte(OW);
conf = OneWire_ReadByte(OW);
th = (uint8_t)High;
tl = (uint8_t)Low;
/* Reset line */
OneWire_Reset(OW);
/* Select ROM number */
OneWire_MatchROM(OW, ROM);
/* Write scratchpad command by onewire protocol, only th, tl and conf
* register can be written */
OneWire_WriteByte(OW, DS18B20_CMD_WRITESCRATCHPAD);
/* Write bytes */
OneWire_WriteByte(OW, th);
OneWire_WriteByte(OW, tl);
OneWire_WriteByte(OW, conf);
/* Reset line */
OneWire_Reset(OW);
/* Select ROM number */
OneWire_MatchROM(OW, ROM);
/* Copy scratchpad to EEPROM of DS18B20 */
OneWire_WriteByte(OW, DS18B20_CMD_COPYSCRATCHPAD);
return HAL_OK;
}
/**
* @brief The function is used as set user bytes with mask
* @retval status in OK = 1, Failed = 0
* @param OW OneWire HandleTypedef
* @param ROM Pointer to ROM number
* @param UserBytes12 First 2 User Bytes (tHigh and tLow)
* @param UserBytes34 Second 2 User Bytes
* @param UserBytesMask Which User Bytes write, and which ignore
*/
HAL_StatusTypeDef DS18B20_WriteUserBytes(OneWire_t* OW, uint8_t *ROM, int16_t UserBytes12,
int16_t UserBytes34, uint8_t UserBytesMask)
{
uint8_t ub1, ub2, conf, ub3, ub4;
uint8_t UserByte1 = UserBytes12 & 0xFF;
uint8_t UserByte2 = UserBytes12 >> 8;
uint8_t UserByte3 = UserBytes34 & 0xFF;
uint8_t UserByte4 = UserBytes34 >> 8;
/* Check if device is DS18B20 */
if (DS18B20_IsValid(ROM) != HAL_OK)
return HAL_ERROR;
/* Reset line */
OneWire_Reset(OW);
/* Select ROM number */
OneWire_MatchROM(OW, ROM);
/* Read scratchpad command by onewire protocol */
OneWire_WriteByte(OW, DS18B20_CMD_READSCRATCHPAD);
/* Ignore first 2 bytes */
OneWire_ReadByte(OW);
OneWire_ReadByte(OW);
ub1 = OneWire_ReadByte(OW);
ub2 = OneWire_ReadByte(OW);
conf = OneWire_ReadByte(OW);
OneWire_ReadByte(OW);
ub3 = OneWire_ReadByte(OW);
ub4 = OneWire_ReadByte(OW);
/* If user bytes in mask */
if(UserBytesMask & (1<<0))
{
ub1 = UserByte1;
}
if(UserBytesMask & (1<<1))
{
ub2 = UserByte2;
}
if(UserBytesMask & (1<<2))
{
ub3 = UserByte3;
}
if(UserBytesMask & (1<<3))
{
ub4 = UserByte4;
}
/* Reset line */
OneWire_Reset(OW);
/* Select ROM number */
OneWire_MatchROM(OW, ROM);
/* Write scratchpad command by onewire protocol, only th, tl and conf
* register can be written */
OneWire_WriteByte(OW, DS18B20_CMD_WRITESCRATCHPAD);
/* Write bytes */
OneWire_WriteByte(OW, ub1);
OneWire_WriteByte(OW, ub2);
OneWire_WriteByte(OW, conf);
OneWire_WriteByte(OW, ub3);
OneWire_WriteByte(OW, ub4);
/* Reset line */
OneWire_Reset(OW);
/* Select ROM number */
OneWire_MatchROM(OW, ROM);
/* Copy scratchpad to EEPROM of DS18B20 */
OneWire_WriteByte(OW, DS18B20_CMD_COPYSCRATCHPAD);
return HAL_OK;
}
/**
* @brief The function is used as search device that had temperature alarm
* triggered and store it in DS18B20 alarm data structure
* @retval status of search, OK = 1, Failed = 0
* @param DS DS18B20 HandleTypedef
* @param OW OneWire HandleTypedef
*/
uint8_t DS18B20_AlarmSearch(DS18B20_Drv_t *DS, OneWire_t* OW)
{
uint8_t t = 0;
/* Reset Alarm in DS */
for(uint8_t i = 0; i < DS18B20_DEVICE_AMOUNT; i++)
{
for(uint8_t j = 0; j < 8; j++)
{
DS->AlmAddr[i][j] = 0;
}
}
/* Start alarm search */
while (OneWire_Search(OW, DS18B20_CMD_ALARM_SEARCH))
{
/* Store ROM of device which has alarm flag set */
OneWire_GetDevRom(OW, DS->AlmAddr[t]);
t++;
}
return (t > 0) ? 1 : 0;
}
/**
* @brief The function is used to initialize the DS18B20 sensor, and search
* for all ROM along the line. Store in DS18B20 data structure
* @retval Rom detect status, OK = 1, No Rom detected = 0
* @param DS DS18B20 HandleTypedef
* @param OW OneWire HandleTypedef
*/
HAL_StatusTypeDef DS18B20_Search(DS18B20_Drv_t *DS, OneWire_t *OW)
{
/* Search all OneWire devices ROM */
while(1)
{
/* Start searching for OneWire devices along the line */
if(OneWire_Search(OW, ONEWIRE_CMD_SEARCHROM) != 1) break;
/* Get device ROM */
OneWire_GetDevRom(OW, DS->DevAddr[OW->RomCnt]);
/* Set ROM Resolution */
DS18B20_SetResolution(OW, &OW->RomCnt, DS->Resolution);
/* Reset Temperature Alarm */
DS18B20_SetTempAlarm(OW, &OW->RomCnt, 0, 0);
OW->RomCnt++;
}
return (OW->RomCnt != 0) ? 1 : 0;
}

110
DS18B20/ds18b20.h Normal file
View File

@@ -0,0 +1,110 @@
/**
******************************************************************************
* @file ds18b20.h
* @brief This file contains all the constants parameters for the DS18B20
* 1-Wire Digital Thermometer
******************************************************************************
* @attention
* Usage:
* Uncomment LL Driver for HAL driver
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef DS18B20_H
#define DS18B20_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "onewire.h"
/* I/O Port ------------------------------------------------------------------*/
#define DS_Pin GPIO_PIN_9
#define DS_GPIO_Port GPIOA
/* Data Structure ------------------------------------------------------------*/
#define DS18B20_DEVICE_AMOUNT 8
/* Register ------------------------------------------------------------------*/
#define DS18B20_CMD_CONVERT 0x44
#define DS18B20_CMD_ALARM_SEARCH 0xEC
#define DS18B20_CMD_READSCRATCHPAD 0xBE
#define DS18B20_CMD_WRITESCRATCHPAD 0x4E
#define DS18B20_CMD_COPYSCRATCHPAD 0x48
/* Data Structure ------------------------------------------------------------*/
#define DS18B20_FAMILY_CODE 0x28
#define DS18B20_SERIAL_NUMBER_LEN_BYTES 6
#define DS18B20_SERIAL_NUMBER_OFFSET_BYTES 1
#define DS18B20_SCRATCHPAD_T_LSB_BYTE_IDX 0
#define DS18B20_SCRATCHPAD_T_MSB_BYTE_IDX 1
#define DS18B20_SCRATCHPAD_T_LIMIT_H_BYTE_IDX 2
#define DS18B20_SCRATCHPAD_T_LIMIT_L_BYTE_IDX 3
#define DS18B20_SCRATCHPAD_CONFIG_BYTE_IDX 4
#define DS18B20_SCRATCHPAD_USER_BYTE_3_IDX 6
#define DS18B20_SCRATCHPAD_USER_BYTE_4_IDX 7
#define DS18B20_SCRATCHPAD_CRC_IDX 8
/* Bits locations for resolution */
#define DS18B20_RESOLUTION_R1 6
#define DS18B20_RESOLUTION_R0 5
#define DS18B20_DECIMAL_STEPS_12BIT 0.0625
#define DS18B20_DECIMAL_STEPS_11BIT 0.125
#define DS18B20_DECIMAL_STEPS_10BIT 0.25
#define DS18B20_DECIMAL_STEPS_9BIT 0.5
#define DS18B20_DELAY_MS_9_BITS 94
#define DS18B20_DELAY_MS_10_BITS 188
#define DS18B20_DELAY_MS_11_BITS 375
#define DS18B20_DELAY_MS_12_BITS 750
#define DS18B20_DELAY_MS_MAX DS18B20_DELAY_MS_12_BITS
#define DS18B20_9_BITS_DATA_MASK 0x7F8
#define DS18B20_10_BITS_DATA_MASK 0x7FC
#define DS18B20_11_BITS_DATA_MASK 0x7FE
#define DS18B20_12_BITS_DATA_MASK 0x7FF
/* DS18B20 Resolutions */
typedef enum {
DS18B20_RESOLUTION_9BITS = 0x1F,
DS18B20_RESOLUTION_10BITS = 0x3F,
DS18B20_RESOLUTION_11BITS = 0x5F,
DS18B20_RESOLUTION_12BITS = 0x7F
} DS18B20_Res_t;
typedef struct
{
uint8_t DevAddr[DS18B20_DEVICE_AMOUNT][8];
uint8_t AlmAddr[DS18B20_DEVICE_AMOUNT][8];
float Temperature[DS18B20_DEVICE_AMOUNT];
DS18B20_Res_t Resolution;
} DS18B20_Drv_t;
extern DS18B20_Drv_t DS;
extern OneWire_t OW;
/* External Function ---------------------------------------------------------*/
HAL_StatusTypeDef DS18B20_Search(DS18B20_Drv_t *DS, OneWire_t *OW);
HAL_StatusTypeDef DS18B20_StartConvT(OneWire_t* OW, uint8_t *ROM);
HAL_StatusTypeDef DS18B20_StartConvTAll(OneWire_t* OW);
HAL_StatusTypeDef DS18B20_CalcTemperature(OneWire_t* OW, uint8_t *ROM, uint8_t *Scratchpad, float *destination);
HAL_StatusTypeDef DS18B20_ReadScratchpad(OneWire_t* OW, uint8_t *ROM, uint8_t *Scratchpad);
HAL_StatusTypeDef DS18B20_WaitForEndConvertion(OneWire_t* OW);
HAL_StatusTypeDef DS18B20_SetTempAlarm(OneWire_t* OW, uint8_t *ROM, int8_t Low,
int8_t High);
HAL_StatusTypeDef DS18B20_WriteUserBytes(OneWire_t* OW, uint8_t *ROM, int16_t UserBytes12,
int16_t UserBytes34, uint8_t UserBytesMask);
uint8_t DS18B20_AlarmSearch(DS18B20_Drv_t *DS, OneWire_t* OW);
#ifdef __cplusplus
}
#endif
#endif /* DS18B20_H */

58
DS18B20/dwt.c Normal file
View File

@@ -0,0 +1,58 @@
/**
******************************************************************************
* @file dwt.c
* @brief This file includes the utilities for DWT
******************************************************************************
*/
#include "dwt.h"
static uint32_t SysCClk, start;
/**
* @brief Initialize DWT
*/
void DwtInit(void)
{
SysCClk = (SystemCoreClock / 1000000); // Calculate in us
DWT_LAR |= DWT_LAR_UNLOCK;
DEM_CR |= (uint32_t)DEM_CR_TRCENA;
DWT_CYCCNT = (uint32_t)0u; // Reset the clock counter
DWT_CR |= (uint32_t)DWT_CR_CYCCNTENA;
}
/**
* @brief Start DWT Counter
*/
void DwtStart(void)
{
start = DWT_CYCCNT;
}
/**
* @brief Calculate Interval Base On Previous Start Time
* @retval Interval in us
*/
float DwtInterval(void)
{
return (float)(DWT_CYCCNT - start) / SysCClk;
}
/**
* @brief Function to delay in microsecond
* @param usec Period in microsecond
*/
inline void DwtDelay_us(uint32_t usec)
{
start = DWT_CYCCNT;
while(((DWT_CYCCNT - start) / SysCClk) < usec) {};
}
/**
* @brief Function to delay in millisecond
* @param msec Period in millisecond
*/
inline void DwtDelay_ms(uint32_t msec)
{
start = DWT_CYCCNT;
while(((DWT_CYCCNT - start) / SysCClk) < (msec * 1000)) {};
}

39
DS18B20/dwt.h Normal file
View File

@@ -0,0 +1,39 @@
/**
******************************************************************************
* @file dwt.h
* @brief This file contains all the constants parameters for the dwt delay
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef DWT_H
#define DWT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Custom Define -------------------------------------------------------------*/
#define DWT_LAR_UNLOCK (uint32_t)0xC5ACCE55
#define DEM_CR_TRCENA (1 << 24)
#define DWT_CR_CYCCNTENA (1 << 0)
#define DWT_CR *(volatile uint32_t *)0xE0001000
#define DWT_LAR *(volatile uint32_t *)0xE0001FB0
#define DWT_CYCCNT *(volatile uint32_t *)0xE0001004
#define DEM_CR *(volatile uint32_t *)0xE000EDFC
/* External Function ---------------------------------------------------------*/
void DwtInit(void);
void DwtStart(void);
float DwtInterval(void);
void DwtDelay_us(uint32_t usec);
void DwtDelay_ms(uint32_t msec);
#ifdef __cplusplus
}
#endif
#endif /* DWT_H */

479
DS18B20/onewire.c Normal file
View File

@@ -0,0 +1,479 @@
/**
******************************************************************************
* @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;
}

82
DS18B20/onewire.h Normal file
View File

@@ -0,0 +1,82 @@
/**
******************************************************************************
* @file onewire.h
* @brief This file contains all the constants parameters for the OneWire
******************************************************************************
* @attention
* Usage:
* Uncomment LL Driver for HAL driver
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef ONEWIRE_H
#define ONEWIRE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "dwt.h"
/* Driver Selection ----------------------------------------------------------*/
//#define LL_Driver
#define CMSIS_Driver
/* OneWire Timings -----------------------------------------------------------*/
#define ONEWIRE_RESET_PULSE_US 480 // Äëèòåëüíîñòü èìïóëüñà ñáðîñà
#define ONEWIRE_PRESENCE_WAIT_US 70 // Îæèäàíèå îòâåòà îò äàò÷èêà
#define ONEWIRE_PRESENCE_DURATION_US 410 // Äëèòåëüíîñòü ñèãíàëà ïðèñóòñòâèÿ
#define ONEWIRE_WRITE_1_US 6 // Äëèòåëüíîñòü çàïèñè "1"
#define ONEWIRE_WRITE_0_US 60 // Äëèòåëüíîñòü çàïèñè "0"
#define ONEWIRE_READ_CMD_US 5 // Âðåìÿ êîììàíäû ÷òåíèÿ áèòà
#define ONEWIRE_READ_DELAY_US 10 // Çàäåðæêà ïåðåä ñ÷èòûâàíèåì áèòà
#define ONEWIRE_RECOVERY_TIME_US 1 // Âîññòàíîâëåíèå ïåðåä ñëåäóþùèì ñëîòîì
#define ONEWIRE_COMMAND_SLOT_US 70 // Îáùåå âðåìÿ êîììàíäû OneWire
/* Common Register -----------------------------------------------------------*/
#define ONEWIRE_CMD_SEARCHROM 0xF0
#define ONEWIRE_CMD_READROM 0x33
#define ONEWIRE_CMD_MATCHROM 0x55
#define ONEWIRE_CMD_SKIPROM 0xCC
/* Data Structure ------------------------------------------------------------*/
typedef enum
{
Input,
Output
} PinMode;
typedef struct
{
uint8_t LastDiscrepancy;
uint8_t LastFamilyDiscrepancy;
uint8_t LastDeviceFlag;
uint8_t RomByte[8];
uint8_t RomCnt;
uint16_t DataPin;
GPIO_TypeDef *DataPort;
} OneWire_t;
/* External Function ---------------------------------------------------------*/
void OneWire_Init(OneWire_t* OW);
uint8_t OneWire_Search(OneWire_t* OW, uint8_t Cmd);
void OneWire_GetDevRom(OneWire_t* OW, uint8_t *dev);
uint8_t OneWire_Reset(OneWire_t* OW);
uint8_t OneWire_ReadBit(OneWire_t* OW);
uint8_t OneWire_ReadByte(OneWire_t* OW);
void OneWire_WriteByte(OneWire_t* OW, uint8_t byte);
void OneWire_MatchROM(OneWire_t* OW, uint8_t *Rom);
void OneWire_Skip(OneWire_t* OW);
uint8_t OneWire_CRC8(uint8_t *addr, uint8_t len);
void OneWire_Pin_Mode(OneWire_t* OW, PinMode Mode);
void OneWire_Pin_Level(OneWire_t* OW, uint8_t Level);
uint8_t OneWire_Pin_Read(OneWire_t* OW);
void OneWire_WriteBit(OneWire_t* OW, uint8_t bit);
#ifdef __cplusplus
}
#endif
#endif /* ONEWIRE_H */

View File

@@ -0,0 +1,230 @@
#include "onewire_it_driver.h"
#define owtim htim3
OneWire_ITHandleTypeDef honewire;
static OneWire_State ow_state = OW_IDLE;
static int32_t ow_delay_counter = 0; // Ñ÷åò÷èê âðåìåíè äëÿ çàäåðæåê
extern TIM_HandleTypeDef owtim;
extern OneWire_t OW;
void OneWireIT_Init(OneWire_ITHandleTypeDef *OW_IT) {
OW_IT->onewire = &OW;
// Ðàçðåøàåì ïðåðûâàíèå òàéìåðà
HAL_TIM_Base_Start_IT(&owtim);
}
void OneWire_AddOperation(OneWire_ITHandleTypeDef *OW_IT, void (*operation)(OneWire_t*), uint8_t *io_data_buffer)
{
uint8_t next_tail = (OW_IT->tail + 1) % OP_QUEUE_SIZE;
if (next_tail != OW_IT->head)
{ // Î÷åðåäü íå ïåðåïîëíåíà
OW_IT->operation_queue[OW_IT->tail] = operation;
OW_IT->tail = next_tail;
}
}
void OneWire_ProcessNextOperation(OneWire_ITHandleTypeDef *OW_IT) {
if (OW_IT->head != OW_IT->tail) { // Åñëè î÷åðåäü íå ïóñòà
void (*current_op)(OneWire_t*) = OW_IT->operation_queue[OW_IT->head];
current_op(OW_IT->onewire);
if(OW_IT->op_done)
{
OW_IT->op_done = 0;
OW_IT->head = (OW_IT->head + 1) % OP_QUEUE_SIZE; // Ïåðåõîäèì ê ñëåäóþùåé îïåðàöèè
}
}
}
void OneWireTIMHandler(TIM_HandleTypeDef *htim, OneWire_ITHandleTypeDef *OW_IT)
{
if (htim == &owtim)
{
if (ow_delay_counter > 0)
{
ow_delay_counter -= ONE_WIRE_TIMER_PERIOD_US; // Óìåíüøàåì ñ÷åò÷èê çàäåðæêè
}
OneWire_Reset_ITHandle(OW_IT->onewire);
// OneWire_ProcessNextOperation(OW_IT);
}
}
void OneWire_WriteBytes_IT(OneWire_ITHandleTypeDef *OW_IT)
{
static HAL_StatusTypeDef res;
if (OW_IT->current_byte_idx < OW_IT->data_len) // Åñëè íå îáðàáîòàíû âñå äàííûå
{
uint8_t byte = OW_IT->data[OW_IT->current_byte_idx]; // Áåðåì òåêóùèé áàéò äàííûõ
for (OW_IT->current_bit_idx = 0; OW_IT->current_bit_idx < 8; OW_IT->current_bit_idx++)
{
uint8_t bit = (byte >> (7 - OW_IT->current_bit_idx)) & 0x01; // Ïîëó÷àåì áèò èç áàéòà
OneWire_WriteBit_ITHandle(OW_IT->onewire, bit); // Ïèøåì ýòîò áèò â OneWire
}
OW_IT->current_byte_idx++; // Ïåðåõîäèì ê ñëåäóþùåìó áàéòó
}
else
{
OW_IT->current_byte_idx = 0; // Çàâåðøàåì îïåðàöèþ çàïèñè
OW_IT->op_done = 1;
}
}
void OneWire_ReadBytes_IT(OneWire_ITHandleTypeDef *OW_IT)
{
uint8_t bit;
if (OW_IT->current_byte_idx < OW_IT->data_len) // Åñëè íå îáðàáîòàíû âñå äàííûå
{
uint8_t byte = 0; // Äëÿ õðàíåíèÿ ïðî÷èòàííîãî áàéòà
for (OW_IT->current_bit_idx = 0; OW_IT->current_bit_idx < 8; OW_IT->current_bit_idx++)
{
OneWire_ReadBit_ITHandle(OW_IT->onewire, &bit); // ×èòàåì áèò
byte |= (bit << (7 - OW_IT->current_bit_idx)); // Ñîáèðàåì áàéò èç áèòîâ
}
OW_IT->data[OW_IT->current_byte_idx] = byte; // Ñîõðàíÿåì áàéò â áóôåð
OW_IT->current_byte_idx++; // Ïåðåõîäèì ê ñëåäóþùåìó áàéòó
}
else
{
OW_IT->current_byte_idx = 0; // Çàâåðøàåì îïåðàöèþ ÷òåíèÿ
OW_IT->head = (OW_IT->head + 1) % OP_QUEUE_SIZE; // Óáèðàåì âûïîëíåííóþ îïåðàöèþ èç î÷åðåäè
}
}
HAL_StatusTypeDef OneWire_ReadBit_ITHandle(OneWire_t *OW, uint8_t *bit) {
static uint8_t read_bit_step = 0;
switch (read_bit_step)
{
case 0:
// Ñíèæàåì ïèí íà 1 ìêñ äëÿ íà÷àëà ïåðåäà÷è áèòà
OneWire_Pin_Level(OW, 0);
OneWire_Pin_Mode(OW, Output);
ow_delay_counter = ONEWIRE_READ_CMD_US; // Çàäåðæêà 1 ìêñ äëÿ ÷òåíèÿ áèòà
read_bit_step++;
return HAL_BUSY;
case 1:
// Ïîäíèìàåì ïèí è ïðîâåðÿåì ñîñòîÿíèå äëÿ ÷òåíèÿ áèòà
if (ow_delay_counter <= 0)
{
OneWire_Pin_Mode(OW, Input);
ow_delay_counter = ONEWIRE_READ_DELAY_US; // Çàäåðæêà ïåðåä ñ÷èòûâàíèåì
read_bit_step++;
}
return HAL_BUSY;
case 2:
// ×èòàåì ïèí íà 1 ìêñ äëÿ îïðåäåëåíèÿ áèòà
if (ow_delay_counter <= 0)
{
*bit = OneWire_Pin_Read(OW);
ow_delay_counter = ONEWIRE_COMMAND_SLOT_US - ONEWIRE_READ_CMD_US - ONEWIRE_READ_DELAY_US;
}
return HAL_BUSY;
case 3:
read_bit_step = 0; // Çàâåðøàåì êîìàíäó ÷òåíèÿ
ow_state = OW_IDLE;
return HAL_OK;
default:
read_bit_step = 3;
return HAL_ERROR;
}
}
HAL_StatusTypeDef OneWire_WriteBit_ITHandle(OneWire_t *OW, uint8_t bit)
{
static uint8_t write_bit_step = 0;
switch (write_bit_step)
{
case 0:
// Ïèøåì áèò 0 èëè 1
OneWire_Pin_Level(OW, 0);
OneWire_Pin_Mode(OW, Output);
if (bit)
{
ow_delay_counter = ONEWIRE_WRITE_1_US; // Çàäåðæêà ìêñ äëÿ çàïèñè 1
}
else
{
ow_delay_counter = ONEWIRE_WRITE_0_US; // Çàäåðæêà ìêñ äëÿ çàïèñè 0
}
write_bit_step++;
return HAL_BUSY;
case 1:
// Çàâåðøàåì çàïèñü, ïîäíèìàåì ïèí
if (ow_delay_counter == 0)
{
OneWire_Pin_Mode(OW, Input);
if (bit) {
ow_delay_counter = ONEWIRE_COMMAND_SLOT_US - ONEWIRE_WRITE_1_US; // Çàäåðæêà ìêñ äëÿ çàâåðøåíèÿ çàïèñè 1
}
else
{
ow_delay_counter = ONEWIRE_COMMAND_SLOT_US - ONEWIRE_WRITE_0_US; // Çàäåðæêà ìêñ äëÿ çàâåðøåíèÿ çàïèñè 0
}
write_bit_step++;
}
return HAL_BUSY;
case 2:
OneWire_Pin_Mode(OW, Input);
// Çàâåðøàåì çàïèñü
write_bit_step = 0;
ow_state = OW_IDLE;
return HAL_OK;
default:
write_bit_step = 2;
return HAL_ERROR;
}
}
HAL_StatusTypeDef OneWire_Reset_ITHandle(OneWire_t *OW)
{
static uint8_t reset_step = 0;
static uint8_t rslt = 0;
GPIOC->ODR ^= (1<<13);
switch (reset_step)
{
case 0:
// Íà÷àëî êîìàíäû Reset - îïóñêàåì ïèí íà 480 ìêñ
OneWire_Pin_Level(OW, 0);
OneWire_Pin_Mode(OW, Output);
ow_delay_counter = ONEWIRE_RESET_PULSE_US; // Óñòàíàâëèâàåì çàäåðæêó â 480 ìêñ
reset_step++;
return HAL_BUSY;
case 1:
// Ïðîâåðÿåì, ïðîøëà ëè çàäåðæêà 480 ìêñ
if (ow_delay_counter <= 0)
{
/* Release line and wait for 70us */
OneWire_Pin_Mode(OW, Input);
ow_delay_counter = ONEWIRE_PRESENCE_WAIT_US; // Óñòàíàâëèâàåì çàäåðæêó íà 70 ìêñ
reset_step++;
}
return HAL_BUSY;
case 2:
// Æäåì îòâåòà îò óñòðîéñòâà íà ïîäíÿòèå ïèíà
if (ow_delay_counter <= 0)
{
// ×èòàåì ïèí, åñëè óñòðîéñòâî îòâåòèëî
uint8_t rslt = OneWire_Pin_Read(OW);
reset_step++;
}
return HAL_BUSY;
case 3:
reset_step = 0; // Çàâåðøàåì êîìàíäó Reset
ow_delay_counter = ONEWIRE_PRESENCE_DURATION_US; // Óñòàíàâëèâàåì çàäåðæêó íà 70 ìêñ
ow_state = OW_IDLE;
return HAL_OK;
default:
reset_step = 3;
return HAL_ERROR;
}
}

View File

@@ -0,0 +1,51 @@
/**
******************************************************************************
* @file onewire.h
* @brief This file contains all the constants parameters for the OneWire
******************************************************************************
* @attention
* Usage:
* Uncomment LL Driver for HAL driver
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef ONEWIRE_IT_DRIVER_H
#define ONEWIRE_IT_DRIVER_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx.h"
#include "onewire.h"
#define ONE_WIRE_TIMER_PERIOD_US 1 // Ïåðèîä òàéìåðà â ìèêðîñåêóíäàõ (1 ìêñ)
#define OP_QUEUE_SIZE 10 // Áóôåð îïåðàöèé OneWire
typedef enum {
OW_RESET,
OW_READ_BIT,
OW_SET_BIT,
OW_RESET_BIT,
OW_IDLE
} OneWire_State;
typedef struct
{
OneWire_t *onewire;
uint8_t *data; // Áóôåð äëÿ äàííûõ (äëÿ çàïèñè è ÷òåíèÿ)
uint8_t data_len; // Äëèíà äàííûõ
uint8_t current_byte_idx; // Èíäåêñ òåêóùåãî áàéòà äëÿ çàïèñè/÷òåíèÿ
uint8_t current_bit_idx; // Èíäåêñ òåêóùåãî áèòà äëÿ çàïèñè/÷òåíèÿ
uint8_t head; // Èíäåêñ ïåðâîé îïåðàöèè â î÷åðåäè
uint8_t tail; // Èíäåêñ ïîñëåäíåé îïåðàöèè â î÷åðåäè
uint8_t op_done; // Èíäåêñ ïîñëåäíåé îïåðàöèè â î÷åðåäè
void (*operation_queue[OP_QUEUE_SIZE])(OneWire_t*); // Î÷åðåäü îïåðàöèé
}OneWire_ITHandleTypeDef;
extern OneWire_ITHandleTypeDef honewire;
void OneWireTIMHandler(TIM_HandleTypeDef *htim, OneWire_ITHandleTypeDef *OW);
void OneWireIT_Init(OneWire_ITHandleTypeDef *OW_IT);
HAL_StatusTypeDef OneWire_ReadBit_ITHandle(OneWire_t *OW, uint8_t *bit);
HAL_StatusTypeDef OneWire_WriteBit_ITHandle(OneWire_t *OW, uint8_t bit);
HAL_StatusTypeDef OneWire_Reset_ITHandle(OneWire_t *OW);
#endif /* ONEWIRE_IT_DRIVER_H */

View File

@@ -0,0 +1,159 @@
/**
******************************************************************************
* @file : onewire_uart.c
* @brief : Драйвер для работы с шиной 1-Wire через UART
* @author : MicroTechnics (microtechnics.ru)
******************************************************************************
@details
Этот файл реализует базовые функции для работы с 1-Wire через UART.
Он включает в себя методы для передачи и приёма битов и байтов, а также
выполнение reset-команды для устройств 1-Wire.
UART передает специально сформированные импульсы, эмулируя 1-Wire.
*****************************************************************************/
/* Includes ----------------------------------------------------------------*/
#include "onewire_uart.h"
/* Declarations and definitions --------------------------------------------*/
/* Functions ---------------------------------------------------------------*/
/**
* @brief Устанавливает скорость передачи данных для UART.
* @param huart Указатель на структуру UART
* @param baudrate Требуемая скорость передачи (бит/с)
* @details Функция изменяет скорость передачи UART в зависимости от используемой шины
* (PCLK1 или PCLK2). Это важно для эмуляции временных параметров 1-Wire.
*/
static void UARTSetBaudrate(UART_HandleTypeDef *huart, uint32_t baudrate)
{
uint32_t pclk = 0;
huart->Init.BaudRate = baudrate;
#if defined(USART6) && defined(UART9) && defined(UART10)
if ((huart->Instance == USART1) || (huart->Instance == USART6) ||
(huart->Instance == UART9) || (huart->Instance == UART10))
{
pclk = HAL_RCC_GetPCLK2Freq();
}
#elif defined(USART6)
if ((huart->Instance == USART1) || (huart->Instance == USART6))
{
pclk = HAL_RCC_GetPCLK2Freq();
}
#else
if (huart->Instance == USART1)
{
pclk = HAL_RCC_GetPCLK2Freq();
}
#endif /* USART6 */
else
{
pclk = HAL_RCC_GetPCLK1Freq();
}
#if defined(USART_CR1_OVER8)
if (huart->Init.OverSampling == UART_OVERSAMPLING_8)
{
huart->Instance->BRR = UART_BRR_SAMPLING8(pclk, huart->Init.BaudRate);
}
else
{
huart->Instance->BRR = UART_BRR_SAMPLING16(pclk, huart->Init.BaudRate);
}
#else
huart->Instance->BRR = UART_BRR_SAMPLING16(pclk, huart->Init.BaudRate);
#endif /* USART_CR1_OVER8 */
}
/**
* @brief Передает и принимает один бит через 1-Wire.
* @param huart Указатель на структуру UART
* @param bit Бит для передачи (0 или 1)
* @return Полученный бит (0 или 1)
* @details Передача осуществляется отправкой специального импульса, длина которого определяет передаваемый бит.
* Ответное значение читается сразу после передачи.
*/
uint8_t OneWireUART_ProcessBit(UART_HandleTypeDef *huart, uint8_t bit)
{
uint8_t txData;
uint8_t rxData = 0x00;
if (bit == 1)
{
txData = ONEWIRE_PULSE_SHORT; // Короткий импульс для передачи '1'
}
else
{
txData = ONEWIRE_PULSE_LONG; // Длинный импульс для передачи '0'
}
HAL_UART_Transmit(huart, &txData, 1, ONEWIRE_UART_TIMEOUT);
HAL_UART_Receive(huart, &rxData, 1, ONEWIRE_UART_TIMEOUT);
return rxData;
}
/**
* @brief Передает и принимает байт через 1-Wire.
* @param huart Указатель на структуру UART
* @param byte Отправляемый байт
* @return Принятый байт
* @details Отправляет 8 бит последовательно, используя @ref OneWire_ProcessBit.
* Каждый полученный бит собирается в байт и возвращается.
*/
uint8_t OneWireUART_ProcessByte(UART_HandleTypeDef *huart, uint8_t byte)
{
uint8_t rxByte = 0x00;
uint8_t txBit = 0;
uint8_t rxBit = 0;
for (uint8_t i = 0; i < ONEWIRE_BITS_NUM; i++)
{
txBit = (byte >> i) & 0x01; // Извлекаем очередной бит для отправки
uint8_t tempRxData = OneWireUART_ProcessBit(huart, txBit);
if (tempRxData == 0xFF)
{
rxBit = 1; // В случае высокого уровня на линии интерпретируем как '1'
}
else
{
rxBit = 0;
}
rxByte |= (rxBit << i); // Собираем принятые биты в байт
}
return rxByte;
}
/**
* @brief Выполняет 1-Wire Reset и проверяет наличие устройств на шине.
* @param huart Указатель на структуру UART
* @return HAL Status
* @details Процедура Reset требует изменения скорости UART, чтобы сформировать
* большой по длительности импульс сброса. Если устройство ответило, шина в рабочем состоянии.
*/
HAL_StatusTypeDef OneWireUART_Reset(UART_HandleTypeDef *huart)
{
HAL_StatusTypeDef status = HAL_OK;
uint8_t txByte = ONEWIRE_RESET;
uint8_t rxByte = 0x00;
UARTSetBaudrate(huart, ONEWIRE_RESET_BAUDRATE); // Устанавливаем низкую скорость для Reset-импульса
HAL_UART_Transmit(huart, &txByte, 1, ONEWIRE_UART_TIMEOUT);
HAL_UART_Receive(huart, &rxByte, 1, ONEWIRE_UART_TIMEOUT);
UARTSetBaudrate(huart, ONEWIRE_BAUDRATE); // Возвращаем стандартную скорость
if (rxByte == txByte)
{
status = HAL_ERROR; // Если ответ совпадает с отправленным байтом, значит, устройств нет
}
return status;
}

View File

@@ -0,0 +1,61 @@
/**
******************************************************************************
* @file : onewire_uart.h
* @brief : 1-Wire driver
* @author : MicroTechnics (microtechnics.ru)
*****************************************************************************/
#ifndef ONEWIRE_UART_H
#define ONEWIRE_UART_H
/* Includes ----------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
/* Declarations and definitions --------------------------------------------*/
extern UART_HandleTypeDef huart1;
#define onewire_uart (&huart1)
#define ONEWIRE_BAUDRATE 115200
#define ONEWIRE_RESET_BAUDRATE 9600
#define ONEWIRE_UART_TIMEOUT 10
#define ONEWIRE_BITS_NUM 8
/**
* @brief Êîììàíäû OneWire
* @details Îïðåäåëÿåò áàéòû äëÿ uart, êîòîðûå áóäóò
* ôîðìèðîâàòü íåîáõîäèìóþ äëèíó èìïóëüñà äëÿ ðàçíûõ êîììàíä
*/
typedef enum
{
ONEWIRE_RESET = 0xF0, /*!< @brief Èìïóëüñ äëèíîé 520ìêñ äëÿ êîìàíäû Reset (9600bod)
@details 1-Wire òðåáóåò èìïóëüñ äëèòåëüíîñòüþ >480ìêñ */
ONEWIRE_PULSE_SHORT = 0xFF, /*!< @brief Èìïóëüñ äëèíîé 8.7 ìêñ äëÿ çàïèñè "1"/÷òåíèÿ áèòà (115200bod)
@details 1-Wire òðåáóåò èìïóëüñ äëèòåëüíîñòüþ 1-15ìêñ */
ONEWIRE_PULSE_LONG = 0x00, /*!< @brief èìïóëüñ äëèíîé 78.3 ìêñ äëÿ çàïèñè "0" (115200bod)
@details 1-Wire òðåáóåò èìïóëüñ äëèòåëüíîñòüþ 60-120ìêñ */
// ONEWIRE_PULSE_1_15US = 0xFF,
// ONEWIRE_PULSE_60_120US = 0x00,
}ONEWIRE_Commands;
/* Functions ---------------------------------------------------------------*/
/* Âûïîëíÿåò 1-Wire Reset è ïðîâåðÿåò íàëè÷èå óñòðîéñòâ íà øèíå */
HAL_StatusTypeDef OneWireUART_Reset(UART_HandleTypeDef *huart);
/* Ïåðåäàåò è ïðèíèìàåò áàéò ÷åðåç 1-Wire */
uint8_t OneWireUART_ProcessByte(UART_HandleTypeDef *huart, uint8_t byte);
/* Ïåðåäàåò è ïðèíèìàåò îäèí áèò ÷åðåç 1-Wire */
uint8_t OneWireUART_ProcessBit(UART_HandleTypeDef *huart, uint8_t bit);
#endif // #ifndef ONEWIRE_UART_H