Спросил дика ЗЫ: ну не понимаю, как код тут оформить, со всякими
тегами вставлял. ЗЗЫ: попросил на основе таблицы сделать -
переписал послушно и тоже разумно. Напиши программу на С для обработки квадратурного энкодера в условиях сильных помех
Неплохой вариант
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
// Параметры фильтра
#define FILTER_ORDER 4
#define DEBOUNCE_THRESHOLD 3
// Глобальные переменные для хранения состояния энкодера
volatile int32_t encoder_count = 0;
volatile uint8_t last_state = 0;
volatile uint8_t debounce_counter = 0;
// Функция для чтения текущего состояния энкодера (A и B каналы)
uint8_t read_encoder_state()
{
// Здесь должен быть код для чтения состояния пинов энкодера
// Например, для A и B каналов:
// uint8_t state = (PINB & 0x03); // Чтение первых двух битов порта B
// return state;
return 0; // Заглушка, замените на реальное чтение
}
// Функция для применения цифрового фильтра
uint8_t apply_filter(uint8_t new_state)
{
static uint8_t filter_buffer[FILTER_ORDER];
static uint8_t filter_index = 0;
// Добавляем новое значение в буфер
filter_buffer[filter_index] = new_state;
filter_index = (filter_index + 1) % FILTER_ORDER;
// Подсчитываем количество одинаковых значений в буфере
uint8_t count = 0;
for(uint8_t i = 0; i < FILTER_ORDER; i++)
{
if(filter_buffer[i] == new_state)
{
count++;
}
}
// Если количество одинаковых значений превышает порог, возвращаем новое состояние
if(count >= FILTER_ORDER / 2)
{
return new_state;
}
// Иначе возвращаем предыдущее состояние
return last_state;
}
// Функция для обработки сигналов энкодера
void process_encoder()
{
uint8_t current_state = read_encoder_state();
uint8_t filtered_state = apply_filter(current_state);
// Подавление дребезга
if(filtered_state != last_state)
{
debounce_counter++;
if(debounce_counter >= DEBOUNCE_THRESHOLD)
{
// Определение направления вращения
uint8_t state_change = (last_state << 2) | filtered_state;
switch(state_change)
{
case 0b0001:
case 0b0111:
case 0b1110:
case 0b1000:
encoder_count++; // Вращение по часовой стрелке
break;
case 0b0010:
case 0b1011:
case 0b1101:
case 0b0100:
encoder_count--; // Вращение против часовой стрелки
break;
default:
// Некорректное изменение состояния, игнорируем
break;
}
last_state = filtered_state;
debounce_counter = 0;
}
}
else
{
debounce_counter = 0;
}
}
int main()
{
// Инициализация (настройка пинов, таймеров и т.д.)
// ...
while(1)
{
// Основной цикл обработки
process_encoder();
// Вывод текущего значения счетчика энкодера
printf("Encoder count: %ld\n", encoder_count);
// Задержка для имитации работы в реальном времени
// (в реальной системе это может быть реализовано через прерывания)
// ...
}
return 0;
}