AVR Frage zu Timer-Einstellungen bei ATmega

Gast #3799731
Lesenswert?

Hallo zusammen,

ich versuche mich gerade am Timer meines ATmega88. Ich möchte ein 
Clock-Signal erzeugen, welches dann auf einen Pin ausgegeben werden 
soll. Die Frequenz sollte so bei 350kHz liegen.

Der Timer an sich läuft, aber irgendwie komme ich mit den erforderlichen 
Einstellungen nicht ganz zu recht, genauer gesagt, ich komme nicht auf 
die gewünschte Frequenz. Ich habe im Moment etwa 125kHz, d.h. eine 
Periodendauer von etwa 8µs, Mit Oszi angesehen.

Der ATmega läuft mit 8MHz.

Den Timer wollte ich im CTC Modus laufen lassen.

Unten ist mein Code dazu.

Wäre klasse, wenn mir da jemand aufzeigen könnte, was isch da falsch 
mache oder wo ich da einen Denkfehler drin habe.

Gruß und schon einmal vielen Dank!

Mein Code sieht bisher mal so aus:
1
void main(void)
2
{
3
    cli();        
4
    port();    
5
    time();    
6

7
    while(1);
8
}
9
            
10

11

12
void time(void)
13
{
14
   TCCR0B |= (1<<CS00);  
15
   TCCR0A = (1<<WGM01);  
16
   OCR0A = 6;
17
   TIMSK0 |= (1<<OCIE0A);  
18
}
19

20

21
ISR (TIMER0_COMPA_vect)
22
{
23
    PORTB ^= ( 1 << PB0 );
24
}
#3799738
Lesenswert?

Marco schrieb:
> Mein Code sieht bisher mal so aus:

Wirklich? Ich sehe keine Funktion port(), und das Aufrufen von cli(), 
d.h. das Deaktivieren von Interrupts macht auch nicht wirklich Sinn, 
wenn diese zuvor nie eingeschaltet worden sind (sei()).

In welchem Modus möchtest du den Timer denn betreiben? Das reine 
Ausgeben eines PWM-Signals kann mittels Output Compares direkt in 
Hardware geschehen. Oder willst du es in Software lösen?

Übrigens: Da du mit jedem Interrupt das Signal nur toggelst, musst du 
deinen Timer so einstellen, dass er mit der doppelten Frequenz, d.h. 700 
kHz Interrupts auslöst.

Mit freundlichen Grüßen,
Karol Babioch
Gast #3799775
Lesenswert?

Hallo, ich habe beim kopieren einige Kommentare gelöscht, dabei habe ich 
wohl auch Codezeilen gelöscht.

Output Compares werde ich mir mal anschauen.
1
void main(void)
2
{
3
    cli();        
4
    port();    
5
    time();    
6
    sei();
7
    while(1);
8
}
9
            
10
void port(void)  
11
{
12
  DDRB |= (1 << PB)|(1 << OUT2_ON_PIN);                                            
13
  PORTB &= ~(1 << PB0);                  
14
}
15

16
void time(void)
17
{
18
   TCCR0B |= (1<<CS00);  
19
   TCCR0A = (1<<WGM01);  
20
   OCR0A = 6;
21
   TIMSK0 |= (1<<OCIE0A);  
22
}
23

24

25
ISR (TIMER0_COMPA_vect)
26
{
27
    PORTB ^= ( 1 << PB0 );
28
}
#3799801
Lesenswert?

Marco schrieb:
> Hallo,
>
> vielleicht noch als Hinweis. Werde mir die Output Compare Units wie
> geschrieben einmal anschauen und ausprobieren, aber wenn ich diesen Weg
> schon einmal angefangen habe, wäre es nicht schlecht, auch das ans
> Laufen zu bekommen, auch wenn es nicht der Beste Weg ist.


Das ist überhaupt kein Weg.
Mit einem Interrupt alle 6 Taktzyklen wird das nichts. Alleine bis der 
AVR die Bearbeitung des Interrupt Vektors aufnimmt vergehen schon einige 
Taktzyklen (wenn mich mein Gedächtnis nicht trügt dann sind das 3, je 
nachdem welcher Befehl durch den Interrupt unterbrochen wird). Den 
unvermeidlichen reti noch dazu. Sichern des Statusregisters und Port 
toggeln und du bist schon über den 6 Taktzklen draussen. Sprich: die 
Interrupts werden schneller generiert, als sie abgearbeitet werden 
können. Mit Assembler könnte man das gerade noch so retten, indem man 
den Porttoggler direkt in die Vektortabelle einschreibt.

Nimm die Hardware. Dafür ist sie gemacht worden.
Hinweis. Auch mit einem Timer im PWM Modus kann man prima Schwingungen 
erzeugen. Dann allerdings wirklich runter bis auf 2 Takzyklen pro 
Schwingung. Also 4Mhz bei 8Mhz Taktfrequenz.
#3799843
Lesenswert?

Wie berechnest du eigentlich deinen OCRA-Wert?

Wenn ich das richtig sehe, hast du CTC Mode mit OCRA als TOP-Wert und 
Prescaler=1 / no prescaling.

Damit zählt der Counter alle 0,125 µs einen hoch. Mit dem Wert "6" (also 
zählen von 0...6) wird der Interrupt alle 0,875 µs aufgerufen. 
Entsprechende Frequenz wären c.a 1,14 MHz.


Ich komme auf 8MHz/350kHz = 22,86....

Nur theoretisch angenommen die ISR würde keine Rechenzeit benötigen 
müsstest du diesen Wert halbieren und 1 abziehen um den richtigen Wert 
für OCRA in deiner Lösung zu bekommen...
Das ist bei mir nicht 6.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren