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

Pomiar okresu przez AVR

10 Sie 2005 21:43 1757 9
  • Poziom 11  
    Witam,

    Chce pomierzyc okres sygnału prostokatnego za pomocą 90S2313. Dla testów podaje z generatora na wejsice INT0 prostokąt o f=1kHz, czyli okres = 1ms. Idea pomiaru to taka ze w momencie wykrycia narastajacego zbocza procek zgłasza przerwanie na INT0, wtedy zeruje i właczam Timer1. Przy nastepnym narastajacym zboczu zatrzymuje Timer1 a zawartosc jego rejestrów TCNT1H i TCNT1L (przy kwarcy 8MHz i podziale CK/8) jest bezposrednia miarą okresu, czyli rejestry te powinnny zawierac wartosc 1000. Dodam tylko ze program napisany jest w C a odczytana wartosc okresu przesyłam do komputera printfem.
    Sprawa wydaje sie dosc prosta i oczywista ale jak sie za to zabrałem to problem najwyrazniej przerósł moje hehe mozliwości;). Do kompa docieraja przypadkowe liczby i nijak sie maja do spodziewanej wartosci okresu:(. Załaczam kod programu, moze ktos znjadzie bład albo mi wyjasni dlaczego to nie dziala tak jak powinno.

    Z góry dziekuję za zainteresowanie i wszelka pomoc

    Pozdrawiam!

    Code:

    #include <90s2313.h>
    #include <stdio.h>

    unsigned int Okres, temp1, temp2;
    unsigned char flaga;

    // Przerwanie INT0
    interrupt [EXT_INT0] void ext_int0_isr(void)
    {
       if(flaga==1)
       {
          TCNT1H=0x00;   //zerowanie Timer1
          TCNT1L=0x00;   //                           
          flaga=2;      //przy nastepnym narastajacym    zboczu skocz do else
       }
       else
       {
          temp1=TCNT1L;   //odczyt zawartosci rejestrów Timer1
          temp2=TCNT1H;            
          Okres = ( temp2*256 + temp1);   // konieczne obliczenia
             printf("%d ", Okres);      //wyslanie wartosci okresu do kompa
          flaga=1;      
       }
    }

    void main(void)
    {
       PORTB=0x00;
       DDRB=0x00;

       PORTD=0x00;   
       DDRD=0x00;
       
       TCCR1B=0x02;   //preskaler CK/8
       GIMSK=0x40;   //zezwolenie na obsluge INT0
       MCUCR=0x03;   //wyzwalanie zboczem narasjatacym
       GIFR=0x40;
       
       UCR=0x08;   //zezwolenie na przerwania od nadajnika
       UBRR=0x19;   //predkosc 19200
       
       flaga=1;
       #asm("sei")      //zezwolenie na przerwania

       while (1)
             {

             };
    }
  • Sklep HeluKabel
  • VIP Zasłużony dla elektroda
    1. W przerwaniu wywal wszystko co w nim być nie powinno, czyli zero czasochłonnych pierdół np. wyświetlanie, warunki, wysyłanie po UART itp., od tego jest pętla główna.
    2. A po co zatrzymujesz timer ? Nie lepiej go zerować i niech będzie na bierząco w następnym pomiarze aktualizowany ? Co jakiś czas robisz średnią pomiarów i ją wyświetlasz ?
    3.Tak chyba prościej :
    Code:
    Okres=TCNT1;

    --
    Pozdrawiam, Daniel
  • Sklep HeluKabel
  • Poziom 28  
    Dla predkosci 19200 przeslanie 3 bajtow(2 bajty danej i zero) zajmie ponad 1ms. Stad moga sie brac te bzdury ktore odbierasz. Sprobuj zwiekszyc predkosc lub wstrzymac pomiar na czas nadawania.
    Pozdro
    Dexter
  • Poziom 11  
    Dziękuje Panowie za pomoc! Zrobiłem tak jak radziliscie tzn skróciłem kod programu w przerwaniu do minimum, wysyłanie danych do kompa(czyli printf) przeniosłem do funkcji main a oprócz tego blokuje przerwania od INT0 na czas transmisji danych do komputera. Po tych zabiegach wszystko PRAWIE ładnie smiga:(. Pojawił sie koljeny problem!!! Gdy wysyłam dana do komputera instrukcja printf, to im wiecej znaków wysyłam za pomoca printfa tym mniej dokłane mam wskazania okresu, np

    Code:
    printf("%d", okres);

    do komputera leci dokładna wartosc okresu(porównałem ze wskazaniami czestosciomierza i oscyloskopu)

    a gdy wysyłam np
    Code:
    printf("%d %d, okres, okres+60);

    to wartosc okresu jest zanirzona w stosunku do tej własciwej

    Napisałem juz nawet własna fukcje wysyłajaca dane do kompa, ale ciagle to samo.
    natomiast gdy wysyłam dane na LCD to dokładnosc wskazan jest własciwa
    Dlaczego im wiecej znaków wysyłam printfem tym mniejsza dokładnosc wskazan, z czego to wynika? Moze ktos spotkał sie juz z taka sytuacją?

    Z góry dzieki za wszelka pomoc
  • VIP Zasłużony dla elektroda
    Proponowałbym zrezygnować z tej funkcji C i zrobić własną obsługę wysyłania danych w przerwaniu od "Transmit Data Complete". Chyba, że ktoś zna bibliotekę, która juz obsługuje transmisję UART w ten sposób, bo standardowa jest strasznie nieoptymalna czasowo - zajmuje się pustymi pętlami, które przysłaniają czasowo pomiary. Inny sposób, to zwiększyć prędkość transmisji.
    --
    Pozdrawiam, Daniel
  • Pomocny dla użytkowników
    Sprawdź priorytet przerwań ! Jeżeli RS ma wyższy to przy długim ciągu wstrzymuje ci pomiar w przerwaniu zegarowym.

    Lepiej mierzyć okres albo nawet mierzyć średnią z kilku pomiarów podzieloną przez ilość okresów (zwiększa to N krotnie dokładność kosztem wydłużenia pomiaru).
    Zatrzymać pomiar, wysłać dane i znów mierzyć !
  • Poziom 28  
    W procesorach AVR nie ma czegos takiego jak priorytety przerwan w doslownym tego slowa znaczeniu, tak jak to np. jest C51. W AVR priorytety obowiazuja tylko w momencie JEDNOCZESNEGO nadejscia przerwan. Sprzetowo przerwanie jest nieprzerywalne. Mozna natomiast to zrobic programowo, wstawiajac w procedure przerwania ktora bedzie miala nizszy "priorytet" instrukcje "sei"
    Pozdro
    Dexter
  • Pomocny dla użytkowników
    To z tego wynika, że przerwanie INT jest gubione lub opóźnione przez obsługę nadawania na RS, jeśli dobrze myślę ?
  • Pomocny post
    Poziom 28  
    W programie przytoczonym powyzej jest tylko jedno zrodlo przerwania wiec nie ma co tu wogole sie rozwodzic nad priorytetami. Kolega napisal ze blokuje przerwania na czas nadawania. Problem w tym ze gdy nadawanie trwa za dlugo to flaga przerwania jest ustawiana ale nie nastepuje skok do przerwania. Dopiero gdy skonczy sie nadawanie przerwania sa odblokowane, poniewaz flaga jest ustawiona od jakiegos czasu to nastepuje od razu skok do obslugi przerwania,. Problem w tym ze w przerwaniu jest uruchamiany licznik i na jego odczytach bazuje pomiar. Powinien byc uruchomiony dokladnie w momencie wystapienia zbocza a jest uruchamiany kiedys tam bo przerwania sa zablokowane. Rozwiazaniem tego problemu jest zerowanie flagi przerwania INTF0 tuz przed ponownym zezwoleniem na przerwania. W ten sposob jeden lub wiecej okresow zostanie pominietych ale pomiar zawsze bedzie przebiegal nie zaklocony innymi procesami.
    Pozdro
    Dexter
  • Poziom 11  
    Witam,

    Wielkie dzieki za pomoc, okazało sie ze własnie istota problemu lezy w blokowaniu flagi INTF0, gdy to zrobiłem to wszystko zaczeło śmigać jak należy.

    Dlatego temat uważam za zamknięty!

    Jeszcze raz wielkie dzięki zapomoć i zainteresowanie!

    Pozdrawiam