Первая итерация
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
# Драйвер инкрементального энкодера DS_Encoder
|
||||
|
||||
Универсальный драйвер для подсчета шагов и определения направления вращения инкрементального энкодера (например, популярного EC11). Поддерживает два независимых режима работы: **аппаратный** (через Encoder Mode таймера STM32) и **программный** (через ручной опрос пинов GPIO).
|
||||
|
||||
## 📌 Особенности реализации
|
||||
* **Двойная архитектура**: выбор между аппаратным декодированием таймером и программным сканированием пинов на лету.
|
||||
* **Аппаратное подавление дребезга**: при использовании таймера задействуются встроенные цифровые фильтры STM32.
|
||||
* **Квантование шага**: в аппаратном режиме учтена специфика энкодеров EC11 — счетчик автоматически делится на 4, возвращая ровно 1 шаг за один физический щелчок ручки.
|
||||
|
||||
---
|
||||
|
||||
## 🛠 Вариант 1: Аппаратный режим (Рекомендуемый)
|
||||
|
||||
Данный режим использует периферию таймера микроконтроллера. Процессор не тратит ресурсы на опрос пинов.
|
||||
|
||||
### Настройка в STM32CubeMX:
|
||||
1. Выберите таймер (например, `TIM1` или `TIM2`).
|
||||
2. В поле **Combined Channels** установите значение **Encoder Mode**.
|
||||
3. В параметрах таймера (`Parameter Settings`):
|
||||
* **Encoder Mode**: `Encoder Mode TI1 and TI2` (подсчет по обоим каналам для максимальной точности).
|
||||
* **Input Filter**: установите значение от `8` до `15` для аппаратного подавления дребезга контактов.
|
||||
4. Настройте соответствующие пины `TIMx_CH1` и `TIMx_CH2` в режим `GPIO_AF`.
|
||||
|
||||
### Пример кода в `main.c`:
|
||||
```c
|
||||
#include "Encoder.h"
|
||||
|
||||
extern TIM_HandleTypeDef htim1;
|
||||
DS_Encoder volume_encoder;
|
||||
|
||||
int main(void) {
|
||||
// ... Инициализация HAL, GPIO, TIM ...
|
||||
|
||||
/* Инициализируем энкодер в режиме таймера */
|
||||
DS_EncoderInitTim(&volume_encoder, &htim1);
|
||||
|
||||
while (1) {
|
||||
/* Получаем изменение положения с момента предыдущего опроса */
|
||||
int8_t diff = DS_EncoderGetState(&volume_encoder);
|
||||
|
||||
if (diff != 0) {
|
||||
// Ручку повернули! diff может быть равен +1, -1, +2 и т.д.
|
||||
// Применяем изменение, например: volume += diff;
|
||||
}
|
||||
|
||||
HAL_Delay(50); // Опрос можно делать с любой редкой периодичностью
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🕹 Вариант 2: Программный режим (Polling)
|
||||
|
||||
Используется, если на плате нет свободных каналов таймера с поддержкой Encoder Mode. Пин 1 и Пин 2 настраиваются как обычные `GPIO_Input` с подтяжкой `Pull-up`.
|
||||
|
||||
### Пример кода в `main.c`:
|
||||
```c
|
||||
#include "Encoder.h"
|
||||
|
||||
DS_Encoder manual_encoder;
|
||||
|
||||
int main(void) {
|
||||
// ... Инициализация ...
|
||||
|
||||
/* Инициализация структуры программными пинами */
|
||||
DS_EncoderInit(&manual_encoder, GPIOB, GPIO_PIN_4, GPIOB, GPIO_PIN_5);
|
||||
|
||||
while (1) {
|
||||
/* ВАЖНО: Функция обновления состояния должна вызываться как можно чаще
|
||||
(в основном цикле без больших задержек или в быстром таймере) */
|
||||
DS_EncoderUpdate(&manual_encoder);
|
||||
|
||||
/* Проверяем, накопились ли шаги вращения */
|
||||
int8_t steps = DS_EncoderGetState(&manual_encoder);
|
||||
if (steps != 0) {
|
||||
// Обработка программного поворота ручки
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Справочник API функций
|
||||
|
||||
### `void DS_EncoderInitTim(DS_Encoder *Encoder, TIM_HandleTypeDef *hTim)`
|
||||
Инициализирует и запускает таймер в режиме аппаратного декодера энкодера.
|
||||
* **`hTim`**: Указатель на структуру таймера HAL (например, `&htim1`).
|
||||
|
||||
### `void DS_EncoderInit(DS_Encoder *Encoder, GPIO_TypeDef *PortEncSignal1, uint16_t PinEncSignal1, GPIO_TypeDef *PortEncSignal2, uint16_t PinEncSignal2)`
|
||||
Конфигурирует структуру для программного отслеживания уровней на указанных GPIO портах и пинах.
|
||||
|
||||
### `void DS_EncoderUpdate(DS_Encoder *Encoder)`
|
||||
Конечный автомат программного парсинга квадратурного сигнала. Опрашивает физическое состояние пинов. Требует высокой частоты вызова.
|
||||
|
||||
### `int8_t DS_EncoderGetState(DS_Encoder *Encoder)`
|
||||
Возвращает относительное изменение положения энкодера (количество шагов) с момента последнего вызова этой функции и **автоматически обнуляет** внутренний накопительный счетчик.
|
||||
Reference in New Issue
Block a user