Guten Tag,
ich bin Schüler und schreibe gerade meine ersten Programme für den
ATmgea8. Ich würde gerne ein Metronom programmieren, aber der Systemtakt
des Controllers ist wohl zu ungenau, deshalb wurde mir ein externer
Quarz empfohlen. Ich habe einen Quarz für 2MHz.
Jetzt meine Frage: Wie muss ich den anschließen bzw. was muss ich genau
einstellen?
Vielen Dank und Grüße aus Südtirol
Martin
Also bei einem Metronom sollte man die Ungenauigkeit des int.
Oszillators nicht merken können. Das wird eigentlich erst bei
asynchroner serieller Kommunikation interessant.
Dein Controller hat zwei Pins, die im Datenblatt mit "XTAL1" und "XTAL2"
beschriftet sind. Da kommt der Quarz mit seinen beiden Pins dran.
Und dann müssen von den beiden Pins jeweils noch ein Keramikkondensator
mit 12...22pF (der AVR verzeiht da eigentlich recht viel) zu Ground
dran.
Dazu dann noch F_CPU mit 2000000 definieren und die Fusebits so
einstellen, dass ein externer Crystal mit Low Freq. verwendet wird.
Für die Einstellung des Quarzes als Taktquelle musst du die Fuse Bits
anpassen. Ist hier beschrieben:
https://www.mikrocontroller.net/articles/AVR_Fuses
Dabei kommts auf dein Programmiertool an, deswegen Vorsicht.
Der Quarzanschluss ist hier beschrieben:
https://www.mikrocontroller.net/articles/Quarze_und_AVR
brauchst also noch zwei 22pF-Kondensatoren.
ACHTUNG: Erst den Quarz einbauen, dann Fusebits ändern, sonst hat der
Atmega keibe Taktversorgung mehr und du kannst ihn nur noch mit "Tricks"
programmieren!
martin schrieb:> Jetzt meine Frage: Wie muss ich den anschließen bzw. was muss ich genau> einstellen?
Datenblatt Seite 27
C1 und C2 richten sich nach dem Quarz und der so genannten
Lastkapazität, die dieser benötigt. Wenn du diese nicht kennst, geh'
einfach mit 2 x 22 pF ins Rennen und schau, ob am Ende alles sauber
anschwingt.
Dort stehen auch einige Fusebits, die du passend einstellen musst. Bei
einem 2-MHz-Quarz wäre CKOPT = 1 und CKSEL[3:1] = 110 sinnvoll. Auf
Seite 28 folgt eine Tabelle, aus der du weitere Bits auswählen musst.
Gehen wir mal davon aus, dass du unter “fast rising power” fällst (weil
dein Gerät mit einem Einschalter schlagartig an die Versorgungsspannung
angeschlossen wird), dann wären CKSEL[0] = 1 und SUT[1:0] = 10 sinnvoll.
Die Fusebytes sind auf Seite 216f. erklärt, das low byte sieht so aus:
1
+-----------------------------------------------+
2
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
3
+-----------------------------------------------+
4
| BOD | BOD | | |
5
|LEVEL| EN | SUT | CKSEL |
6
+-----------------------------------------------+
Gefüllt mit obigen Werten:
1
+-----------------------------------------------+
2
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
3
+-----------------------------------------------+
4
| BOD | BOD | | |
5
|LEVEL| EN | SUT | CKSEL |
6
+-----------------------------------------------+
7
+ 1 1 1 0 1 1 0 1 |
8
+-----------------------------------------------+
(Die beiden Bits für BODLEVEL und BODEN entsprechen der Voreinstellung.)
D.h. das low fuse byte wäre 0b11101101 oder 0xed.
Das Bit CKOPT befindet sich im fuse high byte, steht aber voreingestellt
bereits auf 1; daran muss man also nichts ändern.
> die Fusebits so einstellen, dass ein externer Crystal> mit Low Freq. verwendet wird.
Nein.
An dieser Stelle versteht Atmel unter "low-frequency" den 32 KiHz-Quarz,
sogenannter Uhrenquarz. Es muss "Crystal Oscillator" mit dem Bereich
3.0-8.0 MHz eingestellt werden.
Georg M. schrieb:> Wird es richtig schlagen
Er ist Anfänger, lass ihn doch erstmal überhaupt nur dem Teil ein paar
Töne entlocken. Seinem Spieltrieb freien Lauf lassen und am Ende
vielleicht gar mit einem Mikrofon aufgenommene Samples abspielen kann er
ja danach immer noch. ;-) (Dafür könnten 2 MHz Grundtakt allerdings
etwas zu wenig sein.)
Hallo,
habe jetzt Folgendes gemacht:
fuse.c:
#include <avr/io.h>
FUSES = {
.low = 0b11101101,
.high = HFUSE_DEFAULT
};
main.c:
#define F_CPU 2000000
#include <avr/io.h>
int main (void)
{
DDRB =0;
DDRB |= (1<<PB1);
do
{
//Hier schalte ich eine LED auf PB1 mit einer vorgegebenen Frequenz
ein
und aus
}while(1);
return(0);
}
Aber die die LED blinkt mit der halben Frequenz, als die von mir
eingestellte.
Danke im Voraus und Grüße
Martin
Du bist ja ein Spassvogel, den entscheidenden Teil deines Programmes
hast du geheim gehalten.
Mal angenommen, du hast ihn richtig programmiert, dann läuft dein
Mikrocontroller immer noch mit den Standard-Einstellungen. Das wäre der
interne R/C Oszillator mit 8 MHz, sowie dem Vorteiler durch 8 (CLLDIV8)
-> Ergibt 1 MHz Systemtakt.
Du musst die Fuses mit deinem Programmieradapter einstellen. Wenn du nur
die Kommandos zum Flashen des Programms verwendet hast, sind die Fuses
immer noch unverändert.
Welche Hard- und Software benutzt du denn dazu?
Ich nutze: usbtiny, avrdude, CodeBlocks
Stefanus F. schrieb:> Du musst die Fuses mit deinem Programmieradapter einstellen. Wenn du nur> die Kommandos zum Flashen des Programms verwendet hast, sind die Fuses> immer noch unverändert.
Wie stelle ich das ein?
Abermals Danke!!
Hier mein gesamtes Programm:
#define F_CPU 2000000
#include <avr/io.h>
int main (void)
{
int i;
int x;
DDRB =0;
DDRB |= (1<<PB1);
do
{
//EIN
PORTB |= (1<<PB1);
x=100;
do {
i=20000;
do
{
i--;
}while (i!=0);
x--;
}while (x!=0);
//AUS
PORTB &= ~(1<<PB1);
x=100;
do {
i=20000;
do
{
i--;
}while (i!=0);
x--;
}while (x!=0);
}while(1);
return(0);
}
martin schrieb:>> immer noch unverändert.> Wie stelle ich das ein?
fast genauso wie du den Programmierst, statt ... nimmtst du die
Parameter für Controller/Programmer usw.
avrdude ... -U lfuse:w:<0xHH>:m
zum nachlesen hier: http://www.ladyada.net/learn/avr/avrdude.html
hier kannst du die Fuses berechnen lassen/kontrollieren, wenn du die
falsch setzt brauchst du sonst eventuell nen HV Fuse Programmer oder
einen externen Takt.
http://www.engbedded.com/fusecalc/
martin schrieb:> do {> i=20000;> do> {> i--;> }while (i!=0);>> x--;>> }while (x!=0)
was machen diese do/while schleifen? wenn die nur verzögern sollen
kannst du auch <util/delay.h> einbinden und dann _delay_ms() oder
_delay_us() verwenden.
ne Stufe besser wäre nen Timer mit Interrupt zu verwenden (und den Pin
im Interrupt zu toggeln), oder wenn es vom Timing mit den Vorteilern
passt kannst du auch mit einem Timer den Pin als 50/50 PWM Ausgang
benutzen.
toggeln kannst du indem du PINB1/PORTB1 einliest und dann PORTB1 auf das
Gegenteil setzt.
Timer hat auch den Vorteil dass du später z.b. ein Poti einlesen kannst
und die Taktdauer dynamisch ändern kannst.
edit:
avrdude ... -U lfuse:w:<0xHH>:m
gilt natürlich nur für die low Fuse, für high muss da hfuse:w... stehen
K. S. schrieb:> fast genauso wie du den Programmierst, statt ... nimmtst du die> Parameter für Controller/Programmer usw.
Die Werte für die Fuses hat er im Programmtext stehen.
Aber auch von da aus muss man sie programmieren.
> avrdude ... -U lfuse:w:<0xHH>:m
In diesem Falle gänge das dann auch mit -U lfuse:w:program.elf.
Oder eben manuell -U lfuse:w:0xed
Wenn man mit dem Atmel Studio programmiert, muss man meiner Erinnerung
nach irgendwo ein Häkchen setzen, damit nicht nur der Flash programmiert
wird, aber sie können das auch aus dem ELF-File heraus.
> hier kannst du die Fuses berechnen lassen/kontrollieren
Die hatte ich ja oben schon vorgerechnet.
Stefanus F. schrieb:> Du musst die Fuses mit deinem Programmieradapter einstellen. Wenn du nur> die Kommandos zum Flashen des Programms verwendet hast, sind die Fuses> immer noch unverändert.>> Welche Hard- und Software benutzt du denn dazu?martin schrieb:> Wie stelle ich das ein?
Das kann ich Dir immer noch nicht sagen, weil du meine Frage nach der
Hard- und Software nicht beantwortet hast.
Deine Verzögerungs-schleifen erscheinen mir fragwürdig:
Hast du dich vergewissert, dass sie (korrekter Systemtakt vorausgesetzt)
exakt so lange dauern, wie sie sollen? Das hängt doch sehr stark davon
ab, welchen Maschinencode der Compiler daraus erzeugt, was wiederum von
den Optimierungseinstellungen und der Version des Compilers abhängt.
Ausserdem denke ich, dass der Compiler die Schleifen komplett entfernen
darf, weil sie keinen Effekt auf RAM und I/O Register haben. Dass er
leere Schleifen oft (unerwartet) entfernt ist hier geradezu ein
Klassiker.
Für solche Zwecke gibt es die include Datei
https://www.nongnu.org/avr-libc/user-manual/group__util__delay.html,
benutze sie.
Hallo,
danke erstmal für die weiteren Antworten. Ich benutze CodeBlocks.
Ich habe jetzt, wie man im Anhang sieht, ein neues Tool erstellt.
Wenn ich es auf den usbtiny übertragen will kommt die Fehlermeldung, die
ich euch auch in den Anhang kopiert habe.
Im main.c habe ich nichts mehr definiert, muss ich das denn?
Habt bitte Geduld, bin ein totaler Anfänger :)
Danke und schönen Abend
Martin