Forum: Mikrocontroller und Digitale Elektronik Wie generiere ich zwei Takte am besten


von Thomas Braun (Gast)


Lesenswert?

Hallo,

ich muss mit einem 8MHz-Atmega8 zwei Takte generieren einen ganz
normalen mit 500kHz und dann einen der nach 4096 Takten des ersten ein
kurzes "High" ausgibt.

Momentan nutzen ich den Counter1 um OC-Mode und lasse bei 0x08 den OC1A
pin umschalten, für den zweiten Takt lasse ich den Timer2 zählen,
generiere damit einen Interrupt nach 4096*16 Takten (Prescaler 1024 /
OC-Wert 0x63), der dann kurz den Ausgang an- und ausschaltet.

Das ganze scheint mir aber nicht gerade die ressourcensparendste
Methode. Und da meine Software gerade sowieso ein paar Probleme macht
versuche ich erstmal das in den Griff zu bekommen, könnte der Grund
sein.
Leider kann ich den OC2-Ausgang nicht nutzen, da ich den Pin für den
SPI-Bus brauche.

Hat jemand einen guten Tip für mich?

Danke
Thomas

von Hubert.G (Gast)


Lesenswert?

Alle 4096 Takte ein Pin toggeln zu lasse genügt doch auch ein Register

von inoffizieller WM-Rahul (Gast)


Lesenswert?

>Hat jemand einen guten Tip für mich?
Ob der gut ist, kann ich nicht beurteilen
Du zählst in der OC-ISR eine Int-Variable von 4095 herunter. Immer,
wenn die 0 ist, schaltest du den Pin an (oder andersherum):

n=4095

if (n--)
{
 PORTx &= ~(1<<ausgang2);
// Port wird bei jedem Interrupt ausgeschaltet
}
else
{
 PORTx |=(1<<ausgang2); // bei n=0 wird er eingeschaltet
 n = 4095;
}
kann auch 4096 sein...

von Jan M. (mueschel)


Lesenswert?

Kommt drauf an, welche Ressourcen du sparen willst.
Willst du Rechenzeit sparen, dürfte deine Lösung mit zwei Countern die
beste sein.
Willst du einen Hardware-Counter sparen und hast genügend Rechenzeit,
dann fällt mir auch gerade keine Lösung ein, die nicht eine Auslastung
>60% verursacht

von Thomas Braun (Gast)


Lesenswert?

Sparen will ich Systemauslastung also Rechnenzeit, vor allem aber gern
den Interrupt, da das Timing probleme macht, wenn der mit anderen
(USART) Interrupts zusammenkommt.

>Alle 4096 Takte ein Pin toggeln zu lasse genügt doch auch ein
Register

Problem ist das ich da nicht togglen kann sondern nur ein kurzes High
senden darf (also an - aus).
Ist das mit dem OC-Pin eines Timers, überhaupt möglich?

von inoffizieller WM-Rahul (Gast)


Lesenswert?

>Ist das mit dem OC-Pin eines Timers, überhaupt möglich?
Nur wenn er nicht mit dem Timer verbunden ist.

von Martin K. (mkohler)


Lesenswert?

Ich würde es wie der "inoffizieller WM-Rahul" machen.
Da brauchst du nur einen Zähler und die Zusatzbelastung durch das
Dekrementieren ist gering.

von Jan M. (mueschel)


Lesenswert?

@Martin & WM-Rahul:
Die Belastung durch diese Schleife ist ganz erheblich: Die OC-ISR würde
alle 16 Systemtakte aufgerufen werden.
Die Ausführungsdauer der Schleife würde ich mal mit 4-6 Takten
annehmen. Dazu noch das Springen in und aus der ISR macht nochmal 6-8
Takte, damit wären wir bei 10-14 Takte Code, die alle 16 Takte
ausgeführt werden. Auslastung alleine damit: 75%

von Michael U. (Gast)


Lesenswert?

Hallo,

bin nicht sicher, ob es aufgeht:
die 500kHz per Timer in Hardware erledigen.
Die 4096 500kHz-Takte auch per Timer im CTC-Mode, sind ja dann rund 122
Hz.
Den 2. Timer musst Du beim Initialisieren ja nur einmal Taktgenau
starten, die bleiben dann ja syncron.

Gruß aus Berlin
Michael

von Sonic (Gast)


Lesenswert?

die Auslastung hast Du immer. 500kHz sind halt mal 1/16 Deiner
Taktfrequenz, wenn Du da noch viel agieren willst bleibt sehr wenig
Zeit übrig, Jedenfalls nicht für zeitkritische Programmteile.

von Jan M. (mueschel)


Lesenswert?

@Michael: Ich weiß nicht, wie Thomas das beschriebene umgesetzt hat,
aber dein Text klingt praktisch identisch zum Original-Post

@Sonic: In der ursprünglichen Umsetzung hat man keine ISR, die alle 16
Takte aufgerufen wird. Das toggeln von OC1A erfolgt automatisch ohne
ISR. Nur für den langsamen Takt bräuchte man eine ISR.

@Thomas Braun: Ich glaube, ich liege richtig, wenn ich deine Frage
formuliere als
"Wie kann ich nach einer bestimmten Anzahl Takte einen Pin kurz an und
wieder ausschalten, ohne eine ISR bemühen zu müssen?"

von Rolf Magnus (Gast)


Lesenswert?

> Die Ausführungsdauer der Schleife würde ich mal mit 4-6 Takten
> annehmen. Dazu noch das Springen in und aus der ISR macht nochmal
> 6-8 Takte, damit wären wir bei 10-14 Takte Code, die alle 16 Takte
> ausgeführt werden. Auslastung alleine damit: 75%

Das ist viel zu optimistisch. Im Interrupt-Fall dauert das Springen in
den Interrupt-Vektor 4 Taktzyklen. Falls gerade ein Befehl ausgeführt
wird, der mehr als einen Taktzyklus dauert, wird der vorher noch
fertiggemacht. Der längste Befehl braucht vier, also können bis zu drei
dazukommen. Das rjmp im Interrupt-Vektor braucht nochmal zwei. Das reti
am Ende braucht vier. Damit braucht eine komplett leere
Interrupt-Routine schon 10 bis 13 Taktzyklen. Ein Inkrement braucht
zwar nur einen Taktzyklus, aber verändert die Flags. Das heißt, man muß
erst das SREG sichern. Das geht aber nicht direkt, also muß man erst ein
Register sichern. push + SREG lesen + push machen nochmal 5 Taktzyklen.
Die umgekehrte Operation am Ende auch nochmal. Wenn wir also nur ein
Register inkrementieren wollen, kommen wir mit 21 bis 24 Taktzyklen
davon. Falls die Variable im RAM liegt, werden's nochmal vier mehr.

von Jan M. (mueschel)


Lesenswert?

@Rolf
Da hast du wohl Recht, da hab ich einiges vergessen. In dieser
Anwendung ist es sogar nicht nur ein einfaches Register, sondern es
braucht 16bit für die Variable.

von Michael U. (Gast)


Lesenswert?

Hallo,
@Jan M.: da habe ich mich wohl dann irritieren lassen.
Nur verstehe ich dann das Problem nicht.
Wenn die 500kHz in Hardware erzeugt werden, gibt es nur alle rund 8ms
(wenn ich mich nicht verrechnet habe) einen IRQ, der sbi/cbi macht.
Das sind dann wie im vorigen Posting schon ausgerechnet 10-13 Takte + 2
für sbi/cbi.
Da wüßte ich dann aber in Software aber nichts mehr einzusparen...

Gruß aus Berlin
Michael

von Thomas Braun (Gast)


Lesenswert?

@ Jan
Genau das ist die Frage - wie mache ich das ohne ISR.

@ Michael
Naja es sind 122/s, klar nicht besonders oft, wenn aber gerade eine
andere Interruptschleife läuft, wird der Takt dann verspätet ausgegeben
und das macht Probleme. Daher würde ich das gern per Hardware machen.

von Michael U. (Gast)


Lesenswert?

Hallo,

naja, kommt darauf an, wieviel sich der Impuls verspäten darf (in
Taktzyklen des AVR), wie lang die anderen ISR sind, ob man die kürzen
kann, welche auftreten können, wie zeitkritisch die sind, ob man darin
evtl. den Interrupt freigeben könnte usw. usw.

Ansonsten 12Bit-Zähler ran, Monoflop dahinter, mehr Hardware geht wohl
nicht. ;)

Gruß aus Berlin
Michael

von Uwe (Gast)


Lesenswert?

Hi!
Nur so als Gedanke:
T1 macht 500Khz, damit Timer2 in CTC-Mode(127) extern takten und bei
OC2 Int. ausführen um Ausgang abzuschalten.(vorher natürlich setzen
lassen) Wenn Platz in IRQ-Tabelle "CBI OC2" + reti ditekt eintragen.
Der Imp.an OC2 wäre dann 4? Takte.
Verbrät natürlich haufenweise Hardware und ich habe nicht alles
überprüft.

Viel Erfolg, Uwe

von Profi (Gast)


Lesenswert?

Aus dem Mega8 Datenblatt:
16-bit Timer/Counter1
The 16-bit Timer/Counter unit allows accurate program execution timing
(event management),
wave generation, and signal timing measurement. The main features are:
• True 16-bit Design (i.e., allows 16-bit PWM)

Also: mit dem Timer erzeugst Du ein PWM-Signal mit 1/8192 oder noch
kürzer. Den Prescaler und die PWM-Periode stellst du so ein, dass das
Signal nur alle 2µs*4096=8192µs kommt.

Die 500kHz erzeugst Du mit einem 8-bit-Counter.

von Jan M. (Gast)


Lesenswert?

Richtig, eine 16bit-PWM kann bei 8 Mhz alle 65535 Takte (aka 8192 µs)
einen 1 Takt langen Impuls generieren. Sehr schön, und wie gewünscht
ohne ISR.
Bleibt nur das Problem, dass eben dieser PWM-Ausgang OC2 und MOSI auf
dem selben pin liegen beim mega8 und Thomas SPI verwenden will...

von Jan M. (Gast)


Lesenswert?

Gerade gesehen:
Ich weiß nicht, inwieweit dein Board schon fertig ist, aber wie sieht
es mit einem Mega88 aus? Der ist pinkompatibel, kann aber auch an PD3
die 16bit-PWM ausgeben. Damit hättest du sowohl SPI als auch die PWM.

von Thomas Braun (Gast)


Lesenswert?

Das klingt gut, an die PWM hatte ich mal am Anfang gedacht, aber wegen
OC2-Pin verworfen. Ein Mega88 als Austausch dürfte kein Problem sein,
kostet zwar ein paar cent mehr, ist aber nicht viel.
Danke !

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.