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