Zodiac21

Ик декодер на Atmega8

7 сообщений в этой теме

Zodiac21    0

Всем доброго дня! Ребята, не подскажите как декодировать сигнал с ик пульта (работающего по протоколу Nec). Прерывание T1 срабатывает, внешнее прерывание INT0 тоже срабатывает все 33 значения записываются в массив ir_signal. А вот в функции ir_decode почему-то не выполняется условие оператора IF , а выполняется ELSE...?

#include <io.h>
#include <delay.h>
#include <alcd.h>
#include <stdio.h>

unsigned char signal_time;
static unsigned char ir_ok,ir_decode_ok;
unsigned char ir_code[4]; // Массив для хранения значений адресов и команд
unsigned char ir_signal[33]; // Массив для хранения значений интервалов


// Прерывание по совпадению T1(каждые 560мкс)
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
signal_time++; // Счетчик интервалов
}

// Внешнее прерывание по INT0
interrupt [EXT_INT0] void ExtInt0(void)
{

// Определяем начало приема посылки
if(signal_time > 9) // (4,5ms+562us)/560 = 9 
x = 0; // Выбираем первый интервал

ir_signal[x] = signal_time; // Записываем в буфер значения интервалов 
signal_time = 0; // Обнуляем счетчик интервалов
x++; // Следующий интервал 

if(x == 33) // Если все интервалы приняты
{
ir_ok = 1; // Устанавливаем флаг окончания приема сигнала
} 
}

// Функция декодирования сигнала
void ir_decode(void)
{
unsigned char j;
unsigned char i; 
unsigned char k = 0;
unsigned char signal_length,value = 0;

for(i = 0; i < 4; i++) // Обработка байтов адреса или команды
  {    
  for(j = 0; j < 8; j++) // Обработка 8-ми битов адреса или команды
    {
    k++;
    value = value >> 1; // Сдвигаем биты вправо
    signal_length = ir_signal[k]; // Выбираем следущее значение интервала
    if(signal_length > 4) // Если интервал больше (1,675ms+562us)/560 = 4
      value = value | 0x80; // Добавляем к старшему разряду единицу
    }
  ir_code[i] = value; // Запоминаем в буфере байт адреса или команды
  //value = 0; // Обнуляем значение адреса или команды    
  }
   
// Производим явное приведение типов и проверяем принятые байты
if(((unsigned char)ir_code[0] == (unsigned char)~ir_code[1]) && 
   ((unsigned char)ir_code[2] == (unsigned char)~ir_code[3]))
  {
  ir_decode_ok = 1; // Устанавливаем флаг окончания декодирования сигнала
  ir_ok = 0; // Сбрасываем флаг окончания приема сигнала
  }
else
  {
  ir_decode_ok = 0; // Сбрасываем флаг окончания декодирования сигнала
  ir_ok = 0; // Сбрасываем флаг окончания приема сигнала
  }
}


void main(void)
{

PORTD.2=1;
DDRD.2=0;


MCUCR |= (1 << ISC01); // Внешнее прерывание по заднему фронту
GICR |= (1 << INT0); // Разрешение внешнего прерывния по INT0
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x22;
OCR1AL=0xFF;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (1<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<TOIE0);

lcd_init(16); // Инициализация ЖК дисплея


lcd_gotoxy(0, 0);
lcd_puts("Test");
lcd_gotoxy(0, 1);
lcd_puts("Decoder 'NEC'");
delay_ms(500);


#asm ("sei") // Глобально разрешаем прерывания
while(1)
{   
      
  if(ir_ok) ir_decode(); // Если сигнал принят, декодируем его
    if(ir_decode_ok) // Если обработка сигнала завершена, выводим данные на дисплей
    {
          lcd_gotoxy(0,1);
      lcd_putchar(ir_code[0]/10+0x30);
      lcd_gotoxy(1,1);
      lcd_putchar(ir_code[0]%10+0x30);
      
            lcd_gotoxy(2,1);
      lcd_putchar(ir_code[1]/10+0x30);
      lcd_gotoxy(3,1);
      lcd_putchar(ir_code[1]%10+0x30);
      
            lcd_gotoxy(4,1);
      lcd_putchar(ir_code[2]/10+0x30);
      lcd_gotoxy(5,1);
      lcd_putchar(ir_code[2]%10+0x30);
      
            lcd_gotoxy(6,1);
      lcd_putchar(ir_code[3]/10+0x30);
      lcd_gotoxy(7,1);
      lcd_putchar(ir_code[3]%10+0x30);
      

     
      
      ir_decode_ok = 0; // Сбрасываем флаг окончания декодирования сигнала
	}
   }
 }

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
snn_krs    48

Объявите переменную unsigned char signal_time как volatile unsigned char signal_time

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Zodiac21    0

Изменил переменную, прошил мегу, всё равно ничего не отображает... 

А вообще, код правильный??? 

Кварц стоит на 16мгц. Предделитель 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
snn_krs    48
15 hours ago, Zodiac21 said:

всё равно ничего не отображает...

Закомментируйте условие и выводите постоянно принятые байты. По ним увидите, где ошибка: в приеме или в условии.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Zodiac21    0

Спасибо! Буду пробовать.

А таймер T1, я правильно настроил на прерывание 560мкс?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Zodiac21    0

Закомментировал условие ,появляються коды при нажатии на кнопки пульта, но какие-то не правильные...

IMG_20190122_105004.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
18 минут назад, Zodiac21 сказал:

но какие-то не правильные...

ну так это очевидно же)

В 19.01.2019 в 10:49, Zodiac21 сказал:

все 33 значения записываются в массив ir_signal.

В 19.01.2019 в 10:49, Zodiac21 сказал:

не выполняется условие оператора IF

Логично же, раз данные есть, а условие не выполняется, значит данные или условие не правильные :)

Я не знаю какой протокол у ИК пульта, ни когда не интересовался, но видимо вы условие написали значит знаете.

Посмотрите в дебаге значения в массиве ir_signal. Они похожи на реальные? Если нет, то нужно пересмотреть алгоритм приема.

А в атмеге8 нельзя настроить таймер на захват и подсчет интервалов? что бы не мудрить таймер + прерывание?

 

смотрю в даташите есть инфа что счетчик может работать в режиме захвата. Input Capture Pin (ICP1) PB0

Вместо PD2 подключите ногу PB0. Настройте таймер на захват. В прерывании TIM1_CAPT смотрите значение в ICR1 это будет сколько тиков сделал таймер. Дальше так же в массив распихиваете тайминги и потом переводите в основном цикле в 0 и 1.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас