Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

RC5 problem z odczytem kodów

15 Mar 2010 22:30 1440 13
  • Poziom 11  
    Witam serdecznie

    Mam kłopot z odczytem kodu rc5, staram sie to zrozumiec i zrobic sam, ale nie wiem w czym tkwi problem. Mozecie mi pomóc? Bede bardzo wdzieczny, a kod podaje niżej ;)

    Code:

    if((PINC & 0x01) == 0x00)
    {

    for(i=0;i<14;i++)
    {
    if(bit_is_clear(PINC, PC0)) {n = 0;}
    if(bit_is_set(PINC, PC0))   {n = 1;}

    code[i] = n;

    _delay_us(1778);
    }

    }
     
  • Poziom 38  
    1 rzuca się w oczy 1778 to za duży argument dla tej funkcji. Sprawdź w delay.h maksymalna wartość argumentu tej funkcji
  • Poziom 11  
    rozłozyłem to na czesci i tak nic z tego na lcd wyswietla mi ciagle ten sam kod
  • Poziom 15  
    Zdefiniowałeś F_CPU ? Niezbędne do poprawnego działania funkcji delay.

    Moim zdaniem w złym miejscu umieściłeś również funkcję _delay_us.
    Powinno być:
    Code:
    if((PINC & 0x01) == 0x00)
    
    {
    _delay_us(1778);        // argument tej funkcji prawdopodobnie przekracza
                                   // max wartość zgodnie z tym co pisał kolega wyżej
                                   // więc sprawdź tą wartość i rozbij na mniejsze jeżeli
                                   // zajdzie taka potrzeba
    for(i=0;i<14;i++)
    {
    if(bit_is_clear(PINC, PC0)) {n = 0;}
    if(bit_is_set(PINC, PC0))   {n = 1;}

    code[i] = n;
    }

    }

    Zamieść jeszcze kod, który ciągle wyświetla Ci się na LCD gdyby moje sugestie nic nie zmieniły.
  • Poziom 11  
    Wiec tak testowałem twój sposób wyswietla mi same 0 gdy mam ustawiony taki kod:

    Code:
    if((PINC & 0x01) == 0x00)
    
    {
    for(i=0;i<28;i++)
    {
    if(bit_is_clear(PINC, PC0)) {n = 0;}
    if(bit_is_set(PINC, PC0))   {n = 1;}

    code[i] = n;

    _delay_us(400);
    _delay_us(500);
    _delay_us(500);
    _delay_us(378);
    }


    to wyswietla mi przy wyswietlaniu kolejno 28 bitow

    0000001110101101110011101111

    przewaznie taki kod czasem dla jakiegos przycisku zmienia sie trzecia i czwarta cyfra od konca. Nie ma tak zeby dla kazdego przycisku wyswietlalo konkretny kod. gdy odczekam jakies 15 sekund kod odbiera jakies lewe sygnaly i zamienia sie na 0000001010010100101101011011 badz bardzo podobny do tego zmieniajac jakis znak co nie zmienia faktu ze wszystko zle dekoduje. f_cpu ustawiłem na #define F_CPU 16000000 i gdy sprawdzałem diode z opoznieniem 3000ms srednio opoznia sie o jakies 3 sekundy sprawdzajac ze zegarkiem w reku.

    Jak widac opoznienie us tez rozłozyłem. Zazwyczaj wyswietlalem pierwsze 14 bitow ale postanowilem wyswietlic 28 chcac zobaczyc co sie dzieje dalej z kodem
  • Poziom 42  
    tadzik85 napisał:
    1 rzuca się w oczy 1778 to za duży argument dla tej funkcji. Sprawdź w delay.h maksymalna wartość argumentu tej funkcji


    Nie powielaj błędnych opinii, jakie krążą na elektrodzie często, iż rzekomo nie można stosować większych wartości. Bo można, wprawdzie wiąże się z tym zmniejszeniem precyzji takiego oczekiwania i to może być przyczyną problemów jeśli do dekodowania pordczerwieni używa się wprost takich poleceń zamiast prezyzyjnie odmierzać je za pomocą jakiegoś timera.

    Wystarczy zajrzeć w nagłówek funkcji _delay_us()

    Cytat:
    \ingroup util_delay

    Perform a delay of \c __us microseconds, using _delay_loop_1().

    The macro F_CPU is supposed to be defined to a
    constant defining the CPU clock frequency (in Hertz).

    The maximal possible delay is 768 us / F_CPU in MHz.

    If the user requests a delay greater than the maximal possible one,
    _delay_us() will automatically call _delay_ms() instead. The user
    will not be informed about this case.
    */


    podobnie jest z funkcją _delay_ms() gdzie też często słyszy się, że ktoś robi wielki błąd gdy podaje wartość opóźnienia większą niż 262.14 ms
  • Poziom 15  
    Badasz stan na pinie PC0 w momencie kiedy na PC0 pojawia się stan niski. W pierwszym kroku takie rozwiązanie zawsze da 0 jako wynik a kod RC5 rozpoczyna się sekwencją startu składającą się z dwóch 1 więc Twoje rozwiązanie jest niepoprawne już na starcie. Stąd moja propozycja wstawienia najpierw opóźnienia. Nie rozumiem dlaczego otrzymujesz same 0 przy moim sposobie odczytywania. Podciągnąłeś PC0 do 1 ? Zamieść więcej kodu bo może problem tkwi gdzie indziej.

    Spróbuj też minimalnie zwiększyć i zmniejszyć opóźnienie powiedzmy o 10us i sprawdź jak to się przełoży na otrzymane wyniki.

    Sam zrobiłem obsługę kodu RC5 na przerwaniach więc w ostateczności mogę podesłać Ci mój kod.

    Jeszcze pytanie na marginesie, jaką masz pewność, że pilot nadaje w standardzie RC5 ?
  • Poziom 11  
    Pewnosc ze nadaje RC5 mam 80% ale przeciez proboje takze 6 innych pilotow ktore mam w domu od tv np i na pewno ktorys musi nadawac rc5.

    O co chodziło ci z tym podciagnieciem PC0 do 1? jesli chodzi o rezystor podciagajacy to oczywiscie ze jest orginalnie zamontowany w module ktory zakupiłem.

    Próbowałem kilkakrotnie kombinowac ze zmiana opoznienia i nic, jak powinienem zmienic kod zeby wykonywalo mi sprawdzanie w momencie kiedy mam stan wysoki na porcie a nie niski jak ja to robie?

    Jesli moglbys podeslac swoj kod bylbym wdzieczny podejrze jak to u ciebie dziala, jak uda mi sie zrobic na opoznienieach pomysle zaczac uczyc sie timer'ow, ponizej podaje caly kod jaki mam do swojego programu:

    Code:
    #define F_CPU 16000000
    

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


    #define DDR_DB4  DDRD
    #define PORT_DB4 PORTD
    #define DB4      PD4

    #define DDR_DB5  DDRD
    #define PORT_DB5 PORTD
    #define DB5      PD5

    #define DDR_DB6  DDRD
    #define PORT_DB6 PORTD
    #define DB6      PD6

    #define DDR_DB7  DDRD
    #define PORT_DB7 PORTD
    #define DB7      PD7


    #define DDR_RS   DDRD
    #define PORT_RS  PORTD
    #define RS       PD2

    #define DDR_E    DDRD
    #define PORT_E   PORTD
    #define E        PD3

    #define SET_DB4 PORT_DB4 |= _BV(DB4)
    #define CLR_DB4 PORT_DB4 &= ~_BV(DB4)

    #define SET_DB5 PORT_DB5 |= _BV(DB5)
    #define CLR_DB5 PORT_DB5 &= ~_BV(DB5)

    #define SET_DB6 PORT_DB6 |= _BV(DB6)
    #define CLR_DB6 PORT_DB6 &= ~_BV(DB6)

    #define SET_DB7 PORT_DB7 |= _BV(DB7)
    #define CLR_DB7 PORT_DB7 &= ~_BV(DB7)

    #define SET_E PORT_E |= _BV(E)
    #define CLR_E PORT_E &= ~_BV(E)

    #define SET_RS PORT_RS |= _BV(RS)
    #define CLR_RS PORT_RS &= ~_BV(RS)


    void out_nibble(char x)
    {
    if(x & _BV(0)) SET_DB4; else  CLR_DB4;
    if(x & _BV(1)) SET_DB5; else  CLR_DB5;
    if(x & _BV(2)) SET_DB6; else  CLR_DB6;
    if(x & _BV(3)) SET_DB7; else  CLR_DB7;
    }


    void write_to_lcd(char x)
    {
    SET_E;
    out_nibble(x >> 4);
    CLR_E;
    SET_E;
    out_nibble(x);
    CLR_E;
    _delay_ms(5);
    }


    void write_command(char x)
    {
    CLR_RS;
    write_to_lcd(x);
    }


    void write_char(char x)
    {
    SET_RS;
    write_to_lcd(x);
    }


    void write_text(char * s)
    {
    while(*s)
    {
    write_char(*s);
    s++;
    }
    }


    void lcd_init(void)
    {
    DDR_DB4 |= _BV(DB4);
    DDR_DB5 |= _BV(DB5);
    DDR_DB6 |= _BV(DB6);
    DDR_DB7 |= _BV(DB7);
    DDR_E |= _BV(E);
    DDR_RS |= _BV(RS);

    _delay_ms(15);
    CLR_E; // E = 0
    CLR_RS; // RS = 0
    char i;
    for(i = 0; i < 3; i++)
    {
    SET_E; // E = 1
    out_nibble(0x03);
    CLR_E; // E = 0
    _delay_ms(5);
    }
    SET_E; // E = 1
    out_nibble(0x02);
    CLR_E; // E = 0
    _delay_ms(1);
    write_command(0x28);
    write_command(0x08);
    write_command(0x01);
    write_command(0x06);
    write_command(0x0C);
    }

    void LCDxy(char x,char y)
    {
    unsigned char com=0x80;
    com|=(x|(y<<6));
    write_command(com);
    }





    int main(void)
    {
    DDRC = 0x00;

    int code[28], n, i;


    while(1)
    {
    if((PINC & 0x01) == 0x00)
    {
    for(i=0;i<28;i++)
    {
    if(bit_is_clear(PINC, PC0)) {n = 0;}
    if(bit_is_set(PINC, PC0))   {n = 1;}

    code[i] = n;

    _delay_us(400);
    _delay_us(500);
    _delay_us(500);
    _delay_us(378);
    }


    lcd_init();

    if(code[0] == 1)  {LCDxy(0,0);  write_text("1");} else {LCDxy(0,0);  write_text("0");}
    _delay_us(1000);
    if(code[1] == 1)  {LCDxy(1,0);  write_text("1");} else {LCDxy(1,0);  write_text("0");}
    _delay_us(1000);
    if(code[2] == 1)  {LCDxy(2,0);  write_text("1");} else {LCDxy(2,0);  write_text("0");}
    _delay_us(1000);
    if(code[3] == 1)  {LCDxy(3,0);  write_text("1");} else {LCDxy(3,0);  write_text("0");}
    _delay_us(1000);
    if(code[4] == 1)  {LCDxy(4,0);  write_text("1");} else {LCDxy(4,0);  write_text("0");}
    _delay_us(1000);
    if(code[5] == 1)  {LCDxy(5,0);  write_text("1");} else {LCDxy(5,0);  write_text("0");}
    _delay_us(1000);
    if(code[6] == 1)  {LCDxy(6,0);  write_text("1");} else {LCDxy(6,0);  write_text("0");}
    _delay_us(1000);
    if(code[7] == 1)  {LCDxy(7,0);  write_text("1");} else {LCDxy(7,0);  write_text("0");}
    _delay_us(1000);
    if(code[8] == 1)  {LCDxy(8,0);  write_text("1");} else {LCDxy(8,0);  write_text("0");}
    _delay_us(1000);
    if(code[9] == 1)  {LCDxy(9,0);  write_text("1");} else {LCDxy(9,0);  write_text("0");}
    _delay_us(1000);
    if(code[10] == 1) {LCDxy(10,0); write_text("1");} else {LCDxy(10,0); write_text("0");}
    _delay_us(1000);
    if(code[11] == 1) {LCDxy(11,0); write_text("1");} else {LCDxy(11,0); write_text("0");}
    _delay_us(1000);
    if(code[12] == 1) {LCDxy(12,0); write_text("1");} else {LCDxy(12,0); write_text("0");}
    _delay_us(1000);
    if(code[13] == 1) {LCDxy(13,0); write_text("1");} else {LCDxy(13,0); write_text("0");}
    _delay_us(1000);
    if(code[14] == 1) {LCDxy(0,1);  write_text("1");} else {LCDxy(0,1);  write_text("0");}
    _delay_us(1000);
    if(code[15] == 1) {LCDxy(1,1);  write_text("1");} else {LCDxy(1,1);  write_text("0");}
    _delay_us(1000);
    if(code[16] == 1) {LCDxy(2,1);  write_text("1");} else {LCDxy(2,1);  write_text("0");}
    _delay_us(1000);
    if(code[17] == 1) {LCDxy(3,1);  write_text("1");} else {LCDxy(3,1);  write_text("0");}
    _delay_us(1000);
    if(code[18] == 1) {LCDxy(4,1);  write_text("1");} else {LCDxy(4,1);  write_text("0");}
    _delay_us(1000);
    if(code[19] == 1) {LCDxy(5,1);  write_text("1");} else {LCDxy(5,1);  write_text("0");}
    _delay_us(1000);
    if(code[20] == 1) {LCDxy(6,1);  write_text("1");} else {LCDxy(6,1);  write_text("0");}
    _delay_us(1000);
    if(code[21] == 1) {LCDxy(7,1);  write_text("1");} else {LCDxy(7,1);  write_text("0");}
    _delay_us(1000);
    if(code[22] == 1) {LCDxy(8,1);  write_text("1");} else {LCDxy(8,1);  write_text("0");}
    _delay_us(1000);
    if(code[23] == 1) {LCDxy(9,1);  write_text("1");} else {LCDxy(9,1);  write_text("0");}
    _delay_us(1000);
    if(code[24] == 1) {LCDxy(10,1); write_text("1");} else {LCDxy(10,1); write_text("0");}
    _delay_us(1000);
    if(code[25] == 1) {LCDxy(11,1); write_text("1");} else {LCDxy(11,1); write_text("0");}
    _delay_us(1000);
    if(code[26] == 1) {LCDxy(12,1); write_text("1");} else {LCDxy(12,1); write_text("0");}
    _delay_us(1000);
    if(code[27] == 1) {LCDxy(13,1); write_text("1");} else {LCDxy(13,1); write_text("0");}
    _delay_us(1000);
    }
    }

    }





    jestem poczatkujacy takze wybaczcie mi za błedy jakie pewnie sa w skrypcie, ale jak to mowia praktyka czyni mistrza. A co do wyswietlania na lcd wiem ze moge zrobic petle ale nie chce mi sie do poki nie zrobie zeby mi poprawnie wyswietlalo.
  • Pomocny post
    Poziom 15  
    Na początek odpal mój kod. Będziesz miał pewność czy któryś z pilotów nadaje w standardzie RC5. Pozmieniaj w "LCD.h" piny, żeby wszystko zgadzało się z Twoim podłączeniem a sygnał z odbiornika podczerwieni podaj na PD2.
  • Poziom 11  
    wiesz lekko przerobiłem kod na swoj sposob bo nie mam jak podciagnac port RW lcd i nie moge nic wyswietlic korzystam tylko z RS wiec przerobiłem twoj kod na sygnał IR z portu C0 ale petla while nic nie wykonuje poza wczesniejszym wyswietleniem napisu Pilot ..., kod podaje nizej:

    Code:
    #define F_CPU 16000000
    

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


    #define DDR_DB4  DDRD
    #define PORT_DB4 PORTD
    #define DB4      PD4

    #define DDR_DB5  DDRD
    #define PORT_DB5 PORTD
    #define DB5      PD5

    #define DDR_DB6  DDRD
    #define PORT_DB6 PORTD
    #define DB6      PD6

    #define DDR_DB7  DDRD
    #define PORT_DB7 PORTD
    #define DB7      PD7


    #define DDR_RS   DDRD
    #define PORT_RS  PORTD
    #define RS       PD2

    #define DDR_E    DDRD
    #define PORT_E   PORTD
    #define E        PD3

    #define SET_DB4 PORT_DB4 |= _BV(DB4)
    #define CLR_DB4 PORT_DB4 &= ~_BV(DB4)

    #define SET_DB5 PORT_DB5 |= _BV(DB5)
    #define CLR_DB5 PORT_DB5 &= ~_BV(DB5)

    #define SET_DB6 PORT_DB6 |= _BV(DB6)
    #define CLR_DB6 PORT_DB6 &= ~_BV(DB6)

    #define SET_DB7 PORT_DB7 |= _BV(DB7)
    #define CLR_DB7 PORT_DB7 &= ~_BV(DB7)

    #define SET_E PORT_E |= _BV(E)
    #define CLR_E PORT_E &= ~_BV(E)

    #define SET_RS PORT_RS |= _BV(RS)
    #define CLR_RS PORT_RS &= ~_BV(RS)



    // funkcja wystawiająca na szynę danych połówkę bajtu
    // pod uwagę brana jest młodsza połówka parametru
    void out_nibble(char x)
    {
    if(x & _BV(0)) SET_DB4; else  CLR_DB4;
    if(x & _BV(1)) SET_DB5; else  CLR_DB5;
    if(x & _BV(2)) SET_DB6; else  CLR_DB6;
    if(x & _BV(3)) SET_DB7; else  CLR_DB7;
    }

    // funkcja zapisująca do LCD bajt danych
    void write_to_lcd(char x)
    {
    SET_E;
    out_nibble(x >> 4); // wystawienie na szynę danych starszej połówki bajtu
    CLR_E; // opadające zbocze na E powoduje zapis do wyświetlacza
    SET_E;
    out_nibble(x); // wystawienie na szynę danych młodszej połówki bajtu
    CLR_E; // opadające zbocze na E powoduje zapis do wyświetlacza
    _delay_ms(5); // opóźnienie ok 10 ms
    }

    // funkcja zapisująca do LCD rozkaz
    void write_command(char x)
    {
    CLR_RS; // niski stan na RS -> zapis instrukcji
    write_to_lcd(x); // zapis do LCD
    }

    // funkcja zapisujaca do LCD znak
    void write_char(char x)
    {
    SET_RS; // wysoki stan na RS -> zapis danej
    write_to_lcd(x); // zapis do LCD
    }

    // funkcja zapisu tekstu do wyświetlacza LCD
    void write_text(char * s)
    {
    while(*s) // do napotkania 0
    {
    write_char(*s); // zapisz znak wskazywany przez s na LCD
    s++; // zwiększ s (przygotuj nastepny znak)
    }
    }

    // funkcja inicjująca LCD
    void lcd_init(void)
    {
    // ustawienie wszystkich linii sterujących LCD jako wyjścia
    DDR_DB4 |= _BV(DB4);
    DDR_DB5 |= _BV(DB5);
    DDR_DB6 |= _BV(DB6);
    DDR_DB7 |= _BV(DB7);
    DDR_E |= _BV(E);
    DDR_RS |= _BV(RS);
    //
    _delay_ms(15); // czekaj 15ms na ustabilizowanie się napięcia zasilającego
    CLR_E; // E = 0
    CLR_RS; // RS = 0
    char i; // zmianna licznikowa
    for(i = 0; i < 3; i++) // trzykrotne powtórzenie bloku instrukcji
    {
    SET_E; // E = 1
    out_nibble(0x03);
    CLR_E; // E = 0
    _delay_ms(5); // czekaj 5ms
    }
    SET_E; // E = 1
    out_nibble(0x02);
    CLR_E; // E = 0
    _delay_ms(1); // czekaj 1ms
    write_command(0x28); // interfejs 4-bity, 2-linie, znak 5x7
    write_command(0x08); // wyłącz LCD, kursor i miganie
    write_command(0x01); // czyść LCD
    write_command(0x06); // bez przesuwania w prawo
    write_command(0x0C); // włącz LCD, bez kursora i mrugania
    }

    void LCDxy(char x,char y)
    {
    unsigned char com=0x80;
    com|=(x|(y<<6));
    write_command(com);
    }






    unsigned char dane_bit = 0;
    unsigned int dane_pilota = 0;
    unsigned char po_zboczu = 0;
    unsigned char aktualnie = 1;


    void odmierz_czas(unsigned int czas)
    {
       cli();
       OCR1A = czas;
       TCNT1 = 0;
       TIFR |= _BV(OCF1A);               // wyzerowanie flagi przerwania
       TIMSK |= _BV(OCIE1A);            // odblokowanie przerwania porównania licznika1 z rejestrem A
       sei();
    }

    void IR_init()
    {
       GICR  |= _BV(INT0);              // zezwolenie na przerwanie INT0
       MCUCR |= _BV(ISC01);
       MCUCR &= ~_BV(ISC00);
       DDRC &= ~_BV(0);
       PORTC |= _BV(0);

    }

    SIGNAL(SIG_INTERRUPT0)
    {
       unsigned int k_TCNT1 = TCNT1;
       dane_bit++;
       if(dane_bit == 1 && aktualnie == 1)
          dane_pilota |= _BV(14-dane_bit);
       else if(dane_bit != 1)
       {
          if(aktualnie == 1 && k_TCNT1 < 500)
             dane_pilota |= _BV(14-dane_bit);
          else if(aktualnie == 0 && k_TCNT1 > 600)
             dane_pilota |= _BV(14-dane_bit);
          if(k_TCNT1 > 850)
          {
             dane_pilota |= _BV(13-dane_bit);
             dane_bit++;
          }
          else if(k_TCNT1 > 600)
          {
             if(aktualnie == 0)
                aktualnie = 1;
             else
             {
                aktualnie = 0;
                dane_bit++;
             }
          }
       }
       odmierz_czas(1000);
    }

    ISR(TIMER1_COMPA_vect)
    {
       TIMSK &= ~_BV(OCIE1A);
       if(dane_bit > 12 && dane_bit < 15)
       {
       lcd_init();
       LCDxy(0,0);
        write_text("Adres  : ");

          char c[4];
          utoa(((dane_pilota & 0x07C0) >> 6), c, 10);
          write_text(c);

       LCDxy(0,1);
        write_text("Rozkaz : ");

          utoa((dane_pilota & 0x003F), c, 10);
          write_text(c);
       }
       dane_bit = 0;
       dane_pilota = 0;
       aktualnie = 1;
    }








    int main(void)
    {
    TCCR1B |= (_BV(WGM12) | _BV(CS11) | _BV(CS10));// ustawienie preskalera clk/1024 i pracę licznika1 w trybie CTC
    IR_init();
    sei();
    lcd_init();
    LCDxy(0,0);                        // włączenie przerwań na INT
    write_text("Pilot ...");

    while(1)
    {
    ISR();
    }
    }



  • Poziom 15  
    SIGNAL(SIG_INTERRUPT0) jest przerwaniem generowanym przez zbocze opadające pojawiające się na pinie PD2. Jeżeli to ma działać to sygnał z odbiornika nie może być podłączony na pin PC0. Podłącz sygnał do pinu PD2 i cofnij wprowadzone zmiany. Skoro wyświetlacz Ci działa to część dotyczącą wyświetlacza możesz oczywiście zostawić zrobioną po swojemu.
  • Poziom 11  
    Mam teraz dokładnie taki kod wyswietla tylko na wyswietlaczu napis pilot i nic wiecej nie reaguje na przyciski zadnego pilota.. co mam tu zle w porownaniu do twojego kodu i co powinienem poprawic?

    Code:
    #define F_CPU 16000000
    

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


    #define DDR_DB4  DDRB
    #define PORT_DB4 PORTB
    #define DB4      PB4

    #define DDR_DB5  DDRB
    #define PORT_DB5 PORTB
    #define DB5      PB5

    #define DDR_DB6  DDRB
    #define PORT_DB6 PORTB
    #define DB6      PB6

    #define DDR_DB7  DDRB
    #define PORT_DB7 PORTB
    #define DB7      PB7


    #define DDR_RS   DDRB
    #define PORT_RS  PORTB
    #define RS       PB2

    #define DDR_E    DDRB
    #define PORT_E   PORTB
    #define E        PB3

    #define SET_DB4 PORT_DB4 |= _BV(DB4)
    #define CLR_DB4 PORT_DB4 &= ~_BV(DB4)

    #define SET_DB5 PORT_DB5 |= _BV(DB5)
    #define CLR_DB5 PORT_DB5 &= ~_BV(DB5)

    #define SET_DB6 PORT_DB6 |= _BV(DB6)
    #define CLR_DB6 PORT_DB6 &= ~_BV(DB6)

    #define SET_DB7 PORT_DB7 |= _BV(DB7)
    #define CLR_DB7 PORT_DB7 &= ~_BV(DB7)

    #define SET_E PORT_E |= _BV(E)
    #define CLR_E PORT_E &= ~_BV(E)

    #define SET_RS PORT_RS |= _BV(RS)
    #define CLR_RS PORT_RS &= ~_BV(RS)



    // funkcja wystawiająca na szynę danych połówkę bajtu
    // pod uwagę brana jest młodsza połówka parametru
    void out_nibble(char x)
    {
    if(x & _BV(0)) SET_DB4; else  CLR_DB4;
    if(x & _BV(1)) SET_DB5; else  CLR_DB5;
    if(x & _BV(2)) SET_DB6; else  CLR_DB6;
    if(x & _BV(3)) SET_DB7; else  CLR_DB7;
    }

    // funkcja zapisująca do LCD bajt danych
    void write_to_lcd(char x)
    {
    SET_E;
    out_nibble(x >> 4); // wystawienie na szynę danych starszej połówki bajtu
    CLR_E; // opadające zbocze na E powoduje zapis do wyświetlacza
    SET_E;
    out_nibble(x); // wystawienie na szynę danych młodszej połówki bajtu
    CLR_E; // opadające zbocze na E powoduje zapis do wyświetlacza
    _delay_ms(5); // opóźnienie ok 10 ms
    }

    // funkcja zapisująca do LCD rozkaz
    void write_command(char x)
    {
    CLR_RS; // niski stan na RS -> zapis instrukcji
    write_to_lcd(x); // zapis do LCD
    }

    // funkcja zapisujaca do LCD znak
    void write_char(char x)
    {
    SET_RS; // wysoki stan na RS -> zapis danej
    write_to_lcd(x); // zapis do LCD
    }

    // funkcja zapisu tekstu do wyświetlacza LCD
    void write_text(char * s)
    {
    while(*s) // do napotkania 0
    {
    write_char(*s); // zapisz znak wskazywany przez s na LCD
    s++; // zwiększ s (przygotuj nastepny znak)
    }
    }

    // funkcja inicjująca LCD
    void lcd_init(void)
    {
    // ustawienie wszystkich linii sterujących LCD jako wyjścia
    DDR_DB4 |= _BV(DB4);
    DDR_DB5 |= _BV(DB5);
    DDR_DB6 |= _BV(DB6);
    DDR_DB7 |= _BV(DB7);
    DDR_E |= _BV(E);
    DDR_RS |= _BV(RS);
    //
    _delay_ms(15); // czekaj 15ms na ustabilizowanie się napięcia zasilającego
    CLR_E; // E = 0
    CLR_RS; // RS = 0
    char i; // zmianna licznikowa
    for(i = 0; i < 3; i++) // trzykrotne powtórzenie bloku instrukcji
    {
    SET_E; // E = 1
    out_nibble(0x03);
    CLR_E; // E = 0
    _delay_ms(5); // czekaj 5ms
    }
    SET_E; // E = 1
    out_nibble(0x02);
    CLR_E; // E = 0
    _delay_ms(1); // czekaj 1ms
    write_command(0x28); // interfejs 4-bity, 2-linie, znak 5x7
    write_command(0x08); // wyłącz LCD, kursor i miganie
    write_command(0x01); // czyść LCD
    write_command(0x06); // bez przesuwania w prawo
    write_command(0x0C); // włącz LCD, bez kursora i mrugania
    }

    void LCDxy(char x,char y)
    {
    unsigned char com=0x80;
    com|=(x|(y<<6));
    write_command(com);
    }








    unsigned char dane_bit = 0;
    unsigned int dane_pilota = 0;
    unsigned char po_zboczu = 0;
    unsigned char aktualnie = 1;

    void odmierz_czas(unsigned int czas)
    {
       cli();
       OCR1A = czas;
       TCNT1 = 0;
       TIFR |= _BV(OCF1A);               // wyzerowanie flagi przerwania
       TIMSK |= _BV(OCIE1A);            // odblokowanie przerwania porównania licznika1 z rejestrem A
       sei();
    }

    void IR_init()
    {
       GICR  |= _BV(INT0);              // zezwolenie na przerwanie INT0
       MCUCR |= _BV(ISC01);
       MCUCR &= ~_BV(ISC00);
       DDRD &= ~_BV(2);
       PORTD |= _BV(2);

    }

    SIGNAL(SIG_INTERRUPT0)
    {
       unsigned int k_TCNT1 = TCNT1;
       dane_bit++;
       if(dane_bit == 1 && aktualnie == 1)
          dane_pilota |= _BV(14-dane_bit);
       else if(dane_bit != 1)
       {
          if(aktualnie == 1 && k_TCNT1 < 500)
             dane_pilota |= _BV(14-dane_bit);
          else if(aktualnie == 0 && k_TCNT1 > 600)
             dane_pilota |= _BV(14-dane_bit);
          if(k_TCNT1 > 850)
          {
             dane_pilota |= _BV(13-dane_bit);
             dane_bit++;
          }
          else if(k_TCNT1 > 600)
          {
             if(aktualnie == 0)
                aktualnie = 1;
             else
             {
                aktualnie = 0;
                dane_bit++;
             }
          }
       }
       odmierz_czas(1000);
    }

    ISR(TIMER1_COMPA_vect)
    {
       TIMSK &= ~_BV(OCIE1A);
       if(dane_bit > 12 && dane_bit < 15)
       {
    lcd_init();
    LCDxy(0,0);                        // włączenie przerwań na INT
    write_text("Adres  : ");
    char c[4];
    utoa(((dane_pilota & 0x07C0) >> 6), c, 10);
    write_text(c);
    LCDxy(0,0);                        // włączenie przerwań na INT
    write_text("Rozkaz  : ");
    utoa((dane_pilota & 0x003F), c, 10);
    write_text(c);
       }
       dane_bit = 0;
       dane_pilota = 0;
       aktualnie = 1;
    }




    int main(void)
    {
    TCCR1B |= (_BV(WGM12) | _BV(CS11) | _BV(CS10));// ustawienie preskalera clk/1024 i pracę licznika1 w trybie CTC
    IR_init();
    sei ();                         // włączenie przerwań na INT

    lcd_init();
    LCDxy(0,0);                        // włączenie przerwań na INT
    write_text("Pilot ...");

    while(1)
    {
    }
    }



    Dodano po 2 [minuty]:

    kurcze na jeden z pilotow reaguje ale wyswietla rozkaz : 0 na kazdym przycisku

    Dodano po 3 [minuty]:

    ja pier*** ;( jest jeden pilot i dziala rc5 wyswietla prawidłowo.. miałem fajny malutki pilocik i lipa chciqalem go wykorzystac do zdalnego sterowania, a powiedzcie mi jak moge przerobic pilot na rc5 albo chociaz kod odbioru z tego pilota? ;/
  • Poziom 11  
    eh, czuje jakbym wrocil do punktu wyjsca...

    no nic to dzialamy ;)