Дешифратор ИК-пульта

Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Ответить
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

Приветствую!
нужно раскодировать данные передаваемые с ИК пульта от телека. Протоколы смотрел,но ничего подходящего не нашел. Решил сам их добыть написав свой протокол декодирования. Пощупав осциллографом получил что при нажатии любой кнопки пульт просаживает линию на 3 мс затем отпускает на 3 мс. после начинает просаживать перед каждым битом на время около 500 мкс затем,если 0 отпускает линию на 1,5 мс, если 1 линия в плюсе 2,5 мс и так 16 бит.+ в конце передачи я так понимаю бит завершения передачи линия в плюсе 4 мс. При нажатии любой кнопки первые 8 бит одинаковые, вторые 8 бит меняются. в моем протоколе включено считывание начала передачи и 16 бит данных. Стоп-бит я упускаю.
Решил все это считывать с помощью прерывании и таймера для отсчитывания времени удержания в плюсе.
Все прерывания срабатывают, но считывается всякий бред в основном 1. Грешил на время отсчитываемое таймером,но все варианты предделителя перепробовал, В OCR0 все возможные варианты вписал. Может алгоритм не верный, не могу понять... Спасибо за ранее!!!
Спойлер

Код: Выделить всё

#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define IR_sens    3
#define IR_DDR     DDRD
#define IR_PIN     PIND
#define IR_PORT    PORTD


uint16_t DATA=0;
uint16_t DATA_buf=0;
uint16_t i=0;

uint8_t START_flag=0;              // флаг о начале приема


void init_INT1(void)
{
	MCUCR|=(1<<ISC11)|(0<<ISC10); //генерация прерывания по падающему фронту
	GICR|=1<<INT1;                // включаем прерывание по INT1
}


void init_T0(void)
{
	TCCR0=(0<<WGM00)|(1<<WGM01)|(1<<CS02)|(0<<CS01)|(1<<CS00); // делитель 1024
}



ISR (TIMER0_COMP_vect)
{
	TIMSK&=~(1<<OCIE0);    // отключаем прерывание по таймеру
	if(i<16)
	{
		if((IR_PIN&(1<<IR_sens)))  
		DATA|=1<<i;
		else 
		DATA|=0<<i;
		i++;
	}
	
	if(i==16)
	{
		START_flag=0;
		DATA_buf=DATA;

		DATA=0;
		GICR&=~(1<<INT1);            //отключаем прерывание по INT1               
	    MCUCR=(1<<ISC11)|(0<<ISC10);// восстанавливаем прерывание INT1 по падающему фронту
		GICR|=(1<<INT1);             //включаем прерывание по INT1  
		i=0;

	}
};
	
	

ISR (INT1_vect)
{
	
	if(!START_flag)                       // если флаг старт не установлен проверяем на достоверность начала приема
	{
		_delay_us(800);                  // 
		if((IR_PIN&(1<<IR_sens))==0)     // проверяем достоверность  начала приема
		START_flag=1;                    // если достоверно устанавливаем флаг стат
		                                
	}
	else                                // если флаг установлен 
	{
		if((MCUCR&(0x03<<2))==0xC)     //  проверяем по какому фронту прерывание iNT1,
		{
	                                          // если прерывание было установлено по восходящему фрнту начинаем отсчитывать время для считывания бита
		  TIMSK|=1<<OCIE0;            // включение прерывание таймера
		  TCNT0=0x00;                  
		}
		else    
		{
		GICR&=~(1<<INT1);                      //отключаем прерывание по INT1               
		MCUCR|=(1<<ISC11)|(1<<ISC10); // устанавливаем прерывание по восходящему
		GICR|=(1<<INT1);                         //включаем прерывание по INT1
		}           
	}
	//GIFR|=1<<INTF1;
};

int main(void)
{
   
   IR_DDR&=~(1<<IR_sens); // ножку подключенную к датчику настравиваем на вход. данные только входные
   IR_PORT&=~(1<<IR_sens);   // ножку подтягиваем.
     
  init_T0();
  init_INT1();

    OCR0=15;
    sei();
    while (1) 
    {   
		
    }
}
Вложения
2018-03-18_21-58-41.png
(28.84 КБ) 311 скачиваний
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Вот здесь полностью универсальный алгоритм приема ИК-кодов, проверенный неоднократно и подходящий для 99% всех типов пультов. Для RC5 есть вариант и проще...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

[uquote="ARV",url="/forum/viewtopic.php?p=3334204#p3334204"]Для RC5[/uquote]
моя диаграмма разве схожа с этим протоколом?
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

ROMan2947 писал(а):моя диаграмма разве схожа с этим протоколом?
вы читать умеете?
ARV писал(а):Вот здесь полностью универсальный алгоритм приема ИК-кодов, проверенный неоднократно и подходящий для 99% всех типов пультов.
я вашу диаграмму и смотреть не стал -уверен, что в упомянутые 99% попадет :)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

ок :write:

Добавлено after 7 hours 23 minutes 52 seconds:
На прерываниях и таймере расшифровать данные пока не получается, но на задержках вроде как реализовал.Задолбался правда подгонять тайм-слоты.Понимаю на задержках все уныло,но видя как с пульта управляешь моторчиком это вдохновляет.Хоть пока без реверса))буду разбираться с прерываниями)
Спойлер

Код: Выделить всё



#include <avr/io.h>
#include <util/delay.h>

#define IR_sens    3
#define IR_DDR     DDRD
#define IR_PIN     PIND
#define IR_PORT    PORTD

#define OC1A 5
#define step 50

uint16_t DATA=0;
uint16_t i=0;

void TIMER_instal(void)
{
	DDRD|=(1<<OC1A);
	TCCR1A=(1<<COM1A1)|(0<<COM1A0)|(0<<COM1B1)|(0<<COM1B0)|(0<<FOC1A)|(0<<FOC1B)|(1<<WGM11)|(1<<WGM10);
	TCCR1B=(0<<ICNC1)|(0<<ICES1)|(0<<WGM13)|(1<<WGM12)|(1<<CS12)|(0<<CS11)|(1<<CS10);
}

void read_TIMER(uint8_t data)
{
	switch(data)
	{
		case 0xC8:
		
		if(TCCR1A&(1<<COM1A1))
	{
		if((OCR1A+step)<=0x3FF) OCR1A+=step;else  OCR1A=0x3ff; // увеличиваем обороты
	}
	    break;

		case 0x48: 
		
		if(TCCR1A&(1<<COM1A1))
		{
		if(((OCR1A-step)>0x00)&((OCR1A-step)<0x3FF))   OCR1A-=step;  else OCR1A=0; // убавляем обороты
		}  
		break;
		
		case 0xF4: TCCR1A|=(1<<COM1A1); break; // старт
 		case 0xA8: TCCR1A&=~(1<<COM1A1);break; // стоп
	}
}

uint8_t IR_kod(void)
{
	DATA=0;
	if(!(IR_PIN&(1<<IR_sens)))
	{
		_delay_us(1100);
		if(!(IR_PIN&(1<<IR_sens)))
		{    
			_delay_ms(7);
			
			if(IR_PIN&(1<<IR_sens))
			{
				DATA|=(unsigned int)1<<i;
				_delay_ms(1);
			}
			else
			{
				DATA|=(unsigned int)0<<i;
			}
			
			while(i<=15)
			{
				i++;
				_delay_ms(2);
				if(IR_PIN&(1<<IR_sens))
				{
					DATA|=1<<i;
					_delay_us(1050);
				}
				else
				{
					DATA|=0<<i;
				}
				
			}
			i=0;
		}
		
	}
	DATA=DATA>>8;
	read_TIMER(DATA);
}

int main(void)
{
	IR_DDR&=~(1<<IR_sens); // ножку подключеную к датчику настравиваем на вход. данные только входные
	IR_PORT|=(1<<IR_sens);   // ножку подтягиваем.
	TIMER_instal();
	while (1)
	{
		IR_kod();
	}
}
Реклама
Ответить

Вернуться в «Периферия»