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

[ATMega8] [C] generator przebiegu prostokątnego 153.6 kHz

09 Kwi 2010 20:29 4177 17
  • Poziom 10  
    Witam.
    Mam problem z generatorem przebiegu prostokątnego 153.6 kHZ. Na początku próbowałem go zrealizować przy pomocy układu 4060 (Motorola) i kwarcu 4915.2 MHz. Niestety jak się okazało z tym układem są zbyt duż problemy.. Postanowiłem więc użyć procka - padło na ATMega8 (był pod ręką). Napisałem program:
    Code:
     
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #ifndef F_CPU
    #define F_CPU 4915200
    #endif

    #ifndef _BV
    #define _BV(bit) (1<< (bit))
    #endif

    const unsigned int _freq_time = F_CPU/16 - 1;

    int main(void)
    {
       DDRD = _BV(PD5);
       TCCR1A = _BV(COM1A0);
       TCCR1B = _BV(WGM12);
       TCCR1B |= _BV(CS10);
       OCR1A = _freq_time;
       while(1);
       return 0;

    }



    Fusebity ustawiłem na hFuse-D9, lFuse-FF
    Program wgrałem bez problemów. Odczyt przy ustawionych fusebitach i ponowny zapis(z podłączonym kwarcem 4915.2MHz) odbył się bezproblemowo.
    Niestety na pinie PD5 nie mam sygnału prostokątnego.
    W związku z tym mam pytanie odnośnie kodu programu - czy wszystko jest ok ? Ewentualnie w czym może tkwić problem?

    Z góry dziękuję za pomoc.
  • AM TechnologiesAM Technologies
  • Poziom 2  
    Witam,

    Ustawienia wyglądają na dobre, ale sygnał jeśli będzie to na pinie PB1 (OC1A). Nie musisz ustawiać tego pinu jako output w rejestrze DDRB.

    Pozdrawiam.
  • Poziom 17  
    Na pierwszy rzut oka w kwarcu. Nie możliwe żebyś zastosował kwarc 4915.2MHz do taktowania Atmega8 ale tu nie no to chodzi bo (chyba) masz kwarc 4.9152MHz. Sprawdz wartość _freq_time.
    1. Timer1 ma tylko albo aż 16 bitów.
    2. Nie zna C i nie wiem czy integer może przyjmować taką wartość.
  • Poziom 10  
    Przepraszam z pomyłkę - kwarc rzeczywiście 4.9152 MHZ.

    Rzeczywiście chyba pomyliłem piny..
  • AM TechnologiesAM Technologies
  • Poziom 39  
    Skąd wytrzasnąłeś taki wzór :?:
    Code:
    const unsigned int _freq_time = F_CPU/16 - 1; 

    Powinno być:
    Code:

    #define _freq_time = F_CPU/(153600UL*2) - 1; //preskaler=1
  • Poziom 10  
    zumek -masz racje. Tylko jakby nie patrzeć pomimo to nie działa...

    Obecnie kod wygląda tak:
    Code:

    #include <avr/io.h>
    #include <avr/interrupt.h>
    #ifndef F_CPU
    #define F_CPU 4915200
    #endif

    #ifndef _BV
    #define _BV(bit) (1<< (bit))
    #endif

    #define _freq_time = (F_CPU/153600UL * 2) - 1;

    int main(void)
    {
       DDRB = _BV(PB1);
       TCCR1A = _BV(COM1A0);
       TCCR1B = _BV(WGM12);
       TCCR1B |= _BV(CS10);
       OCR1A  _freq_time;
       while(1);



    i dalej nie widze zmian na porcie


    Przepraszam, źle zmierzyłem - na PB1 jest 1.86V. Podpiołem diodę, ale nie widać by mrugała (z tą częstotliwością pewnie nawet bym nie zobaczył). Czy jest możliwe by to była wina kwarcu- mimo iż spokojnie komunikuje się z prockiem przy jego użyciu? (jeśli oczywiście program jest ok...)
  • Poziom 39  
    drago256 napisał:
    Obecnie kod wygląda tak:

    Kolego :!:
    Jeżeli Twoim zdaniem, F_CPU/(153600UL*2) - 1 jest równoważne (F_CPU/153600UL * 2) - 1, to .... wybacz - zmień zainteresowania :P
  • Poziom 10  
    Sorki gałgan ze mnie. Na procka wrzuciłem oczywiście poprawny wzór - błąd pojawił się przy wrzucaniu na forum...

    Tak jak pisałem wcześniej - żadnych zmian na porcie
  • Poziom 19  
    Tak czytając ten post, zastanawiam się w jaki sposób mierzysz ten przebieg na porcie, bo jeżeli w inny niz oscyloskopem lub miernikiem częstotliwości, to chyba będzie trochę trudno cokolwiek ustalić. Napisz, jak dokonujesz pomiaru, może to pomoże w ustaleniu przyczyny
  • Poziom 15  
    Code:
    while(1)//petla 
    
    {

    // cykl 
    for(C1=0;C1<MC1;C1++) //pętla
       {
       //postaw w stan wysoki   zapal lede
       LED_ON;     //zapal led
          for(B=0;B<10;B++)
                {
        asm("nop");asm("nop"); // dobrac czasy
                }

       //koniec stanu wysokiego
       LED_OFF;//zgas led
       //
       //przerwa długa stan niski    dobrac czasy
       for(D1=0;D1<MD1;D1++)
                {
                asm("nop");   // lub tu dobrac czasy
                }
       //koniec długiej przerwy
       }


    dobierz czasy do kwarcu i dla "nop" i zadziała ;)
  • Poziom 38  
    drago256 napisał:

    Code:

       OCR1A  _freq_time;


    Ponieważ nie znam się na C a też chciałbym się czegoś nauczyć- co robi program w tej linijce?
    Bo w Bascomie jak wstawię np:
    Code:

    OCR1A=50

    to procesor generuje sygnał.
  • Poziom 39  
    janbernat napisał:
    drago256 napisał:

    Code:

       OCR1A  _freq_time;


    Ponieważ nie znam się na C a też chciałbym się czegoś nauczyć- co robi program w tej linijce?

    Ta linia kodu po "przejściu" przez preprocesor, będzie wyglądała następująco:OCR1A = 15
    Całym sprawcą zamieszania jestem ja, ale preprocesor naprawił mój błąd i kod bezbłędnie się kompiluje.
    Poprawnie powinno być:
    Code:

    #define _freq_time  F_CPU/(153600UL*2) - 1;
    //...
    OCR1A = _freq_time;


    janbernat - jeśli chcesz wiedzieć "dlaczego tak", to poczytaj o "stworzeniu" zwanym przeprocesorem :P
  • Poziom 38  
    Słyszałem- ale nie przypuszczałem że jest taki samodzielny.
    Skąd wie że to proste podstawienie a nie np. |= albo iloczyn?
    Nie może po prostu wywalić błędu?
    Kompilator to ma rózne poziomy optymalizacji- a preprocesor?
    P.S.
    Znalazłem kwarc 4915200.
    Podział ma równo 15 i rzeczywiście pięknie chodzi- dokładnie 153.6kHz.
    Pozwoliło mi to sprawdzić że oscyloskop dobrze mierzy.
  • Poziom 39  
    janbernat napisał:
    ...Skąd wie że to proste podstawienie a nie np. |= albo iloczyn?
    Nie może po prostu wywalić błędu?

    Nie wie :P
    Zauważ, że po #define i etykiecie _freq_time_ znalazł się taki ciąg: = F_CPU/(153600UL*2) - 1;
    Preprocesor pominął znak '=' i zajął się wyrażeniem 'F_CPU/(153600UL*2) - 1'.
    Po obliczeniu wyrażenia, etykieta '_freq_time_' wyglądała tak: = 15; i taki ciąg wstawił w kodzie, w miejsce etykiety '_freq_time_'.
    Po jego "zabiegach", linia
    Code:
     OCR1A  _freq_time; 

    wyglądała
    Code:
    OCR1A  = 15;;


    Jaśniej :?:
  • Poziom 38  
    Dzięki- dużo jaśniej.
    P.S.
    A dlaczego:
    Code:

    #define _freq_time  F_CPU/(153600UL*2) - 1;
    //...
    OCR1A = _freq_time;

    jest poprawniej niż:
    Code:

    #define _freq_time = F_CPU/(153600UL*2) - 1; //preskaler=1
    OCR1A    _freq_time;

    Może dlatego że ktoś zobaczy brak = i wstawi i zamiast podstawienia = będzie porównanie== i- w maliny.
    Ja bym tak zrobił.
    Z tym C to trzeba uważać.
  • Poziom 10  
    @Smoczy : chyba trafiłeś.Do pomiaru używałem miernika częstotliwości. Jak się okazało po dłuższej przerwie zaprzestał działać (podpiołem pod niego 40kHz i nic).

    Mam w domu jakiś multimetr z opcją pomiaru częstotliwości, ale zakres tylko do 20kHz. Jakby nie patrzeć pokazuje przekroczenie zakresu więc zapewne coś się generuje.

    Z tego co napisał janbernat z programem nie ma problemu, więc myślę, że pozostaje tylko zbudować na szybko jakiś miernik częstotliwości i się upewnić.

    W związku z tym mam pytanko: czy nie ma ktoś z was sprawdzonego kodu- miernika częstotliwości na ATmega8 ? Mógłbym go sam napisać, ale biorąc pod uwagę to, że nie mam zbyt wielkiego doświadczenia, wolałbym wykluczyć możliwość popełnienia błędu przy tworzeniu urządzenia pomiarowego (już jeden częstotliwościomierz napsuł mi trochę krwi).

    Z góry dziękuję za pomoc.


    janbernat napisał:
    Dzięki- dużo jaśniej.
    P.S.
    A dlaczego:
    Code:

    #define _freq_time  F_CPU/(153600UL*2) - 1;
    //...
    OCR1A = _freq_time;

    jest poprawniej niż:
    Code:

    #define _freq_time = F_CPU/(153600UL*2) - 1; //preskaler=1
    OCR1A    _freq_time;

    Może dlatego że ktoś zobaczy brak = i wstawi i zamiast podstawienia = będzie porównanie== i- w maliny.
    Ja bym tak zrobił.
    Z tym C to trzeba uważać.


    @janbernet: Jeżeli wstawisz porównanie to kompilator zgłosi błąd.
  • Poziom 38  
    W zasadzie to robisz coś na kształt częstościomierza.
    Wystarczy zbramkować innym timerem.
    Przy Twoich ustawieniach mam na oscyloskopie 153.6kHz.
    Dla kwarcu 4915200Hz.
    Tak że chyba dobrze.