Port mit 8MHz toggeln

Gast #1580794
Lesenswert?

Ich brauche zum Testen der Geschwindigkeit von Optokopplern eine 
Schaltung die mir verschiedene Frequenzen macht:
8kHz
80kHz
800kHz
8MHz

Anstelle eines Quarzosszillators und eine paar TTL 7490 Teiler durch 10 
überlege ich das mal mit einem ATtiny25 zu machen.
Ich würde das gerne mal in C programmieren. Leider bin ich mit den 
Timer-Registern des ATtiny25 nicht recht schlau.
Wie kann ich das programmieren?
Habe dieses Blinkprogramm:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3

4
#define Led_gelb_toggle PINB = (1 << PIN4);
5

6
void Port_init(void);
7

8
int main(void)
9
{
10
  Port_init();
11
  while(1)
12
  {
13
    /*
14
    Portleitungen abfragen
15
    Geschwindigkeit einstellen
16
    */
17
  }
18
}
19
//***********************************************
20
void Port_init(void)
21
{
22
  DDRB = (1 << DDB4);  // PB4 als Output der  Led_gelb
23
  PORTB =  0;
24

25
  TCCR1 = 0b00001110;  // Prescaler = CK / 8192
26
  TIMSK |= (1 << TOIE1);  // Timer1 Overflow Interrupt Enable
27
  sei();        // Enable Interrrupt
28
}
29
//***********************************************
30
ISR(TIMER1_OVF_vect)
31
{
32
  Led_gelb_toggle // Led an PB4 toggeln
33
}
34
//***********************************************
Das blinkt schön mit 2Hz.
Wie aber kann ich jetzt auf 8MHz kommen?
Ist da ein PIC eventuel die bessere Wahl?
#1580804
Lesenswert?

Hallo,

der schnellste Umschalttakt per Timer im CTC-Mode ist Clock/2 mit 
Prescaler auf 1 und Comparewert auf 0. Dann den Ausgang festlegen und 
die Hardware das erledigen lassen.

Muß also mit 16MHz Takt laufen damit 8MHz rauskommen.
Bei einigen AVR kann man auch den Systemtakt auf einem Pin ausgeben 
lassen.

Gruß aus Berlin
Michael
Gast #1580811
Lesenswert?

Entweder arbeitest du im CTC Modus oder mit der Harsware PWM.
Im 16 Bit CTC Modus berechnet sich die Frequenz zu:
f = (Taktfrequenz des µC)/(Prescaler*(1+OCR0A))

je nachdem wie du nun OCR0A einstellst kannst du deine Frequenz 
variieren und in der ISR des Pin toggeln. Aber nehmen wir mal an du 
stellst Prescaler auf 1 und OCR0A ebenfalls auf 1 --> f=8Mhz. Da du aber 
den Pin toggelst, hast du effektiv auch nur 4MHz. Ich weiss jetzt nicht 
ob ein Wert von OCR0A=0 zulässig ist, aber wenn ja, dann hast du deine 
8Mhz. Den Rest musst natürlich noch selber ausrechnen. Wie alles 
eingestellt wird steht im Datenblatt oder hier im Forum im GCC Tutorial.
Gast #1580855
Lesenswert?

A. K. schrieb:
> Sachte, der Tiny25 hat einen Highspeed-Timer, mit dem auch bei langsamem
> CPU-Takt über eine PLL bis zu 32MHz Pinfrequenz fabrizieren kann.

Brauche mal ein paar Code-Schnipsel, drehe im Moment ziemlich am Rad.

Ächz keuch stöhn!
#1580858
Lesenswert?

Hallo,

CTC schrieb:
> je nachdem wie du nun OCR0A einstellst kannst du deine Frequenz
> variieren und in der ISR des Pin toggeln. Aber nehmen wir mal an du
> stellst Prescaler auf 1 und OCR0A ebenfalls auf 1 --> f=8Mhz. Da du aber
> den Pin toggelst, hast du effektiv auch nur 4MHz. Ich weiss jetzt nicht
> ob ein Wert von OCR0A=0 zulässig ist, aber wenn ja, dann hast du deine
> 8Mhz. Den Rest musst natürlich noch selber ausrechnen. Wie alles
> eingestellt wird steht im Datenblatt oder hier im Forum im GCC Tutorial.

Ja, Comparewert 0 im CTC-Mode ist zulässig und erzeugt Clock/2.
Ist in den Datenblättern nicht überall direkt erwähnt, wenn man sich 
aber das Timingdiagramm des CTC-Mode genauer anschaut, sieht man, warum 
es so funktioniert.

Gruß aus Berlin
Michael
Gast #1580940
Lesenswert?

A. K. schrieb:
> Ich habe mit einem solchen Teil mal einen Taktgenerator gebaut, der über
> ein Poti und dem Kalibrierregister des Oszillators durchstimmbar ist,
> Code anbei.

Bin dabei das durchzuarbeiten. Vielen lieben Dank, ist ganz toll!
#1585131
Lesenswert?

Ich greif A.K. mal vor (scheint schon weg zu sein)
1
#define loop_until_bit_is_set(p,b)   { while( !( (p) & (1<<(b)) ) ) ; }

einfach eine while-Schleife, die das Bit PLOCK im Register PLLCSR 
abfrägt und solange looped, solange es nicht gesetzt ist. Allerdings aus 
Makro ausgeführt, damit es keine Probleme bei der Parameterübergabe 
gibt.

Ohne das Makro hätte man einfach geschrieben
1
   while( ! ( PLLCSR & (1<<PLOCK) ) )
2
     ;
Gast #1585366
Lesenswert?

Die Funktion:

loop_until_bit_is_set(bla, blub);

scheint recht universell zu sein, es werden anscheinend zwei Werte 
übergeben,
die Adresse des Registers und die Bitposition.
Finde es so etwas besser lesbar, die Übergabe der Parameter kostet 
natürlich Resourcen...
Habe mich nur gewundert, das die Funktion im Programm 32MHz.c nirgendwo 
deklariert noch definiert ist.
Würde diese Definition halt gern mal sehen.

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