Kenne mich mit ATmega gut aus, versuche gerade ein Atxmega mal unter Assembler auszuprobieren. Port´s usw. habe ich erfolgreich hinter mich gebracht. Bin gerade am erfolgreichen testen vom ADC und habe festgestellt, das im Datenblatt zwar von einem "ADCA_CH0_RESL" und "ADCA_CH0_RESH" als ADC Kanal0 Endergebnis - Register die Rede ist. Aber es gibt ja nur ein "ADCA_CH0_RES" Register, welches als 16Bit Register fungiert. Bei einem ATmega hat man immer Werte über 8Bit so eingeladen: ldi r16, Registername_LOWBYTE ldi r17, Registername_HIGHBYTE Im Datenblatt habe ich jetzt gefunden, das bei den 16Bit Register der HIGH Wert in ein Register "ADC_TEMP" zwischengespeichert bzw. abgelegt wird. Deshalb habe ich es nun so gelöst: ldi r16, ADCA_CH0_RES ldi r17, ADCA_TEMP Das funktioniert auch, jedoch wollte ich hier mal nachfragen, ob das so überhaupt richtig gelöst ist, oder ob das Auslesen des ADC-16Bit Registers "ADCA_CH0_RES" eigentlich ganz anders, halt professioneller gemacht wird? Ist halt für einen alten ATmega Programmierer etwas ungewohnt... Danke
> Bei einem ATmega hat man immer Werte über 8Bit so eingeladen: > ldi ... Wohl eher mit in bzw. lds. > Das funktioniert auch ... ?
Ahh JA, macht der Gewohnheit.... Natürlich beim ATxmega mit LDS! und nicht mit LDI! Aber ist das denn so in Ordnung??? mit dem Laden des HIGH wertes aus dem "TEMP" Register? Danke
Dies nun kann ich leider nicht beantworten, da ich die ATxmega nicht kenne, hatte mich nur gewundert, dass es dort per ldi funktioniert,
Tom schrieb: > Ahh JA, macht der Gewohnheit.... > > Natürlich beim ATxmega mit LDS! und nicht mit LDI! Auch bei den Classic-AVRs wäre "ldi" in jedem Fall falsch gewesen. Entweder "lds" oder "in", je nachdem ob das Register memory mapped ist oder über den IO-Space erreichbar. Du kannst Assembler nicht wirklich, stimmt's?
Beitrag #6010693 wurde von einem Moderator gelöscht.
> Aber es gibt ja nur ein "ADCA_CH0_RES" Register
Und welche Adresse sollte dieses haben? Wenn ich mir, als alt gewordener
ATmega-Programmierer, ein ATxmega-Datenblatt anschaue, finde ich dort
nur z.B. 'CH0RESL' und 'CH0RESH' mit um 1 verschiedenen Adressen. Also
ganz naiv hätte ich gesagt, das läuft wie bei den ATmega.
S. Landolt schrieb: > Und welche Adresse sollte dieses haben? Wenn ich mir, als alt gewordener > ATmega-Programmierer, ein ATxmega-Datenblatt anschaue, finde ich dort > nur z.B. 'CH0RESL' und 'CH0RESH' mit um 1 verschiedenen Adressen. Also > ganz naiv hätte ich gesagt, das läuft wie bei den ATmega. Und ganz genau so ist das auch.
Okay, merkwürdig - bei dem 'def.inc'-File, dass ich mir eben mal heruntergeladen habe, steht wirklich nur .equ ADCA_CH0RES = 528 // Channel 0 Result nichts mit RESL bzw. RESH. Keine Ahnung, was der Grund hierfür ist. Bei der megaAVR-0-series (die ich etwas kenne) sieht es so aus: .equ ADC0_RES = 1552 ; ADC Accumulator Result .equ ADC0_RESL = 1552 ; ADC Accumulator Result low byte .equ ADC0_RESH = 1553 ; ADC Accumulator Result hi byte
Das mit dem Temp-Register ist eine Hardware, die für 16Bit-Register einen atomaren Zugriff ermöglicht. Das ist besonders bei laufenden Timern entscheident. Der richtige Zugriff ist aber NICHT auf das Temp-Register, sondern zuerst auf LB (latched HB) und dann auf HB! Aber der Xmega hat doch auch 16Bit-Ladebefehle(?). Evtl. einfach die benutzen. Ich kenne mich aber in Assembler nicht so aus...
Tom schrieb: > Deshalb habe ich es nun so gelöst: > ldi r16, ADCA_CH0_RES > ldi r17, ADCA_TEMP > Das funktioniert auch Schwer vorstellbar. LDI heißt "load immediate", also "lade direkt". Und zwar eine Konstante, die du im Header mit der EQU Direktive den Labels ADCA_CH0_RES und ADCA_TEMP zugewiesen haben müßtest. Du liest also nicht den ADC aus, sondern füllst die Register mit immer denselben Festwerten. Wie es richtig geht, wurde schon geschrieben.
:
Bearbeitet durch User
Das hatten wir doch bereits geklärt: Tom hat sich schlicht verschrieben, er meinte lds. Die Frage ist eine andere: weshalb steht im 'def.inc'-File keine Definition für _RESH und _RESL.
S. Landolt schrieb: > Das hatten wir doch bereits geklärt: Tom hat sich schlicht verschrieben, > er meinte lds. > Die Frage ist eine andere: weshalb steht im 'def.inc'-File keine > Definition für _RESH und _RESL. Genau, so ist es. Die 2 Zeilen habe ich mal schnell zusammengetippt nur um zu zeigen, das es beim ATmega immer 2 Register eines LOW das andere HIGH gegeben hat. Habe leider nicht auf IN und LDS dabei geachtet. Vergebt mir bitte. :-) S. Landolt schrieb: > Okay, merkwürdig - bei dem 'def.inc'-File, dass ich mir eben mal > heruntergeladen habe, steht wirklich nur > > .equ ADCA_CH0RES = 528 // Channel 0 Result UND genau deshalb hatte ich hier auch nachgefragt, ob mein Handling dann das richtige ist. Weil ich das eben von den ATmegas so nicht kenne und Atxmega ist ja nun erst einmal neu für mich. Alexxx schrieb: > Der richtige Zugriff ist aber NICHT auf das Temp-Register, > sondern zuerst auf LB (latched HB) und dann auf HB! Auch deshalb habe ich hier nachgefragt, weil mir das mit dem TEMP-Register auch etwas merkwürdig vorgekommen ist. Auch das man immer das LOW Register als erstes und das HIGH Register als zweites lesen muss habe ich schon im Datenblatt gelesen. Aber hat jemand vielleicht bitte eine Idee, wie ich denn nun das 16Bit Register "ADCA_CH0_RES" ganz professionell unter Assembler auslese? Danke Wäre sehr dankbar, wenn man bitte 2 Zeilen mal hier eintippen könnte.
Tom schrieb: > Genau, so ist es. Die 2 Zeilen habe ich mal schnell zusammengetippt nur > um zu zeigen, das es beim ATmega immer 2 Register eines LOW das andere > HIGH gegeben hat. Habe leider nicht auf IN und LDS dabei geachtet. Nun, oben liest sich das so, als ob es tatsächlich funktioniert hätte: Tom schrieb: > Deshalb habe ich es nun so gelöst: > ldi r16, ADCA_CH0_RES > ldi r17, ADCA_TEMP > Das funktioniert auch So kann es jedoch unmöglich funktionieren. > Vergebt mir bitte. :-) Wenn es deinen Seelenfrieden rettet, bitteschön. Um auch zukünftig Absolution zu erhalten, solltest du nicht mit Salamitaktik arbeiten, sondern den gesamten Code posten. Und dazu schreiben, um welchen ATxmega es eigentlich geht, da gibt es nicht nur einen.
> Aber hat jemand vielleicht bitte eine Idee ...
Tja, solange sich hier kein ATxmega-Spezialist einschaltet, versuche ich
es mal (aber es gibt hoffentlich bessere Möglichkeiten):
1 | lds tmp0,ADCA_CH0_RES+0 ; low-byte |
2 | lds tmp0,ADCA_CH0_RES+1 ; high-byte |
3 | |
4 | ; oder das 'def.inc'-File ergaenzen, dort steht ja z.B.: |
5 | ; .equ ADCA_CH0_RES = 548 // Channel Result; |
6 | |
7 | ; also: |
8 | |
9 | .equ ADCA_CH0_RESL = ADCA_CH0_RES+0 |
10 | .equ ADCA_CH0_RESH = ADCA_CH0_RES+1 |
11 | |
12 | lds tmp0,ADCA_CH0_RESL |
13 | lds tmp1,ADCA_CH0_RESH |
Oder eben versuchen, ein "ordentliches" 'def.inc'-File irgendwoher zu bekommen.
Oder so etwas, ist vielleicht einfacher&flexibler:
1 | .macro getw ; high,low,source |
2 | lds @1,@2+0 |
3 | lds @0,@2+1 |
4 | .endmacro |
5 | |
6 | getw tmpH,tmpL,ADCA_CH0_RES |
Icke ®. schrieb: > Nun, oben liest sich das so, als ob es tatsächlich funktioniert hätte Es funktioniert ja auch, aber halt mit LDS. Ich habe halt nicht den originalen Code mit copy & past gemacht sondern nur schnell so eingetippt... War auch gestern schon sehr geschafft und müde nach stundenlangen studieren des Datenblattes. Es handelt sich übrigens um den ATxmega256A3AU. Wenn jetzt einer sagt, den gibt es doch schon lange nicht mehr. Kann sein, habe das Teil auch schon ein paar Jährchen hier rum liegen. Es gab bis jetzt noch keine Anwendung die einen ATxmega benötigt hätte. Habe bis jetzt alles mit ATmega gemacht. Aber irgendwann kommt halt die Zeit... Habe auch hier im Forum schon die Info zum ADC gelesen, das bei den "alten" Dingern das erste ADC Ergebnis nach Reset oder Power on nicht stimmt. Konnte ich auch bereits nachvollziehen. S. Landolt schrieb: > Tja, solange sich hier kein ATxmega-Spezialist einschaltet, versuche ich > es mal Danke, für das Code Beispiel. Werde es auf jeden Fall mal ausprobieren. Habe aber gerade eben folgendes aus dem Datenblatt "A" gelesen: For a read operation, the low byte of the 16-bit register must be read before the high byte. When the low byte register is read by the CPU, the high byte of the 16-bit register is copied into the temporary register in the same clock cycle as the low byte is read. When the high byte is read, it is then read from the temporary register. Also sieht es doch so aus, als müsse man das ADC_TEMP Register für das HIGH Byte lesen und die Art und Weise wie ich es gemacht habe wäre dann ja richtig. Alexxx schrieb: > Das mit dem Temp-Register ist eine Hardware, die für 16Bit-Register > einen atomaren Zugriff ermöglicht. Somit hatte Alexxx auch mit dem "Atomaren Zugriff" genau das richtige angesprochen. Nur was dieser Atomare Zugriff überhaupt ist, hatte ich bis jetzt nicht gewusst. Hatte damit noch niemals etwas zu tun... Also so wie es aussieht muss man dann wohl über das TEMP-Register gehen, um ein 16-Bit Register (wo nur ein Register im def.inc File steht) einzuladen. Danke an alle, die dabei mitgeholfen haben.
nur noch mal zum Codebeispiel von S. Landolt. Habe es gerade mal ausprobiert und es funktioniert auch! Ich denke mir aber, das man das zwischenspeichern des HIGH Bytes in dem ADC_TEMP Register deshalb macht, damit nichts anderes (weiss der Teufel was...) das HIGH Byte Register ADCA_CH0_RESH während des lesen des LOW Registers verändert. Eventuell bekommt ein Resultatregister bereits mit dem nächsten oder übernächsten Takt schon eine neue AD-Konversion eingeschrieben bevor das HIGH Byte der vorherigen Konversion ausgelesen wurde. Änderst kann ich mir die Sache mit dem TEMP Register nicht erklären. Aber vielen Dank nochmal an alle, die sich beteiligt haben.
Tom schrieb: > Also so wie es aussieht muss man dann wohl über das TEMP-Register gehen, > um ein 16-Bit Register (wo nur ein Register im def.inc File steht) > einzuladen. Nein. Dieses Register wird nur controllerintern benutzt, um das Highbyte zwischenzuspeichern. Den Grund hast du schon richtig erkannt. Ausgelesen wird der ADC über die beiden Register CHnRESL und CHnRESH (n steht für die Kanalnummer). DU mußt nur darauf achten, zuerst das Lowbyte auszulesen (CHnRESL) und danach das Highbyte (CHnRESH). Siehe auch Seite 357 des PDFs: http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-8331-8-and-16-bit-AVR-Microcontroller-XMEGA-AU_Manual.pdf Beispiel für Kanal 0: lds tmp_lowbyte,CH0RESL lds tmp_highbyte,CH0RESH
>> TEMP-Register > Dieses Register wird nur controllerintern benutzt So sehe ich das auch. Bleibt aber die Frage, weshalb es eine (extern zugängliche) Adresse bekommen hat und diese auch noch explizit im 'def.inc'-File steht.
Icke ®. schrieb: > Beispiel für Kanal 0: > > lds tmp_lowbyte,CH0RESL > lds tmp_highbyte,CH0RESH Danke für deine zusätzliche Info. Also die Register ADCA_CH0RESL oder ADCA_CH0RESH sind im def.inc File nicht vorhanden. Kann diese aber wie S. Landolt beschrieben hat anlegen. Habe jetzt diese 2 Zeilen im Programmcode eingegeben. Es funzt! lds temp,ADCA_CH0RES lds temp2,ADCA_CH0RES + 1 Dann verstehe ich auch jetzt was mit dem Satz aus dem Datenblatt "When the high byte is read, it is then read from the temporary register." gemeint ist. Es soll nicht bedeuten, das man das HIGH Byte aus dem temp-Register holen muss, sondern das bei dem Lesen des HIGH Byte (ADCA_CH0RES + 1) der Wert aus dem temp-Register kommt... Dann ist das Ganze Problem mit meiner Frage nur aufgetreten, weil in dem def.inc File des ATxmega256A3AU keine Registernamen für LOW und HIGH-Byte existieren, sondern nur ein Registername ADCA_CH0RES. Wenn ich da die Namen des LOW und HIGH Registers gefunden hätte, so wie diese auch im Datenblatt stehen, wäre alles klar gewesen. Aber Dank eurer Hilfe ist das jetzt alles ganz klar. Es gibt ja wahrscheinlich auch noch andere 16-Bit Register die ähnlich zu bedienen sind. Da werde ich in den nächsten Tagen bei meinem ATxmega kennenlern-Tests bestimmt noch drauf stoßen. Danke für all eure Info.
S. Landolt schrieb: > Bleibt aber die Frage, weshalb es eine (extern > zugängliche) Adresse bekommen hat und diese auch noch explizit im > 'def.inc'-File steht. Ich denke zum simpleren Debugen. Auch die 0/1-Series haben das TMP Register. Und es wurde zwischendurch mal die Reihenfolge der L/H Zugriffe re. Lesen/Schreiben veraendert. leo
Tom schrieb: > Also die Register ADCA_CH0RESL oder ADCA_CH0RESH sind im def.inc File > nicht vorhanden. Ja, das ist doof. Tom schrieb: > Es gibt ja wahrscheinlich auch noch andere 16-Bit Register die ähnlich zu > bedienen sind. Richtig, da muß man stets aufpassen. Beliebte Stolperfalle ist auch das Mapping der Register (I/O bzw. Memory), das nicht immer logisch konsistent ist. So sind bspw. beim ATmega1284 die OCR-Register der Timerkanäle 1-3 memory mapped, die des Timerkanals 0 dagegen I/O mapped. Ein Blick ins *def.inc lohnt immer.
Icke ®. schrieb: > So sind bspw. beim ATmega1284 die OCR-Register der > Timerkanäle 1-3 memory mapped, die des Timerkanals 0 dagegen I/O mapped. OCR0A ist auch I/O mapped. OCR1.. offsets sind jenseitig der direkt mittels I/O-Befehlen erreichbaren. s. Handbuch 9.5 usw "The device is a complex microcontroller with more peripheral units than can be supportedwithin the 64 location reserved in Opcode for the IN and OUT instructions." leo
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.