From 6d5c91cb2353fecc4b2a3a34031034f42efcdd6c Mon Sep 17 00:00:00 2001 From: Razvalyaev Date: Fri, 23 Oct 2026 13:57:08 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A3=D1=81=D1=82=D1=80=D0=B0=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BC=D1=91=D1=80=D1=82=D0=B2=D0=B0=D1=8F=20?= =?UTF-8?q?=D0=B7=D0=BE=D0=BD=D0=B0=20=D1=8D=D0=BD=D0=BA=D0=BE=D0=B4=D0=B5?= =?UTF-8?q?=D1=80=D0=B0=20=D0=BF=D1=80=D0=B8=20=D1=80=D0=B5=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D1=81=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Фаза фиксации передаётся в Encoder_Init явно и не зависит от положения контактов при включении. Для режимов с двумя и четырьмя переходами детент завершается только на заданных границах; повреждённый остаток сбрасывается при возвращении к ним. Сохранён счётчик недопустимых переходов. Проверены старт во всех фазах, дребезг, реверсы и восстановление после пропуска переходов в host-тестах основного проекта; измерения установленного энкодера не выполнялись. --- Inc/general_encoder.h | 5 +++-- Src/general_encoder.c | 24 +++++++++++++++++++++--- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/Inc/general_encoder.h b/Inc/general_encoder.h index ee97247..b4cdb25 100644 --- a/Inc/general_encoder.h +++ b/Inc/general_encoder.h @@ -23,16 +23,17 @@ typedef struct uint16_t pin_a; uint16_t pin_b; uint8_t state; + uint8_t detent_state; uint8_t steps_per_detent; int8_t partial_steps; uint32_t invalid_transitions; } Encoder_HandleTypeDef; -/** Привязать настроенные GPIO A/B; steps_per_detent — от 1 до 4. */ +/** Привязать GPIO A/B; detent_state задаёт фазу фиксации, не фазу включения. */ HAL_StatusTypeDef Encoder_Init(Encoder_HandleTypeDef *encoder, GPIO_TypeDef *port_a, uint16_t pin_a, GPIO_TypeDef *port_b, uint16_t pin_b, - unsigned steps_per_detent); + unsigned steps_per_detent, unsigned detent_state); /** Самостоятельно опросить GPIO, обработать фазы и вернуть -1, 0 или +1 детент. */ int Encoder_Update(Encoder_HandleTypeDef *encoder); diff --git a/Src/general_encoder.c b/Src/general_encoder.c index efd1759..fef2562 100644 --- a/Src/general_encoder.c +++ b/Src/general_encoder.c @@ -22,16 +22,17 @@ static uint8_t read_phases(const Encoder_HandleTypeDef *encoder) * @brief Подготовить независимый экземпляр энкодера к опросу. * @details Входы предварительно настраивает CubeMX или вызывающий код. * Начальный снимок предотвращает событие при включении питания. - * Число переходов задаётся механикой конкретного энкодера. + * Число переходов и фаза фиксации заданы конфигурацией энкодера. + * Промежуточное положение при включении не становится фазой фиксации. * @return HAL_OK при успехе, HAL_ERROR при неверной конфигурации. */ HAL_StatusTypeDef Encoder_Init(Encoder_HandleTypeDef *encoder, GPIO_TypeDef *port_a, uint16_t pin_a, GPIO_TypeDef *port_b, uint16_t pin_b, - unsigned steps_per_detent) + unsigned steps_per_detent, unsigned detent_state) { if (!encoder || !port_a || !port_b || !pin_a || !pin_b || - !steps_per_detent || steps_per_detent > 4U) + !steps_per_detent || steps_per_detent > 4U || detent_state > 3U) { return HAL_ERROR; } @@ -40,6 +41,7 @@ HAL_StatusTypeDef Encoder_Init(Encoder_HandleTypeDef *encoder, encoder->pin_a = pin_a; encoder->pin_b = pin_b; encoder->state = read_phases(encoder); + encoder->detent_state = (uint8_t)detent_state; encoder->steps_per_detent = (uint8_t)steps_per_detent; encoder->partial_steps = 0; encoder->invalid_transitions = 0U; @@ -50,6 +52,9 @@ HAL_StatusTypeDef Encoder_Init(Encoder_HandleTypeDef *encoder, * @brief Превратить последовательность фаз в законченный шаг вращения. * @details Обратные переходы компенсируют дребезг. Одновременная смена обеих * фаз обрывает незавершённый детент и учитывается как пропуск опроса. + * Для 4/2 переходов шаг завершается только в опорной/противоположной + * фазе покоя. Возврат к ней сбрасывает остаток повреждённого детента: + * пропуск не сдвигает последующие шаги и не создаёт люфт при реверсе. * Функция сама читает оба GPIO; вызывающий код задаёт частоту опроса. */ int Encoder_Update(Encoder_HandleTypeDef *encoder) @@ -71,6 +76,19 @@ int Encoder_Update(Encoder_HandleTypeDef *encoder) return 0; } encoder->partial_steps += direction[previous * 4U + state]; + if (encoder->steps_per_detent == 4U || encoder->steps_per_detent == 2U) + { + int step; + if (state != encoder->detent_state && + !(encoder->steps_per_detent == 2U && state == (encoder->detent_state ^ 3U))) + { + return 0; + } + step = encoder->partial_steps >= (int)encoder->steps_per_detent ? 1 : + encoder->partial_steps <= -(int)encoder->steps_per_detent ? -1 : 0; + encoder->partial_steps = 0; + return step; + } if (encoder->partial_steps >= (int)encoder->steps_per_detent) { encoder->partial_steps -= (int8_t)encoder->steps_per_detent;