Momentami odnoszę wrażenie, że nie wiesz co piszesz. Do pomiaru długości nie potrzebujesz dodatkowego timera oprócz tego t0. Wystarczy, że będziesz sprawdzał co określony czas, jeśli na wejściu będzie ten sam stan co poprzednio, to będziesz zwiększał pomocniczą zmienną. Jeśli stan się zmieni, to dopiero zapiszesz wartość do np.tablicy, żeby później interpretować sygnał.
Chociaż dobrze kombinujesz, brakuje kilku negacji, nie wiem czy t2 rusza, nie chce mi się sprawdzać.
Dodano po 24 [minuty]:
Nie wnikając w ład, funkcjonalność, czytelność, to można to zrobić mniej więcej tak:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>
#define TIMER_WAIT() \
{ \
while(!( TIFR & _BV(TOV0) )) \
; \
TIFR = _BV(TOV0); \
}
#define IR_GET() (PIND & _BV(2))
// inicjalizacja portu szeregowego
void UART_Init()
{
UBRRH = 0;
UBRRL = 51;
UCSRA = 0;
UCSRC = _BV(URSEL)|_BV(UCSZ0)|_BV(UCSZ1);
UCSRB = _BV(RXEN)|_BV(TXEN)|_BV(RXCIE);
}
// wysyła znak podany jako parametr na port szeregowy
void UART_putchar(unsigned char c)
{
while ( !( UCSRA & _BV(UDRE)) )
;
UDR = c;
}
//wysyła string podany jako parametr na port szeregowy
void UART_putstring(const char *tekst)
{
while(*tekst)
UART_putchar(*tekst++);
}
const unsigned char hextab[16] = "0123456789ABCDEF";
/** Funkcja sprawdza jak długo trwa stan niski. */
unsigned char ir_getlo(unsigned char maxlen)
{
unsigned char len = 0;
while(1)
{
TIMER_WAIT();
// jeśli pojawił się stan wysoki - przerwij funkcję
if(IR_GET())
return len;
// aktualizacja licznika - jak długo trwa aktualny stan
len++;
// jeśli stan niski trwa zbyt długo - przerwij funkcję
if(len > maxlen)
return 0;
}
}
/** Funkcja sprawdza jak długo trwa stan wysoki */
unsigned char ir_gethi(unsigned char maxlen)
{
unsigned char len = 0;
while(1)
{
TIMER_WAIT();
if(!IR_GET())
return len;
len++;
if(len >= maxlen)
return 0;
}
}
int main(void)
{
UART_Init();
// PORTD=wejścia/pu
DDRD = 0x00;
PORTD = 0xFF;
// wszystkie przerwania od timerów wyłączone
TIMSK = 0;
// Załączenie timera 0, F_CPU/8, przepełnienie co 2048 cykli
TCCR0 = _BV(CS01);
while(1)
{
// oczekiwanie na pojawienie się stanu niskiego
while(IR_GET())
TIMER_WAIT();
// odebranie startu - jeśli błąd, to powrót do początku
if(ir_getlo(90) < 50)
continue;
// odebranie sync
if(ir_gethi(50) < 25)
continue;
// odbieranie poszczególnych bitów
// - zmienna, w której będzie cały odebrany kod
uint32_t code = 0;
unsigned char i;
for(i=0; i<32; i++)
{
// sync bitu
if(ir_getlo(6) < 2)
break;
// właściwy bit
unsigned char len = ir_gethi(20);
if(len < 2)
break;
// zrobienie miejsca na bit
code >>= 1;
// wstawienie bitu
if(len >= 7)
code |= (1UL << 31);
}
// jeśli pętla została przerwana w środku (któryś stan był zbyt długi lub zbyt krótki) - przerwij (wróć do początku pętli)
if(i < 32)
continue;
// sprawdzenie poprawności kodu - jeśli błąd, wróć do początku
if(((code >> 8) ^ ~code) & 0x00FF00FF)
continue;
// wyłuskanie właściwego kodu przycisku
uint16_t code_unp = (code & 0xFF) | ((code >> 8) & 0xFF00);
// wysłanie kodu przycisku
char odb[5];
odb[0] = hextab[(code_unp >> 12) & 0xF];
odb[1] = hextab[(code_unp >> 8) & 0xF];
odb[2] = hextab[(code_unp >> 4) & 0xF];
odb[3] = hextab[code_unp & 0xF];
odb[4] = 0;
UART_putstring(odb);
}
return 0;
}
Jednak sam kod ma wiele wad, jak np blokujące działanie. Można kod przepisać do działania na przerwaniach. Przeanalizuj może najpierw co ten kod robi, czy kompiluje się chociaż (pisany od ręki, może nie działać).