Hallo zusammen :)
Bisher war mir der Takt des Mikrocontrollers immer relativ egal, da
weder Performance noch Timing ausschlaggebend waren. Für etwas aktuelles
ist zwar das Timing wieder eher uninteressant (in einem vernünftigen
Rahmen), Performance dafür umso wichtiger.
Ich verwende dafür einen ATMega 644P, der ja seine 20Mhz schaffen sollte
bei 5V. Den Quarz habe ich mir allerdings wieder gespart.
Ich habe jetzt allerdings den Eindruck, dass der Mikrocontroller
langsamer ist als er sein sollte... :/ kann es sein, dass er (spürbar)
langsamer taktet, wenn kein Quarz beteiligt ist?
Danke euch :)
Jain! ;-)
Wenn der Quarz eine niedrigere Frequenz hat als der interne Generator
dann ja. Guck mal in das Datenblatt, auf welcher Frequenz er arbeitet,
wenn die Werkseinstellungen noch nicht geändert wurden.
MfG Paul
Hi
>Ich habe jetzt allerdings den Eindruck, dass der Mikrocontroller>langsamer ist als er sein sollte... :/ kann es sein, dass er (spürbar)>langsamer taktet, wenn kein Quarz beteiligt ist?
Was hast du über die Fuses eingestellt? Und woran merkst du das?
MfG Spess
> kann es sein, dass er (spürbar) langsamer taktet, wenn kein Quarz beteiligt ist?
Abgesehen davon, dass der interne Oszillator recht instabil ist
(abhängig von Spannung und Temperatur, siehe Datenblatt) und dessen
Frequenz demnach auch etwas nach unten abweichen kann, nein. ;)
Wie kommst du überhaupt zu der Aussage? Gemessen? Wenn nicht: Du
könntest z.B. mal einen Pin timergesteuert togglen und mit einem Oszi
schauen, ob er Controller das tut, was du denkst.
Naja, ich schreibe in C, sodass ich nicht genau weiß, wie viel er nun
wirklich pro Sekunde schaffen sollte. Direkt Pins ändern geht da soweit
ich weiß ja auch nicht, ohne den ganzen Port neuzuschreiben (was auch
wieder mehrere Maschinenbefehle sind?).
Es ist kein Quarz angeschlossen, überhaupt nichts der Art. Hat bisher
immer prima funktioniert :) Die AVRs (oder zumindest alle die ich bisher
in den Fingern hatte) haben ja alle interne Oszillatoren, oder?
In den Fuses steht er auf "Int. RC Osc.".
Laufen sollte er ja auf 20 Mhz im 5V-Bereich.
Hi,
der 644P hat einen internal RC Oscillator mit 8MHz die von Werk her
durch 8 geteilt werden.
==> Wenn du die Fuses nicht verändert hast läuft dein Kontroller also
mit 1MHz.
Max. kannst du allerdings 8MHz erreichen wobei dieser Clock zwischen
7.3MHz und 8.1MHz liegen darf. Er ist also ziemlich ungenau aber für die
meisten Anwendungen genau genug.
Wenn du die 20MHz ausnutzen willst brauchst du schon eine externe
Taktquelle mit 20MHz.
Servus
Andreas
Wenn man den internen Oszillator ohne weitere Teiler verwendet und das
CAL-Byte auf 0xff setzt, kommt man bei einem ATmega8 oder ATmega48 knapp
auf 16MHz.
Der ATmega644 könnte sich ähnlich verhalten.
Uff! Sieht aus, als hätte ich Nachhilfe nötig :|
Der lief dann also die ganze Zeit auf 1Mhz... kein Wunder, dass mir das
langsam vorkam. Mit CKDIV8=0 läuft es schon gleich wesentlich
schneller.
Was ist das CAL-Byte?
Und was muss ich beim Anschluss eines Quarzes beachten, außer den
Kondensatoren? Sorry, für mich ist das leider Neuland... :/
Aber schonmal danke für die Erkenntis! :)
>Und was muss ich beim Anschluss eines Quarzes beachten, außer den>Kondensatoren? Sorry, für mich ist das leider Neuland... :/
Quarz nah ran an die Pins und guter Kontakt der Kondensatoren zu GND.
Oder nimm einen Quarzoszillator, sowas hier:
http://www.reichelt.de/?;ACTION=3;LA=2;GROUPID=3174;ARTICLE=13694;
Susanne schrieb:
> Direkt Pins ändern geht da soweit> ich weiß ja auch nicht, ohne den ganzen Port neuzuschreiben (was auch> wieder mehrere Maschinenbefehle sind?).
Das Beschreiben geht sogar in einem Takt -- auch mit C.
1
#include<avr/io.h>
2
intmain()
3
{
4
DDRD=_BV(PIN2);
5
while(1)
6
{
7
PIND=_BV(PIN2);
8
}
9
}
Übersetzt nach Assembler mit z.B. avr-gcc 4.3.3 von Ubuntu:
avr-gcc -g -S -mmcu=atmega164p -Os -o toggle.s toggle.c
ergibt ab Zeile 87 :
1
.LM2:
2
out 41-32,r24
3
rjmp .L2
Wie man sieht eine wunderbare Schleife, die einfach nur eine Zelle 43-32
also Zelle 9 mit r24 beschreibt. Der Compiler hat dafür gesorgt, dass in
Register r24 4 steht.
Wenn man in das Datenblatt (Version 8011M–AVR–08/09) vom ATmega164P /
ATmega644P schaut, findet man, dass dies ein Toggeln des Pins D4 bewirkt
(11.2.2).
Die Tabelle von Kapitel 28 hilft nun voraus zu sagen, dass OUT immer
genau einen Takt und rjmp immer genau zwei Takte braucht. Alle drei
Takte wird also einmal getoggelt also ist die Frequenz am Pin genau
sechs mal kleiner als die des Prozessors.
C zu verwenden ist also keine Entschuldigung dafür nicht zu wissen, was
der Prozessor tut -- es gibt sogar Compiler die voraussagen wie viel
Energie eine Operation kostet und dann die Operationen auswählen, die am
wenigsten Energie brauchen. Ja, sie können dies sogar im Assembly
annotieren.
Du soltest daher
- einen Quarz mit 20 Mhz verwenden, wenn knapp 16 Mhz reichen, weiter
den RC Oszilator verwenden, s.o.
- natürlich C weiter verwenden
- dir die performancekritischen Stellen ruhig den assemblierten Code
ansehen -- mit der Option -g sieht man sogar die Zeilen nummern des
C-Programms, so dass man sie leichter zuordnen kann.
- wenn das dann noch nicht reicht -- nicht Assembler verwenden, sondern
darüber nachdenken, ob man den Algorithmus nicht umformen oder anders
heran gehen kann, so dass es trotzdem passen wird.
Schwierig ist es manchmal für den Compiler Schleifen Invarianten zu
erkennen und sie dann automatisch außerhalb zu erledigen. Wenn Du zu
viele lebendige (1) Variablen benutzt kann es sein, dass er sie nicht
mehr alle in Registern halten kann. Auch den Wertebereich von
Parametern zu erraten kann schwierig sein. Wenn Du weißt dass Du für
manche Operationen nur 8-Bit benötigst, dann sag dem Compiler dies in
dem Du einen geeigneten Datentyp wählst. Auch ein Cast innerhalb von
Berechnungen zu einem 8-bit Typ, kann vorausgesetzt es kann nicht zu
Überläufen kommen, wunder wirken.
viel Erfolg und Grüße,
Thorsten
P.S. falls jemand nicht weiß was lebendig bedeutet...
(1) Eine Variable ist lebendig, nachdem sie geschrieben wurde, bis sie
das letzte mal gelesen wurde, vor dem nächsten Schreiben oder Ende der
Funktion. Globale Variablen werden in der Regel nicht in Registern
gespeichert und sind daher teurer. Viele sprechende Variablen Namen zu
benutzen kostet oft nichts.
Hallo Susanne,
wenn 8 MHz nicht reichen brauchst du einen Quarz.
Mit dem OSCCAL – Oscillator Calibration Register ist
es möglich den Internen Oszillator zu verstellen.
Das ist aber nur um Einflüsse von Versorgungsspannung
und Temperatur auszugleichen. Ein "Hochdrehen" auf
16 MHz liegt auserhalb der Spezifikation, interne Module
wie AD-Wandler, EEProm etc. arbeiten dann mit falschem
Timing und damit gerne falsch.
Beim Quarz geht es bis 20 MHz, wenn mal UART benötigt
besser "nur" 18,432 MHz (Baudratenquarz).
Kondensatoren (22 pF sollten passen) mit Quarz nahe
an den µC.
Bei den Fuses auf "Full Swing Crystal Oscillator"
(CKSEL3..1 011) und Startzeit nach Versorgungslage
(Datenblatt Tabelle 6.6).
AVR
Thorsten schrieb:
> Susanne schrieb:>> Direkt Pins ändern geht da soweit>> ich weiß ja auch nicht, ohne den ganzen Port neuzuschreiben (was auch>> wieder mehrere Maschinenbefehle sind?).>> Das Beschreiben geht sogar in einem Takt -- auch mit C.
...
>
1
> .LM2:
2
> out 41-32,r24
3
> rjmp .L2
4
>
5
>
...
> Wenn man in das Datenblatt (Version 8011M–AVR–08/09) vom ATmega164P /> ATmega644P schaut, findet man, dass dies ein Toggeln des Pins D4 bewirkt> (11.2.2).
Im OP steht ja das Wort Ändern. Wie willst Du in einem Takt (nur) Bit0
auf 1 setzen?
...
> C zu verwenden ist also keine Entschuldigung dafür nicht zu wissen, was> der Prozessor tut
Das stimmt natürlich.
Falk
Moin
Das toggling übernimmt anscheined die HW im AVR
aus dem oben genannten datenblatt.
11.2.2 Toggling the Pin
Writing a logic one to PINxn toggles the value of PORTxn, independent on
the value of DDRxn.
Note that the SBI instruction can be used to toggle one single bit in a
port.
AVR ist jar Harvard Architektur mit getrennten Daten und Adress Bussen,
der Wert der geschrieben wird, kommt aus einem register, somit ist der
Befehl in einem Takt abarbeit bar. Befehlsdekodierung läuft getrennt.
gruss
Hi
>11.2.2 Toggling the Pin>Writing a logic one to PINxn toggles the value of PORTxn, independent on>the value of DDRxn.>Note that the SBI instruction can be used to toggle one single bit in a>port.
Hat nur einen Schönheitsfehler: sbi/cbi sind nur in einem beschränkten
Adressbereich anwendbar. Und bei einigen AVRs liegen einige Portregister
außerhalb dieses Adressbereichs.
MfG Spess
Susanne schrieb:
> Wie ist denn der zu sbi / cbi passende Befehl für den C-Compiler?
Beim avr-gcc
PORTx |= ( 1 << PIN_NR );
PORTx &= ~( 1 << PIN_NR );
:-)
So habe ich's bisher auch immer gemacht :)
Hatte aber iwie angenommen, dass der Compiler das nicht in sbi / cbi
übersetzt, sondern das Portregister neu berechnet und vollständig neu
schreibt.
Susanne schrieb:
> So habe ich's bisher auch immer gemacht :)> Hatte aber iwie angenommen, dass der Compiler das nicht in sbi / cbi> übersetzt, sondern das Portregister neu berechnet und vollständig neu> schreibt.
So dämlich sind die Compiler dann auch wieder nicht.
Das ist eine der einfacheren Übungen für einen Optimizer.
Hallo!
>Wie ist denn der zu sbi / cbi passende Befehl für den C-Compiler?
#define sbi(ADDRESS,BIT) ((ADDRESS)|=(1<<(BIT)))
#define cbi(ADDRESS,BIT) ((ADDRESS)&=~(1<<(BIT)))
Gruss
Thomas