Witam,
Zrobiłem prosty układzik, przerobiłem prosty programik ze stronki http://www.microsyl.com/ ( i zakładka Mod Lamp ) do dekodowania sygnałów IR z pilota Sony, na swoje potrzeby. Sposób ten wykorzytuje wejście ICP procesora (u mnie Atmega8) oraz Timer1. Jak widać program przerobiłem dosyć mocno
i najważniejsze , że przepięknie działa. Jednak męczy mnie to, że nie mogę zrozumieć zasady działania jego jednego małego fragmentu - dotyczącego obliczania długości impulsu (zmienna PulseWidth)
dokładniej mówiąc tego fragmentu:
poniżej cały kodzik:
(częstotliwość taktowania procka tutaj to 8MHz, preskaler = 8 dzięki czemu jedno "tiknięcie" Timera1 = 1us. W związku z tym wartość w ICR1 to już dokładna równowartość długości sygnału w us)
(przy okazji może się komuś przyda bo naprawdę prosty jak drut i rewelacyjnie działa bo w tle pracy programu głównego
poniżej jak coś przypomnę jak wygląda przebieg Sony IR aby lepiej było to przeanalizować:
jak widać przerwanie jest wywoływane za każdym razem gdy następuje zbocze wzrastające sygnału. Na początku jest obliczana długość trwania każdego impulsu (zera bądź jedynki), impulsy jak widać składają się zawsze z 2 części. i tak
JEDYNKA to: 600us + 1200us co daje nam 1800us
ZERO to: 600us + 600us co daje nam 1200us
gdy impuls trwa dłużej to resetowane są wartości licznika odebranych bitów itp.
dla mnie główny problem jest taki:
ponieważ sposób obliczania dł.impulsu jest tak jak podałem wyżej to nie rozumiem jak to się zachowuje gdy np:
1. wystąpiło przerwanie
2. wartość ICR1 = 1200us
3. wartość LastCapture = 1800us
więc PulseWidth = 1200 - 1800 co nam da chyba
64936 więc poniższy warunek za każdym razem powinien być spełniony
i ciągle powinien następować reset - a tak się nie dzieje - więc zastanawiam się co naknociłem w moim powyższym wywodzie i jak to naprawdę działa:
tylko to nie daje mi spać bo cała reszta jest dla mnie jasna.
(z góry dziękuję za pomoc w rozwikładniu mojej zagadki)
Zrobiłem prosty układzik, przerobiłem prosty programik ze stronki http://www.microsyl.com/ ( i zakładka Mod Lamp ) do dekodowania sygnałów IR z pilota Sony, na swoje potrzeby. Sposób ten wykorzytuje wejście ICP procesora (u mnie Atmega8) oraz Timer1. Jak widać program przerobiłem dosyć mocno
dokładniej mówiąc tego fragmentu:
PulseWidth = ICR1 - LastCapture;
LastCapture = ICR1;poniżej cały kodzik:
(częstotliwość taktowania procka tutaj to 8MHz, preskaler = 8 dzięki czemu jedno "tiknięcie" Timera1 = 1us. W związku z tym wartość w ICR1 to już dokładna równowartość długości sygnału w us)
// ir_decode.c
#define IR_PORT B
#define IR_PIN 0
#define IR_IN (1<<IR_PIN)
volatile uint16_t LatchedIrData;
volatile uint8_t address;
volatile uint8_t command;
volatile uint8_t Ir_key_press_flag = 0;
void ir_init()
{
DDR(IR_PORT) RESET IR_IN; // pin jako wejście
PORT(IR_PORT) SET IR_IN; // podciągnięcie pinu do VCC
TCCR1B SET (1<<CS11); // Timer1 / 8
TCCR1B SET(1<<ICES1); // Zbocze narastające na ICP
TIMSK SET (1<<TICIE1); // Przerwanie od ICP
}
SIGNAL(SIG_INPUT_CAPTURE1)
{
static uint16_t LastCapture;
uint16_t PulseWidth;
static uint8_t IrPulseCount;
static uint16_t IrData;
PulseWidth = ICR1 - LastCapture;
LastCapture = ICR1;
if (PulseWidth > 1984)
{ // jeśli impuls dłuższy niż czas trwania JEDYNKI to reset wskaźników
IrPulseCount = 0;
IrData = 0;
}
else
{
IrData = IrData >> 1;
if (PulseWidth > 1388) IrData = IrData | 0x8000;
IrPulseCount++;
if (IrPulseCount == 12)
{
LatchedIrData = ((IrData >> 4) & 0b0000000001111111);
command = LatchedIrData;
LatchedIrData = (IrData >> 11);
address = LatchedIrData;
Ir_key_press_flag = 1;
}
}
}(przy okazji może się komuś przyda bo naprawdę prosty jak drut i rewelacyjnie działa bo w tle pracy programu głównego
poniżej jak coś przypomnę jak wygląda przebieg Sony IR aby lepiej było to przeanalizować:
jak widać przerwanie jest wywoływane za każdym razem gdy następuje zbocze wzrastające sygnału. Na początku jest obliczana długość trwania każdego impulsu (zera bądź jedynki), impulsy jak widać składają się zawsze z 2 części. i tak
JEDYNKA to: 600us + 1200us co daje nam 1800us
ZERO to: 600us + 600us co daje nam 1200us
gdy impuls trwa dłużej to resetowane są wartości licznika odebranych bitów itp.
dla mnie główny problem jest taki:
ponieważ sposób obliczania dł.impulsu jest tak jak podałem wyżej to nie rozumiem jak to się zachowuje gdy np:
1. wystąpiło przerwanie
2. wartość ICR1 = 1200us
3. wartość LastCapture = 1800us
więc PulseWidth = 1200 - 1800 co nam da chyba
if (PulseWidth > 1984)
{
IrPulseCount = 0;
IrData = 0;
}i ciągle powinien następować reset - a tak się nie dzieje - więc zastanawiam się co naknociłem w moim powyższym wywodzie i jak to naprawdę działa:
PulseWidth = ICR1 - LastCapture;
LastCapture = ICR1;tylko to nie daje mi spać bo cała reszta jest dla mnie jasna.
(z góry dziękuję za pomoc w rozwikładniu mojej zagadki)