logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[C][Atmega8]presclaler,licznik T1, tablica stałych w PROGMEM

beniamin82 24 Kwi 2009 20:22 2882 3
REKLAMA
  • #1 6452840
    beniamin82
    Poziom 10  
    Piszę program sterujący zapłonem silnika 3 cylindrowego,
    Ma on na celu "emulację" mechanicznego regulatora odśrodkowego kąta wyprzedzenia zapłonu.

    Wymyśliłem sobie że tabelę zmiennych zapiszę w PROGMEM, poniżej program testujący rozwiązanie z tabelą.

    No i teraz:

    Niech mi ktoś proszę powie czy licznik T1 (16bitowy) zwiększa się co 5uS??
    Takie obliczenia założyłem w excelu obliczając czas po którym powinien komputerek dać iskrę.

    12,8Mhz / prescaler 64 =5uS


    zmienna indeks będzie docelowo pobierana z licznika T2 (zwiększającego się co 80uS (prescaler 1024) i jest wskaźnikiem prędkości obrotowej.
    Założyłem 459 punktów charakterystyki.

    np. dla wskaźnika 300 powinien program zaświecić diodę po 3,1ms i po takim samym czasie ją zgasić. natomiast podstawiając taką wartość w miejsce indeks widzę jak dioda miga około 3 razy na sek.


    Puszczając program tak jak poniżej, czyli z zwiększającym się indeksem widzę jak dioda miga coraz wolniej.

    teraz jeszcze jedno pytanko, jeżeli stałe z tabeli są 16bitowe to indeks pokazuje początek każdej stałej, czy początek kolejnego bajtu?

    No i oczywiście koronne pytanie: Ile trwa odczyt z pamięci PROGMEM.

    Tutaj programik testowy

    
    #define F_CPU 12800000L
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/pgmspace.h>
    
    static const PROGMEM int licznik[]=
    {64915,64911,64907,64903,64898,64894,64890,64886,64882,
    64878,64874,64870,64865,64861,64857,64853,64849,64845,
    
    ....cała tabela ma 459 stałych w zakresie od 64915do 62127....
    
    64841,64836,64832,64828,64824,64820,64816,64812,64808,
    64803,64799,64795,64791,64787,64783,64779,64774,64770,
    62292,62286,62280,62274,62268,62262,62256,62250,62244,
    62239,62233,62227,62221,62215,62209,62203,62197,62191,
    62186,62180,62174,62168,62162,62156,62150,62144,62138,
    62133,62127
    };
    
    volatile unsigned int  led,indeks,wys;
             
    
    SIGNAL (SIG_OVERFLOW1)
    {
    led=~led;
    PORTD=led;
    wys=1;
    
    if (indeks<450) {   indeks++;};
    
    }
    
    
    int main(void)
    {
    
    
    
    
    DDRD=0xFF; //PORT D jako wyjście
    
    
    TIMSK=_BV(TOIE1);
    TCCR1A=0x00;
    TCCR1B=_BV(CS10)|_BV(CS11); //prescaler ck/64
    
    
    sei();   //uruchomienie przerwań
    indeks=0;
    
    wys=1;
    
    
    while(1)    //pętla nieskończona
           {
    
    	  if (wys==1)
    	  {
    	  	  
    	   TCNT1=pgm_read_word(&licznik[indeks]);
           wys=0;
    
    	   }
               }
    
    
        }
     
     
  • REKLAMA
  • Pomocny post
    #2 6453856
    Dr.Vee
    VIP Zasłużony dla elektroda
    Obliczenia są +/- poprawne, pod warunkiem, że procesor rzeczywiście jest taktowany 12,8MHz.

    Domyślnie atmega8 działa na wewnętrznym rezonatorze 8MHz który jest dodatkowo dzielony przez 8. Żeby to zmienić musisz przeprogramować fuse bity.

    Najlepiej to zacznik od uzyskania częstotliwości 1Hz na jakimś pinie - miganie LED przy czasach rzędu 3,1ms dość ciężko zauważyć...

    Co do programu:
    0) najlepiej użyć trybu CTC timera1 - poczytaj datasheet.
    1) w tablicy licznik powinieneś mieć liczby typu unsigned, a nie int.
    2) led i wys mogą i powinny być typu uint8_t (unsigned char)
    3) odczyt z pamięci programu w Twoim przypadku to:
    obliczenie adresu = 2*indeks + adr. początkowy tablicy licznik (~ 8 cykli) + 2 instrukcje LPM po 3 cykle każda = ~14 cykli.
    4) sformatuj jakoś porządnie ten kod...

    Pozdrawiam,
    Dr.Vee
  • REKLAMA
  • #3 6460198
    beniamin82
    Poziom 10  
    Okazało się ze atmega chodziła na 1MHz...wewnętrznym oscylatorze...

    Ale teraz mam kolejny problem

    Dodano po 16 [minuty]:

    Więc jest tak, dzięki odpowiedniemu ustawieniu Fusebitów ustawiłem Atmegę na 8Mhz. Przeliczyłem tablicę stałych dla 8Mhz.
    I teraz mam pytanko:

    Uruchamiając ten program widać jak diody migają..

    
    
    #define F_CPU 800000L
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/pgmspace.h>
    
    static const PROGMEM unsigned licznik[]=
    {
    
    65146,65142,65138,65134,65130,65126,65122,65118,65113,
    65109,65105,65101,65097,65093,65089,65084,65080,65076,
    
              ------tablica zmiennych-----------
    65072,65068,65064,65060,65056,65051,65036,65031,65026
    63321,63315,63309,63303,63297,63291,63286,63280,63274
    
    };
    
    volatile unsigned char  led,wys;
    volatile unsigned int indeks;         
    
    SIGNAL (SIG_OVERFLOW1)
    {
    led=~led;
    PORTD=led;
    wys=1;
    
    if (indeks<330) {   indeks++;};
    
    }
    
    
    int main(void)
    {
    
    
    
    
    DDRD=0xFF; //PORT D jako wyjście
    
    
    TIMSK=_BV(TOIE1);
    TCCR1A=0x00;
    TCCR1B=_BV(CS10)|_BV(CS11); //prescaler ck/64
    
    
    sei();   //uruchomienie przerwań
    indeks=0;
    
    wys=1;
    
    
    while(1)    //pętla nieskończona
           {
    
    	  if (wys==1)
    	  {
    	  	  
    	   TCNT1=pgm_read_word(&licznik[indeks]);
           wys=0;
    
    	   }
    
           }
    
    
    
    
        }
      
    



    A w poniższym Kodzie diody się nie zapalają....
    są podłączone do portu przez oporniki do zasilania.

    Mam wrażenie że liczniki nie wchodzą w przerwanie. przy zastosowaniu polecenia w pętli while typu if (TCNT1>20){wsk_obr=0xF0;}; diody zaświecają się. ustawienia dla T1 skopiowałem żywcem.

    
    
    #define F_CPU 8000000L
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/pgmspace.h>
    #include <util/delay.h>
    
    static const PROGMEM uint16_t licznik[]=
    {
    65146,65142,65138,65134,65130,65126,65122,65118,65113,
    65109,65105,65101,65097,65093,65089,65084,65080,65076,
    ---------------------tablica stałych--------------------------------
    65072,65068,65064,65060,65056,65051,65036,65031,65026,
    63321,63315,63309,63303,63297,63291,63286,63280,63274};
    
    volatile uint16_t faza,cylinder,zakres,zawT2,Temp_przepT2,przepT2,przyspieszenie,indeks;
    
    volatile uint8_t wsk_obr,stan_portu;
            
    
    SIGNAL (SIG_OVERFLOW1)
    {
    wsk_obr=0xF0; 
    
    }
    
     
    SIGNAL (SIG_OVERFLOW0)
    {
    Temp_przepT2++;
    wsk_obr=0xF0; 
    }
    
    
    
    
    
    int main(void)
    
    {
    
    _delay_ms(5);
    
    DDRD=0xFF; //PORT D jako wyjście
    DDRC=0x00; //PORT C jako wejście
    
    
    TIMSK=_BV(TOIE1); //ustaw przerwanie T1
    TIMSK=_BV(TOIE0); //ustaw przerwanie T0
    
    TCCR1A=0x00;
    TCCR1B=_BV(CS10)|_BV(CS11); //prescaler ck/64
    
    TCCR0=_BV(CS02)|_BV(CS00); //prescaler ck/1024
    
    
    sei();   //uruchomienie przerwań
    
    wsk_obr=0x00; //wygaszenie diód
    
    TCNT1=0xFF00;
    TCNT0=0x01;
    
    while(1)    //pętla nieskończona
    
           {
           
         PORTD=~wsk_obr;	
    	
    	
            }
    }
    
    
    
     
    
    
  • #4 6463441
    beniamin82
    Poziom 10  
    Taka moja rada...

    Jeżeli NIKT, ale to NIKT wam nic nie podpowiada, zacznijcie czytać elektrodę..

    Powiem wam że po 2godzinach czytania, jak już miałem dosyć, znalazłem rozwiązanie problemu... i to całkiem prozaiczne...

    Otóż AVR studio ustawia sobie przy nowym projekcie procesor domyślny na Atmega128 (mimo że na dolnej listwie pisze ATMEGA8).

    i podczas kompilacji wstawia nie te adresy bitów i wszystko się sypie, oprócz standardowych portów i operacji...
REKLAMA