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.

Jak przyśpieszyć (zmodyfikować) program w na ATMega32

01 Lut 2010 18:14 1793 6
  • Poziom 9  
    Witam...Dlaczego przerwania z Timera0 generowane nie sa zgodnie z dokumentacja? chciałbym zrealizować generator sterujący pinami portu PC0-7...w taki sposób aby wartości z tabeli --- unsigned char GenTab[12]; ---- były kolejno podawane na port PC z kazdym przerwaniem TIMERA0....
    wiec na poczatku w main() wykonuje ponizsze instrukcje :


    Code:
    DDRC = 0xFF;      // port C jako wyjscie 11111111
    
     CLI(); //disable all interrupts
     TIMSK = 0x01; //timer interrupt sources
     TCCR0 = 0x00; //stop
     OCR0  = 0xFF;
     TCNT0 = 0xFE;//set count
     TCCR0 = 0x01; //start timera bez prescalera clock zegara
     SEI(); //re-enable interrupts

    taki kod wywoluje przerwanie dla Timera0...a procedura obslugi jest taka:
    #pragma interrupt_handler timer1_ovf_isr:12
    void timer1_ovf_isr(void)
    {
    TCNT0 = 0xFE; //reload counter value
     Licznik++;
     if (Licznik>11) Licznik=0;
     PORTC = GenTab[Licznik];
     PORTD ^= BIT(0); // !! to tak dodatkowo by zmierzyc czestotliwosc na oscyloskopie
    }

    wiec dla kazdego przerwania dla portu C wpisywany jest kolejny bajt tabeli oraz bit0 portuD powinien generowac fale prostokatna polowe czestotliwosc zegara 16MHz?...
    ATMega32 jest taktowana kwarcem zewnętrznym 16MHz...i teraz moje pytanie:

    Dlaczego generowany sygnal mierzony oscyloskopem na bit(0) portuD ma czestotliwość 250kHz...skoro przerwanie powinno byc generowane przy TCNT0==0xFF
    ? przy obsludze kazdego przerwania ustawiam TCNT0 na 0xFE a OCR0 jest 0xFF..wiec po jednej imkrementacji licznika powinno byc generowane przerwanie?

    250KHz probek z tablicy o dlugosci 12 to jest jakies 21KHz.....!! jak to zwiekszyc??
    wystarczyloby aby przerwanie bylo wykonywane ok 500kHz dla zegara 16MHz...to by zostalo kilka cykli dla wyswietlacz i klawiatury...

    a potrzebuje zrobic 3 kanalowy , analogowy (dokladnosc 2bit - na drabince R) generator fali prostokatnej z modulowana szerokoscia impulsu. Zmiana czestotliwosci dla kazdego kanalu niezalezna...jak juz uda sie wykonac przerwanie 500 razy/s to chyba kolejne kanaly beda zrealizowane niezaleznie...
    generator raczej lepiej jak jest na przerwaniach gdyz obsuguje jeszcze w main wyswietlacz i klawiature.

    Nie wiem czy mam dobrze skonfigurowane rejestry timera0 bo wyswietlacz podlaczony do portu B gdzie jest pin OCR0 czasami wywala krzaki gdy zmienam warotsc TCNT0 chcac regulowac czestotliwosc...dziwne jest to, ze od TCNT0=255 do 216 klawiatura reaguje wolniej a wyswietlacz prawidlowo....jak zmieniam TCNT0 ponizej 216 to odczyt klawiatury w main() smiga max szybko a wyswietlacz sie wykrzacza....

    Prosze bardzo o pomoc bo juz kolejna analiza dokumentacji Atmegi32 nie przyniosla rezultatu.....jak powinienem ustawic rejesrtry i jak zmieniac TCNT0 aby przerwania byly wywolywane najszybciej...
  • Moderator Mikrokontrolery Projektowanie
    Po pierwsze na niektorych pinach PORTC masz JTAG, wylaczyles go?
    Po drugie - ATMega potrzebuje ok. 6 cykli zegara, zeby wejsc w przerwanie, a twoje instrukcje tez nie wykonuja sie w jednym takcie. Zobacz jaki kod dla przerwania generuje gcc, okaze sie, ze osiagniecie przebiegu rownego clk/2 w ten sposob jest niemozliwe.
  • Poziom 12  
    Polecam użyć trybu 2 (CTC) dla Timera0.
    Wtedy timer taktowany bez preskalera,
    Wartość 32(dec) do OCR0, (16000000/32 = 500000)
    Licznik liczy wtedy od 0 do 31 (32? - nie pamiętam, trzeba sprawdzić w datasheet)

    Nie pamiętam tylko czy wtedy idą przerwania od overflow-a czy od compare match-a.

    Tak czy inaczej powinny być wołane z f=500000kHz.
    W obsludze przerwania nie ruszasz zadnych rejestrow timera, tylko od razy wrzucasz dane na port.

    Czyli:

    Code:

    TCCR0=0x09;
    OCR0=0x20; (0x1F?)
    TIMSK=0x01; (0x02 - zależnie czy od TOIE0 czy OCIE0)

    ISR(SIG....)
    {
    PORTC = GenTab[Licznik];
    PORTD ^= BIT(0); // !! to tak dodatkowo by zmierzyc czestotliwosc na oscyloskopie
    }


    i przerwanie pojechało 500kHz, oczywiście pod warunkiem, że program wyrobi się z obsługą przerwania przed wystąpieniem następnego.

    Oczywiście w podanym kodzie mogą być drobne błędy, ale rzut oka do PDF-a powinien załatwić sprawe.
  • Poziom 9  
    dziekuje za wskazowki...uzywam teraz trybu CTC...i ustawiam tak:
    OCR0=0x20; /// podobno mozna zjechac do 0 i otrzymac fck/2
    TCCR0=0x09; // i tu poprawka przyniosla efekt
    TIMSK=0x02; //

    procedura obslugi:
    #pragma interrupt_handler timer0_comp_isr:11
    void timer0_comp_isr(void)
    {
    PORTC ^= BIT(0);
    }

    wszystko byloby w porzadku tylko sygnal prostokatny na porcie0 bit0 zanika po mniej niz sekundzie...po resecie znow pojawia sie na niecala sekunde...a mikrokontroler dale dziala bo dziala klawiatura i wyswietlacz....dlaczego sie zablokowaly przerwania czy to moze w tym trybie sie jeszcze ustawia aby sie nie wylaczal..? jak zmienilem spowrotem na ustawienia fabryczne (1MHz) to przebieg byl wolniejszy ale i dluzej utrzymywal sie na porcie...juz bylo mozna odczytac czestotliwosc...wiec czy istnieje jeszcze jakas blokada na ten tryb..ze np wykona 255 calych cykli i sie wylaczy...a jesli tak to jak go wlaczyc?
  • Pomocny post
    Poziom 12  
    Code:
    OCR0=0x20; /// podobno mozna zjechac do 0 i otrzymac fck/2 

    Zjechać może i można, ale chyba tylko do sprzętowego przełączania pinu. bo obsługa przerwania w 1 cyklu jest niemożliwa.

    Code:
    void timer0_comp_isr(void)
    
    {
    PORTC ^= BIT(0);
    }


    Wrzuć co kompilator wyrzuca do assemblera do kompilacji.
    W sumie na obsługe jest 32 takty razem z wejściem i wyjściem z przerwania.

    Cytat:
    czy istnieje jeszcze jakas blokada na ten tryb..ze np wykona 255 calych cykli i sie wylaczy


    Nie ma takiej blokady. Jedyne co mi przychodzi do głowy, to zbyt wolna obsługa przerwania...

    Spróbuj włączyć toggling na pinie OC0.
    Code:
    TCCR0 = 0x19
    


    i wyłączyć przerwanie (nie ustawiać TIMSK).
    Jeżeli na pinie OC0 jest 250kHz, to znaczy że przerwanie wywołuje się OK, a jego obsługa jest za wolna. W takim wypadku pozostaje wstawka w ASM.

    Jeżeli na OC0 ginie przebieg, to nie mam pomysłu naszybko.
  • Poziom 9  
    tak to jest wina wolnej obslugi przerwania bo na OC0 byl przebieg..a jak ustawilem OCR0 na 255 to przebieg juz nie gasnie....ale czas czestotliwosc podobnie cos ponad 250kHz..niecale 300KHz...ale dalem kwarc 25MHz i uzyskalem czestotliwosc 500kHz...ale procedura bedzie dluzsza wiec i tak trzeba bedzie napisac ja w assemblerze...dziekuje za pomoc i temat uwazam za zamkniety...

    poprawny kod...

    OCR0=0xFF; //
    TCCR0=0x19; // dodatkowo generacja sprzetowa na pinie oc0
    TIMSK=0x02; //

    #pragma interrupt_handler timer0_comp_isr:11
    void timer0_comp_isr(void)
    { PORTC ^= BIT(0);
    }

  • Poziom 28  
    Moderowany przez inventco.eu:

    Zgodnie z regulaminem temat zamykam.