Похожую задачу решает декодер RC-5, ресурсов при этом тратит минимум: //----------------------------------------------------------------------------
//Декодер RC-5
//----------------------------------------------------------------------------
//Декодер использует два прерывания: внешнее от фотоприемника и
//прерывание по переполнению таймера 0.
//После того, как обнаружен стартовый бит (переход из единицы
//в ноль на входе прерывания), в обработчике внешнего прерывания
//разрешается прерывание таймера 0 и загружается интервал до первой
//выборки T_SAMPLE. В прерывании таймера 0 делаются выборки для
//каждной половинки бита. Подсчет выборок ведется в переменной SampCnt.
//Количество выборок задается константой SAMPLE_COUNT.
//Логический уровень для каждой половинки бита вычисляется по
//мажоритарному принципу. Для этого вычисляется сумма выборок
//в переменной SampVal. Если на входе обнаруживается ВЫСОКИЙ уровень,
//то к этой переменной добавляется единица, если НИЗКИЙ - вычитается.
//Значение суммы не может быть равно нулю, так как общее количество
//выборок всегда задается нечетным. По первой половине текущего бита
//принимается решение о значении принятого бита. Для проверки
//корректности кода Манчестер этот уровень сравнивается со значением
//второй половины предыдущего бита, которое сохраняется в переменной
//PreVal. Если значения совпадают, была ошибка, и прием начинается
//с начала. То же самое происходит, если очередной переход на входе
//не обнаружен через время T_SAMPLE * 2 после последней выборки
//(ошибка таймаута). Принятые биты вдвигаются в переменную Rc5Code.
//Подсчет принятых битов осуществляется в переменной BitCounter.
//Когда принято RC5_LENGTH битов, прием завершен, номер системы
//копируется в переменную SysVar, а код команды - в переменную ComVar.
//Декодер поддерживает Extended RC-5 Code, второй стартовый бит
//интерпретируется как бит F (Field). Бит F представляет собой
//инвертированный дополнительный (старший) бит кода команды,
//в результате количество команд удваивается.
//----------------------------------------------------------------------------
#include "Main.h"
#include "RC5.h"
//----------------------------- Константы: -----------------------------------
#define PRE            64 //предделитель таймера 0
#define RC5_SLOT     1778 //длительность слота RC-5, мкс
#define RC5_LENGTH     14 //количество принимаемых битов
#define SAMPLE_COUNT    3 //количество выборок (должно быть нечетным)
#define T_SAMPLE_US (RC5_SLOT / ((SAMPLE_COUNT + 1) * 2))
#define T_SAMPLE    (T_SAMPLE_US * F_CLK / PRE + 0.5)
//----------------------------- Переменные: ----------------------------------
static char SampCnt;        //счетчик выборок
static signed char SampVal; //сумма выборок
static bool PreVal;         //значение предыдущего полуинтервала
static int RC5Code;         //принятый код
static char BitCounter;     //счетчик принятых битов
static char SysVar;         //номер системы
static char ComVar;         //код команды
//-------------------------- Прототипы функций: ------------------------------
#pragma vector = INT0_vect
__interrupt void EdgeIR(void);   //прерывание по сигналу фотоприемника
#pragma vector = TIMER0_OVF_vect
__interrupt void TimerIR(void);  //прерывание таймера 0
//----------------- Инициализация модуля декодера RC-5: ----------------------
void RC5_Init(void)
{
  BitCounter = RC5_LENGTH;  //инициализация счетчика битов
  PreVal = 1;               //перед стартовым битом была единица
  SysVar = 0xFF;            //неиспользуемый код системы
  ComVar = 0xFF;            //неиспользуемый код команды
  TCCR0 = (1<<CS00) | (1<<CS01); //прескалер CK/64 для таймера 0
  MCUCR = (1<<ISC01);       //INT0 по спаду
  GIFR = (1<<INTF0);        //очистка отложенных прерываний
  GICR |= (1<<INT0);        //разрешение INT0
}
//------------- Обработчик прерывания по сигналу фотоприемника: --------------
#pragma vector = INT0_vect
__interrupt void EdgeIR(void)
{
  Port_LED_1;
  GICR &= ~(1<<INT0);       //запрещение INT0
  TCNT0 = 256 - T_SAMPLE;   //интервал до первой выборки
  TIFR = (1<<TOV0);         //очистка отложенных прерываний
  TIMSK |= (1<<TOIE0);      //разрешение прерываний таймера 0
  SampCnt = SAMPLE_COUNT * 2; //общее количесто выборок
  SampVal = 0;              //очистка принятого значения
}
    
//------------------ Обработчик прерывания таймера 0: ------------------------
#pragma vector = TIMER0_OVF_vect
__interrupt void TimerIR(void)
{
  if(SampCnt)                       //проверка таймаута
  {
    if(Pin_RC5) SampVal++;          //если на входе единица, инкремент суммы,
      else SampVal--;               //иначе декремент суммы
      
    if(--SampCnt)                   //декремент количества выборок
    {
      if(SampCnt != SAMPLE_COUNT)
      {
        TCNT0 = 256 - T_SAMPLE;     //продолжаем опрашивать
        return;
      }
      else                          //первая половина интервала закончилась:
      {
        TCNT0 = 256 - T_SAMPLE * 2; //загрузка интервала между сериями выборок
        bool Val = (SampVal > 0);   //оценка бита
        if(Val != PreVal)           //проверка корректности кода Манчестер
        {
          RC5Code <<= 1;            //сдвиг принятого кода
          if(!Val) RC5Code |= 1;    //первая половина = 0, бит = 1
          SampVal = 0;              //очистка счетчика выборок
          return;
        }
      }
    }
    else                            //вторая половина интервала закончилась:
    {
      TCNT0 = 256 - T_SAMPLE * 2;   //загрузка интервала таймаута
      PreVal = (SampVal > 0);       //оценка второй половины бита
      if(PreVal)                    //обнаружена единица,
        MCUCR &= ~(1<<ISC00);       //INT0 по спаду,
          else MCUCR |= (1<<ISC00); //иначе INT0 по фронту
      GICR |= (1<<INT0);            //разрешение INT0
      if(--BitCounter)              //декремент счетчика битов
        return;                     //переход к приему следующего бита
      SysVar = (RC5Code >> 6) & 0x3F; //номер системы
      ComVar = RC5Code & 0x3F;      //код команды
      if(!(RC5Code & 0x1000))       //добавление бита F
        ComVar |= 0x40;
    }
  }
  BitCounter = RC5_LENGTH;          //загрузка счетчика битов
  PreVal = 1;                       //перед стартовым битом была единица
  TIMSK &= ~(1<<TOIE0);             //запрещение прерываний таймера 0
  MCUCR &= ~(1<<ISC00);             //INT0 по спаду
  GICR |= (1<<INT0);                //разрешение INT0
  Port_LED_0;
}
//------------------------- Чтение номера системы: ---------------------------
char RC5_GetSys(void)
{
  return(SysVar);
}
//-------------------------- Чтение кода команды: ----------------------------
char RC5_GetCom(void)
{
  return(ComVar);
}
//----------------------------------------------------------------------------