Archiv verlassen und diese Seite im Standarddesign anzeigen : Zeit am AVR: Delay und Timer-Interrupt lernen
runner02
20.12.2010, 11:57
Hallo @ alle!
Da ich nun den Ein- und Ausgang des AVRs beherrsche, und auch der ADC endlich klappt, möchte ich mich an das nächste große Thema wagen:
Zeitbestimmung mittels des AVRs.
Also, erstmals muss man ja die MHz definieren am Anfang des Programmes. Bei meinem Programm steht standartmäßig irgend ein Wert drinnen, und das hat mich auch nie gestört. Ich musste halt berücksichtigen, dass "50 ms" in echt 800ms waren oder so...
Nun ja, nun hängt die Frequenz des Chips laut Datenblatt ja angeblich von der Spannung ab??
Oder schafft er unter 4V keine 20 MHz??
Ich betreib ihn meist mit 3V, und wenn ich dann 10 Mhz definiere, sind das dann wirklich 10Mhz oder muss ich irgendwie die Spannung berücksichtigen??
Das ganze ist vollkommen unübersichtlich für mich, bitte um die Hilfe eines Profis :)
Mfg
Hi,
die Frequenzdefinition in der Software dient nur dazu, einigen Funktionen aus der Library (z.B. den _delay-Funktionen) die Taktfrequenz, mir der der Prozessor betrieben wird, mitzuteilen. Nur so können diese Funktionen zeitgenau funktionieren.
Die reale Taktfrequenz stellst Du in den Fuses ein (ich hoffe, davon hast Du schon mal was gehört ;) ) Du kannst entweder einen internen Takt verwenden (bei den meisten AVRs 1,0-8,0MHz) oder einen externen Takt per RC-Oszillator, Quarz oder Quarzoszillator wählen. Dann kannst Du - je nach Betriebsspannung und verwendetem Controller - bis 20MHz hochgehen. Die angaben im Datenblatt beziehen sich auf die maximal mögliche Taktfrequenz in Abhängigkeit von der Spannung.
Gruß,
askazo
runner02
20.12.2010, 13:08
Die reale Taktfrequenz stellst Du in den Fuses ein (ich hoffe, davon hast Du schon mal was gehört )
Das Wort ist mir schon geläufig, hab aber keine Ahnung was das bezeichnet :( :-k ](*,)
die Frequenzdefinition in der Software dient nur dazu, einigen Funktionen aus der Library (z.B. den _delay-Funktionen) die Taktfrequenz, mir der der Prozessor betrieben wird, mitzuteilen. Nur so können diese Funktionen zeitgenau funktionieren.
Das heißt, ich stelle per fuse die Frequenz ein, und oben teile ich die gewählte Frequenz dem delay (,..etc) mit??
Du kannst entweder einen internen Takt verwenden (bei den meisten AVRs 1,0-8,0MHz)
Ja, geanu den würde ich gerne verwenden... Kennst du dazu einen guten Link??
Dann kannst Du - je nach Betriebsspannung und verwendetem Controller - bis 20MHz hochgehenDas ghet nur mit exterenem Taktgeber?
Das heißt, ich stelle per fuse die Frequenz ein, und oben teile ich die gewählte Frequenz dem delay (,..etc) mit??
Genau!
Ja, geanu den würde ich gerne verwenden... Kennst du dazu einen guten Link??
Hier findest Du ein recht gutes Tutorial über Fusebits: http://www.wiki.elektronik-projekt.de/mikrocontroller/avr/fusebit_tutorial
Das ghet nur mit exterenem Taktgeber? Ja, Frequenzen über 8,0MHz gehen bei den Tiny-/Mega-AVRs nur über externe Taktgeber.
Gruß,
askazo
runner02
20.12.2010, 15:16
Die wohl am häufigsten geänderten Fusebits sind CKSEL0 bis CKSEL3 (Select Clock Source). Mit ihrer Hilfe wählt man die Taktquelle aus der der Controller seinen Takt erhält. Hier ist etwas Vorsicht geboten da eine falsche Einstellung den Controller lähmen kann. Eine falsche Einstellung lässt sich jedoch relativ leicht beheben. Die genauen Parameter können zwischen den einzelnen Typen variieren
Default: Interner RC Oszillator mit 1MHz (bzw 8MHz bei Typen mit Vorteiler)
Was ich der Seite entnehmen kann ist der interne Quarz automatisch auf 1Mhz gestellt?
Dann müsste ich es doch gar nicht verstellen?
Vor einer Stunde habe ich die Frequenz von 3.864 MHz (standartmäßig im AVR Studio) auf 8 Mhz verstelt, das war wohl nichts, dann hab ich es auf 1Mhz eingestellt. Da waren 10 sek in waitMs etwas über 8 sek....
Ist das WaitMs so ungenau, oder stimmt die Taktrate immer noch nicht??
hardware.bas
20.12.2010, 15:27
Es gibt keinen "internen" Quarz im AVR. Das wäre schön, dann brauchte
man keinen Externen. Ohne Quarz, also freilaufend intern mit 1MHz
hatte ich bisher bis ca. 2Prozent Abweichung und auch
temperaturabhängig. VG Micha
Standardmäsig ist der interne Oszillator auf 1MHz eingestellt. Wenn Du mit 1MHz hinkommst, brauchst Du nichts zu verändern. Das lohnt sich aber eigentlich nur für Batterieanwendungen, wenn man Energie sparen muss. Ansonsten sehe ich keinen Sinn darin, nur 1MHz zu benutzen wenn man ohne Aufwand auch 8MHz nutzen kann.
Bist Du sicher, dass Du an der richtigen Stelle die Frequenz verstellt hast?
3.864MHz kommt mir nämclich für den internen Ozillator sehr krumm vor (die mir bekannten AVRs haben immer 1,2,4 und 8MHz zur Auswahl)
Ansonsten schreib mal bitte, welchen AVR Du verwendest und poste mal Deinen Quellcode.
Gruß,
askazo
hardware.bas
20.12.2010, 16:53
3686400 Hz ist ok. und auch ein Standartwert. Damit kriegt man auch
die UART richtig hin. Doppelte und Vierfache Quarzfrequenzen sind auch
noch übliche Werte. VG Micha
runner02
20.12.2010, 17:29
Wenn Du mit 1MHz hinkommst, brauchst Du nichts zu verändern.
Naja, so hochleistungsfähige Programme schreibe ich dann ja doch nicht...
Momentan arbeite ich (nach wie vor) am ATtiny13.
3686400 Hz ist ok. und auch ein Standartwert. Damit kriegt man auch
die UART richtig hin.
Ja, aber wenn der Attiny automatisch auf 1MHz eigestellt ist, müsste ich ihn dann doch auf 3,68..MHz umfusen, sonst käme ich ja nicht auf die richtigen Zeiten bei wait/delay/...
Klapppt UART auch mit 1 MHz??? Der ist mein nächstes Ziel, gleich nach den Zeiteinstellungen!
Und da will ich dann gleich mit der richtigen Frequenz einsteigen...
___
Ach ja, die waitMs waren bei mir ja nicht sehr akkurat... Ist die delay-Funktion besser? Aber die hat ja auch nur die ungenaue Frequenz, oder ist da das Programm genauer?
Ich bin immer noch ein wenig von den Taktfrequenzen verwirrt, die Du hier angibst.... :-k
Der Tiny13 kann intern doch nur auf 128kHz, 4,8MHz oder 9,6MHz eingestellt werden (Zusätzlich noch CKDIV8). Wie kommst Du da auf 1MHz bzw. 3,68...Mhz???
Um auf die richtigen Zeiten bei wait/delay zu kommen, muss lediglich der gefuste Takt mit dem in der Software unter F_CPU angegebenen Wert übereinstimmen.
UART klappt eigentlich mit fast jeder Taktfrequenz. Allerdings bekommst Du mit einigen Frequenzen manche Baudraten nicht vernünftig hin.
Dein Tiny13 hat allerdings keine Hardware-UART, so dass Du Dir eine Soft-UART bauen müsstest. Ich würde da eher einen größeren Controller mit UART verwenden.
Gruß,
askazo
Besserwessi
21.12.2010, 12:21
Der tiny13 ist bei der internen Taktfrequenz eine Ausnahmen. Bei fast allen anderen Typen hat man Standardmäßig 1 MHz und dann meist noch 4 MHz, 8 MHz und 128 kHz zur Auswahl.
Die 3,68.. MHz ist eine Übliche Quarzfrequenz, wenn man eine RS232 Verbindung nutzen will. Mit etwas Glück kriegt man ggf. den internen Takt von 4 MHz auch noch so weit verstellt, aber der Sinn ist dann verloren, weil der interne Takt nicht so genau ist.
hardware.bas
21.12.2010, 18:37
Ums Umfusen kommt man nicht umhin... ist doch nicht so schlimm.
VG Micha
runner02
22.12.2010, 09:19
Um auf die richtigen Zeiten bei wait/delay zu kommen, muss lediglich der gefuste Takt mit dem in der Software unter F_CPU angegebenen Wert übereinstimmen.
Ja. So wie ich ausgetestet habe, müsste der Chip standartmäßig auf etwa 1MHz gefused sein. Irre ich mich da etwa?
Der Tiny13 kann intern doch nur auf 128kHz, 4,8MHz oder 9,6MHz eingestellt werden
Hat der 3 'innere Uhren' (:) ) und von denen wählt man beim fusen eine aus??
Wie kommst Du da auf 1MHz bzw. 3,68...Mhz???
Unter F_CPU steht beim workpad automatisch 3.684... drinnen.
Das habe ich verstellt auf 10 - da hats nicht gepasst.
Dann habe ich auf 1 gestellt - jetzt müssts ungefähr hinhauen...
Besserwessi
22.12.2010, 13:03
Bei der Auswahl des internen Taktes kann man wirklich verschiedene Oszillatoren wählen, oder einfach nur einen Teiler zuschalten. Die 128 kHz kommen vom Watchdog timer also einen extra Oszillator. Die alten Versionen haben wirklich die Frequenz des Oszillators oder gar den ganzen Oszillator umgeschaltet. Neu wird eher eine Teiler dazu geschaltet und der 1 MHz Takt den man Standardmäßig meist hat kommt von einem 8 MHz Takt der durch 8 geteilt wird.
runner02
23.12.2010, 15:51
Ich nehme an, der Befehl zum umfusen der Taktreferenz steht im datasheet?
Naja, wenn ich weiß, dass er auf 1Mhz läuft, dann passt das erstmal...
Batteriesparender ists ja auch, und auf speed kommts bei meinen bisherigen Programmen ja nicht an :)
Beim nächsten Projekt, einem Datumsmitzähler (Mo, xx.yy.20xx) kommt es auch nur auf Genauigkeit an, nicht auf Schnelligkeit...
Genügt für sowas eigentlich die interne Taktgebung oder ist die dafür zu ungenau (hm, welche Genauigkeit wäre denn akzeptabel? ... <1h pro 10 Jahre? Kann das zu schaffen sein??)
runner02
10.01.2011, 16:37
Möchte nur mal vermelden, dass ich eine Art Eieruhr für diverse Zwecke gebaut habe...
Der Chip ist ja serienmäßig auf 1Mhz gefused, und das habe ich mal so gelassen. Dann waitMs(5000) (also 5 sek) und das in einer Schleife oftmals ablaufen lassen (Ok, Energiesparen ist hier noch nicht dabei :) )
5 sek * 12 = 1 Min... 5*12 sek * x min
Mit 2 Tastern kann man 20 oder 50 Minuten einstellen, und dann leuchtet eine Status-LED....
Demnächst werde ich es mit delay versuchen... Und später mit sleep und interrupt....
hardware.bas
10.01.2011, 17:24
Eine Eieruhr ist ein dankbares Projekt zum Lernen, insbesonders
für Timerprozesse. Und eine Quarzgenauigkeit nicht notwendig.
Gute Wahl. VG Micha
Du solltest noch bedenken, dass solche delay-befehle und so bei zu großen werten etwas ungenau werden. Über 5-6s solltest du nicht nehmen. Bei diesen Anwendungen zwar nicht dramatisch, aber wenn es mal genau gehen soll, doch ein wichtiger Faktor.
mfg
runner02
12.01.2011, 20:47
Du solltest noch bedenken, dass solche delay-befehle und so bei zu großen werten etwas ungenau werden. Über 5-6s solltest du nicht nehmen. Bei diesen Anwendungen zwar nicht dramatisch, aber wenn es mal genau gehen soll, doch ein wichtiger Faktor.
Sobald ich Interrupts kann, werde ich das mit Timer-Interrupt und sleep ergänzen.
Ist bereits auf eine Lochrasterplatine gelötet, der Chip steckt nur im Sockel - also gut ergänzbar :)
Ich denke, ich poste das mal, falls weiter Anfänger nach einem Demoprogramm suchen
//----------------------------------------------------------------------
#define F_CPU 1000000 // Taktfrequenz des myAVR-Boards
#include <avr\io.h> // AVR Register und Konstantendefinitionen
//----------------------------------------------------------------------
uint16_t weckton ()
{
int i=0;
for (i; i<3000; i++)
{
PORTB=PORTB|(1<<PB2); // us = mikrosekunden ; 200us -> 5000Hz
waitMs(0.8);
PORTB=PORTB&(~(1<<PB2));
waitMs(0.8);
}
waitMs(70);
for (i; i<3000; i++)
{
PORTB=PORTB|(1<<PB2); // 200us -> 5000Hz
waitMs(1);
PORTB=PORTB&(~(1<<PB2));
waitMs(1);
}
waitMs(50);
for (i; i<2000; i++)
{
PORTB=PORTB|(1<<PB2); // us = mikrosekunden ; 200us -> 5000Hz
waitMs(1.5);
PORTB=PORTB&(~(1<<PB2));
waitMs(1.5);
}
return 0;
}
main ()
{
DDRB=0b11110110;
PORTB=0b00011001;
waitMs(500);
PORTB=PORTB&(~(1<<PB4));
while(true) // wichtig, dass Controller mehrmals if-abfragt!!!
{
if(!(PINB&(1 << PB0))) // Wenn Taster1 gedrückt, dann
{
PORTB=PORTB|(1<<PB1); // Status-LED: 2 min
for (int j=0; j<24;j++) //24* 5sek = 2Min (*10=20 min)
{
waitMs(6000); // 1000ms *60 sek -> min -> *2 min (6sek ~ 5sek laut AVR)
// waitms schafft nur 64K Zyklen, je nach Taktung zb. 30 sek -> Schleife
}
while (true)
{
weckton ();
}
}
if(!(PINB&(1 << PB3))) // Wenn Taster3 gedrückt, dann
{
PORTB=PORTB|(1<<PB4); // Status-LED: 5 min
for (int g=0; g<60;g++) //600* 5sek = 50Min (60*5 = 5 min)
{
waitMs(6000); // 1000ms *60 sek -> min -> *20 min (6sek ~ 5sek laut AVR)
// waitms schafft nur 64K Zyklen, je nach Taktung zb. 30 sek -> Schleife
}
while (true) //5 min
{
weckton ();
}
}
}
}
Danke, Micha ;)
Mfg
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.