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 :)
Wenn du den Quarz gespart hast, was hast du dann stattdessen dort angeschlossen? Keramik-Resonator? RC-Kombi? Wie sind die Fuses gesetzt?
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.
Hi >Laufen sollte er ja auf 20 Mhz im 5V-Bereich. Es gibt keinen AVR mit internem 20MHz-Oszillator. MfG Spess
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;
Seite 36 im Datenblatt des von dir verwendeten Controllers. http://www.atmel.com/dyn/resources/prod_documents/doc8011.pdf Für die Problematik aber momentan nicht wirklich relevant, du legst ja keinen allzu großen Wert auf Genauigkeit.
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 | int main() |
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
Falk Willberg schrieb: > Im OP steht ja das Wort Ändern. Wie willst Du in einem Takt (nur) Bit0 > auf 1 setzen? > ... Die AVR haben genau dafür einen ganz speziellen Befehl. Und natürlich kennt den auch der C-Compiler .... http://www.mikrocontroller.net/articles/AVR-Tutorial:_IO-Grundlagen#Zugriff_auf_einzelne_Bits
Wie ist denn der zu sbi / cbi passende Befehl für den C-Compiler?
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
Danke euch allen für die Hilfe und das gigantische Licht, das mir aufgegangen ist :)
>...gigantische Licht
Scheint bei Dir etwa die Sonne?
Neid, Neid, Neid,....
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.