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

Wpisywanie wartości do tablicy, ATmega16 - jak wykonać?

Drako1988 29 Sty 2010 13:00 1084 2
  • #1 29 Sty 2010 13:00
    Drako1988
    Poziom 20  

    Witam serdecznie. Z racji chwili wolnego czasu piszę sobie kod do odbiornika IR na ATmega16. Korzystam ze scalonego odbiornika TSOP1736. O tym jak wygląda kodowanie sygnału w przypadku pilota do telewizora firmy Philips dowiedziałem się ze strony http://www.sbprojects.com/knowledge/ir/rc5.htm. Po odkodowaniu sygnału wszystko jest ok, ale tutaj pojawił się problem. Otóż w przerwaniu Timera 1 program nie chce wpisywać wartości do tablicy(przynajmniej po wielu próbach doszedłem do takiego wniosku). Poniżej przedstawiam kod:

    Code:

    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>
    #include <stdint.h>
    #include <stdlib.h>

    #ifndef F_CPU
    #define F_CPU 16000000ul
    #endif

    #include "lcd.h"

    #define IR_PORT PORTD
    #define IR_PIN PIND

    #define IR 3

    //#define MY_OCR(time, prescaler)   ( (time * F_CPU)/(2*prescaler) - 1 )

    #define SBI(addr, bit)   (addr |= (1<<bit))
    #define CBI(addr, bit)   (addr &= ~(1<<bit))
    #define TBI(addr, bit)   (addr ^= (1<<bit))

    #define D_ON   (SBI(PORTD, PD0))
    #define D_OFF   (CBI(PORTD, PD0))
    #define D_TOG   (TBI(PORTD, PD0))

    #define INT1_FALLING (CBI(MCUCR, ISC10)); (SBI(MCUCR, ISC11)); (SBI(GICR, INT1))
    #define INT1_RISING    (SBI(MCUCR, ISC10)); (SBI(MCUCR, ISC11)); (SBI(GICR, INT1))
    #define INT1_OFF    (CBI(GICR, INT1))

    #define START_CLOCK      SBI(TCCR1B, WGM12); SBI(TCCR1B, CS10); SBI(TIMSK, OCIE1A)
    #define STOP_CLOCK      CBI(TCCR1B, CS10);

    volatile int kod[26];
    volatile int licznik = 0;
    volatile int DlugoscKodu = 0;

    ISR(TIMER1_COMPA_vect)
    {
       if(bit_is_set(IR_PIN, IR))
       {
          kod[licznik++] = 0;
       }
       else if(bit_is_clear(IR_PIN, IR))
       {
          kod[licznik++] = 1;
       }
       if(licznik >= 26)
       {
          STOP_CLOCK;
          _delay_ms(100);
          INT1_FALLING;
       }
    }





    ISR(INT1_vect)   //wywołane po wykryciu pierwszego znaku wysłanego z pilota
    {
       licznik = 0;
       INT1_OFF;
       _delay_us(450);   //czekaj aby próbkować sygnały w połowie ich czasu trwania
       START_CLOCK;
    }

    int main(void)
    {
       uint8_t kod[13];
       char buf[10];

       DDRD = 0b11110011;
       PORTD = 0b00001100;
       OCR1A = 14396;   //na czas 450 us

       lcd_init(LCD_DISP_ON);
       INT1_FALLING;

       sei();
       
       while(1)
       {
          if(licznik >= 26)
          {
             for(int i = 0; i < 26; i++)
             {   
                if(kod[i] == 0)
                   lcd_putc('0');
                else if(kod[i] == 1)
                   lcd_putc('1');
                else
                {
                   itoa(kod[i], buf, 10);
                   lcd_puts(buf);
                }
             }
             _delay_ms(1000);
          }
       }

       return 0;
    }


    Jeśli natomiast przerwanie będzie wyglądać tak:

    Code:

    ISR(TIMER1_COMPA_vect)
    {
       if(bit_is_set(IR_PIN, IR))
       {
          lcd_putc('0');
       }
       else if(bit_is_clear(IR_PIN, IR))
       {
          lcd_putc('1');
       }
       if(licznik == 16)
          lcd_gotoxy(0,1);
       if(licznik >= 26)
       {
          STOP_CLOCK;
          _delay_ms(100);
          INT1_FALLING;
       }
    }


    To na wyświetlaczu ukazuje mi się pełny odkodowany sygnał (w postaci zero jedynkowej) Nie wiem w czym może być problem bo wydaje mi się że próbowałem już wszystkiego. Proszę o pomoc w tej sprawie. Dodam, że ATmega pracuje na kwarcu 16MHz a wersja avrStudio na jakiej pracuję to 4.16. Z góry serdecznie dziękuję za pomoc.

    0 2
  • #2 29 Sty 2010 13:06
    _Robak_
    Poziom 33  

    Masz dwa razy deklaracje tablicy kod[]. Z tego co pamiętam to zmienna lokalna przysłania globalną, więc w mainie i przerwaniu operujesz na dwóch róznych zmiennych.

    EDIT:
    Tak, dobrze pamiętam, lokalna zmienna przesłania globalną ;)

    0
  • #3 29 Sty 2010 14:16
    Drako1988
    Poziom 20  

    Dzięki Ci wielki, przesiadując tyle nad tym kodem pominąłem taki detal. Teraz już wszystko śmiga. I można pobawić się pilocikiem.

    Pozdrawiam.

    0