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

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

drago256 09 Kwi 2010 20:29 4399 17
  • #1 7940844
    drago256
    Poziom 11  
    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:
     
    #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.
  • #2 7940969
    matitlf
    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.
  • #3 7940987
    mpietras
    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ść.
  • #4 7941021
    drago256
    Poziom 11  
    Przepraszam z pomyłkę - kwarc rzeczywiście 4.9152 MHZ.

    Rzeczywiście chyba pomyliłem piny..
  • #5 7941037
    Konto nie istnieje
    Poziom 1  
  • #7 7941991
    drago256
    Poziom 11  
    zumek -masz racje. Tylko jakby nie patrzeć pomimo to nie działa...

    Obecnie kod wygląda tak:
    
    #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...)
  • #8 7943613
    zumek
    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
  • #9 7943988
    drago256
    Poziom 11  
    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
  • #10 7944760
    Smoczy
    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
  • #11 7946530
    chrobot
    Poziom 16  
    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 ;)
  • #13 7948060
    zumek
    Poziom 39  
    janbernat napisał:
    drago256 napisał:

    
       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ć:
    
    #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
  • #14 7948194
    janbernat
    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.
  • #15 7948299
    zumek
    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
     OCR1A  _freq_time; 

    wyglądała
    OCR1A  = 15;;


    Jaśniej :?:
  • #16 7948389
    janbernat
    Poziom 38  
    Dzięki- dużo jaśniej.
    P.S.
    A dlaczego:
    
    #define _freq_time  F_CPU/(153600UL*2) - 1;
    //...
    OCR1A = _freq_time;
    

    jest poprawniej niż:
    
    #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ć.
  • #17 7948989
    drago256
    Poziom 11  
    @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:
    
    #define _freq_time  F_CPU/(153600UL*2) - 1;
    //...
    OCR1A = _freq_time;
    

    jest poprawniej niż:
    
    #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.
  • #18 7949811
    janbernat
    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.
REKLAMA