Das DATA-Register des 10-Bit-DAC sieht "left-adjusted" aus. Aber nirgendwo im Text steht, dass der 10-Bit-Wert entsprechend angepasst werden muss. Wie ist dies zu verstehen? Als "selbstverständlich"?
So macht es halt am meisten Sinn. Wenn morgen noch ein paar Bits bei einem anderen uC dazu kommen, dann ändert sich das Alignment nicht.
Georg M. schrieb: > Aber nirgendwo im Text steht, dass der 10-Bit-Wert entsprechend > angepasst werden muss. Doch, da steht sogar explizit der Name der Bits: DACn.**DATA** > Wie ist dies zu verstehen? Als "selbstverständlich"? Ja, selbstverständlich musst du die 10 Bits Data[9:0] so verwenden, dass ein für dich taugliches Ergebnis herauskommt. Deshalb ist die Position dieser Bits im Datenblatt ausdrücklich beschrieben. Bei ganz, ganz vielen anderen Bits ist das ja auch so. Der Witz an diesem Alignment ist, dass im Highbyte "automatisch" die signifikanten 8 Bit stehen. Wenn dir also 8 Bit Auflösung ausreichen, musst du einfach nur dieses Byte verarbeiten. > dass der 10-Bit-Wert entsprechend angepasst werden muss. Wenn du es schaffst, diesen Faktor 64 in deiner Rechnung zu "verstecken", dann musst du da gar nichts extra anpassen. N. M. schrieb: > Wenn morgen noch ein paar Bits bei einem anderen uC dazu kommen, dann ... kommen die garantiert immer bei den LSB dazu.
:
Wiederhergestellt durch Moderator
Peter D. schrieb: > Welcher AVR? AVR32DA28, AVR32DA32, AVR32DA48, AVR64DA28, AVR64DA32, AVR64DA48, AVR64DA64, AVR128DA28, AVR128DA32, AVR128DA48, AVR128DA64 AVR32DB28, AVR32DB32, AVR32DB48, AVR64DB28, AVR64DB32, AVR64DB48, AVR64DB64, AVR128DB28, AVR128DB32, AVR128DB48, AVR128DB64 AVR16DD14, AVR16DD20, AVR16DD28, AVR16DD32, AVR32DD14, AVR32DD20, AVR32DD28, AVR32DD32, AVR64DD14, AVR64DD20, AVR64DD28, AVR64DD32 AVR16EA28, AVR16EA32, AVR16EA48, AVR32EA28, AVR32EA32, AVR32EA48, AVR64EA28, AVR64EA32, AVR64EA48
Beitrag #7699544 wurde vom Autor gelöscht.
Adam P. schrieb im Beitrag #7699544:
> dac_value = (DACn.DATA >> 6);
Wenn DACn ein Bitfeld ist ... dann kümmert sich der Compiler um das
Shiften, das musst Du nicht selbst machen. Sonst hätte das Bitfeld auch
irgendwie wenig Sinn.
Harald K. schrieb: > Adam P. schrieb im Beitrag #7699544: >> dac_value = (DACn.DATA >> 6); > > Wenn DACn ein Bitfeld ist ... dann kümmert sich der Compiler um das > Shiften, das musst Du nicht selbst machen. Sonst hätte das Bitfeld auch > irgendwie wenig Sinn. Ja ne, vergiss es, hatte den Beitrag gelöscht, weil ich falsch herum gedacht habe. Right Shift 6 wäre beim ADC richtig, beim DAC müsste es ja dann Left Shift sein. Aber wenn der Compiler das macht, ist ja top, kannte ich so auch noch nicht.
Harald K. schrieb: > ... dann kümmert sich der Compiler um das Shiften Wie denn? Was soll ich schreiben:
1 | DAC0.DATA = dac_value; |
oder doch
1 | DAC0.DATA = dac_value << 6; |
???
Google findet nach 1 Minute sowas: - https://github.com/microchip-pic-avr-examples/avr128da48-using-10-bit-dac/blob/master/avr128da48-using-10-bit-dac/Generating_Constant_Signal_Example/main.c
1 | static void DAC0_setVal(uint16_t value) |
2 | {
|
3 | /* Store the two LSbs in DAC0.DATAL */
|
4 | DAC0.DATAL = (value & LSB_MASK) << 6; |
5 | /* Store the eight MSbs in DAC0.DATAH */
|
6 | DAC0.DATAH = value >> 2; |
7 | }
|
Ich hätte das einfach mal so wie du probiert, den 16-Bit Wert um 6 Bits nach links geshiftet und das komplette 16 Bit Register DAC0.DATA angesprochen.
:
Bearbeitet durch Moderator
Lothar M. schrieb: > Google findet nach 1 Minute sowas: Dann ist das kein Bitfeld, sondern DATAH/DATAL sind die beiden kompletten Bytes der Register. Und dann muss natürlich geshiftet werden. Da im Datenblatt aber die zehn relevanten Bits im Register als "Data[9..0]" bezeichnet werden, war ich davon ausgegangen, daß im Code ein Bitfeld verwendet wird.
Harald K. schrieb: > daß im Code ein Bitfeld verwendet wird Ja, das wäre natürlich ziemlich ungeschickt dokumentiert, wenn ein 16-Bit Zugriff auf das Register DATA nach rechts justiert ist, Zugriffe auf die 8-Bit Register DATAH und DATAL dann aber nach links. Aber ich denke, der Faktor 64 bei der ausgegebenen Spannung macht sich ganz schnell bemerkbar. Deshalb schrieb ich dass ich es "probiert" hätte. Und möglicherweise komme ich dann genau dort raus, wie es der Code von Github auch macht. Einfach, weil das explizit und sonnenklar ist.
:
Bearbeitet durch Moderator
Lothar M. schrieb: > Google findet nach 1 Minute sowas: Ich dachte, wenn man das "Complete DataSheet" hat, dann braucht man keine Google-Funde. Deswegen war meine ursprüngliche Frage.
Georg M. schrieb: > dachte, wenn man das "Complete DataSheet" hat, dann braucht man > keine Google-Funde. Aber nachdenken und notfalls ein kleines Testprogramm schreiben ist schon erlaubt. Du bist hier 1,5 Stunden dran. In der Zeit hättest du x-Mal ein Testprogramm schreiben können. Oder geht es dir nur ums Prinzip?
Georg M. schrieb: > Ich dachte, wenn man das "Complete DataSheet" hat, dann braucht man > keine Google-Funde. Dein Glaube ehrt dich, aber was meinst du, warum es Errata auch zu Datenblättern gibt?
Lothar M. schrieb: > Georg M. schrieb: >> Ich dachte, wenn man das "Complete DataSheet" hat, dann braucht man >> keine Google-Funde. > Dein Glaube ehrt dich, aber was meinst du, warum es Errata auch zu > Datenblättern gibt? Was ich bei der Arbeit mit Atmel/Microchip Datenblättern in den ganzen letzten Jahren gelernt habe: Vertraue nicht nur auf das Datenblatt. Aber das hier ist richtig: Lothar M. schrieb: > Google findet nach 1 Minute sowas: Siehe ApplicationNote, die sind auch mal nützlich wenn das Datenblatt alleine nicht ausreicht: https://ww1.microchip.com/downloads/aemDocuments/documents/MCU08/ApplicationNotes/ApplicationNotes/Using-10Bit-DAC-for-Generating-Analog-Signals-DS90003235C.pdf Seite 7 "Starting a Conversion"
:
Bearbeitet durch User
Adam P. schrieb: > Seite 7 "Starting a Conversion" Da steht dann auch sowas Halbgares:
1 | Starting a Conversion |
2 | ... |
3 | a conversion starts as soon as the Data (DACn.DATA) register is written. |
4 | ... |
5 | DAC0.DATAL = (value & (0x03)) << 6; |
6 | DAC0.DATAH = value >> 2; |
Denn lustigerweise wird hier das Register DAC0.DATA gar nie explizit beschreiben, sondern nur DAC0.DATAL und DAC0.DATAH nacheinander. Welcher der beiden Zugriffe triggert jetzt die Ausgabe? Hoffentlich nur der auf DATAH? Oder wird die Ausgabe 2x angestoßen? Das würde ich dann aber sicherheitshalber auch mal ausprobieren. Könnte ja hässliche Effekte geben...
:
Bearbeitet durch Moderator
Georg M. schrieb: > Harald K. schrieb: >> ... dann kümmert sich der Compiler um das Shiften > > Wie denn? > Was soll ich schreiben:DAC0.DATA = dac_value; > oder dochDAC0.DATA = dac_value << 6; > > ??? Bitfelder wäre sowas:
1 | struct myDAC_s |
2 | {
|
3 | uint16_t value:10; |
4 | uint16_t :6; /* unused */ |
5 | };
|
6 | |
7 | volatile struct myDAC_s myDAC @ 0x1000; /* Adresse vom Register in HW, Compilerspezifisch */ |
8 | ...
|
9 | xy = myDAC.value; |
Da kümmert sich der Compiler um alles. In der Praxis scheitert es manchmal daran, dass die Reihenfolge der Bits per Schalter umgedreht werden kann oder dass die Register in bestimmter Art und Weise ausgelesen werden müssen.
Lothar M. schrieb: > Welcher der beiden Zugriffe triggert jetzt die Ausgabe? Hoffentlich nur > der auf DATAH? Oder wird die Ausgabe 2x angestoßen? > > Das würde ich dann aber sicherheitshalber auch mal ausprobieren. Könnte > ja hässliche Effekte geben... Seite 6 "The output will be updated after DACn.DATAH is written"
Adam P. schrieb: > "The output will be updated after DACn.DATAH is written" Blöd, genau andersrum wie bei den 16-Bit-Timern. Da hätten sich die Spezialisten bei der Entwicklung doch mal über die Reihenfolge austauschen sollen.
Adam P. schrieb: > "The output will be updated after DACn.DATAH is written" Das ist sinnvoll, wenn man nur einen 8Bit-DAC benötigt. Das DATAL kann dann im Resetzustand verbleiben.
Peter D. schrieb: > Das ist sinnvoll, wenn man nur einen 8Bit-DAC benötigt. > Das DATAL kann dann im Resetzustand verbleiben. Du meinst wenn man nur 8Bit Auflösung haben möchte und dafür die größere Abstufung in kauf nimmt? Klingt logisch, aber warum sollte man sowas machen wollen?
Adam P. schrieb: > Klingt logisch, aber warum sollte man sowas machen wollen? Möglicherweise falls man das Ding per DMA** betanken möchte. (Halbe RAM-Puffergröße) **Unter der Annahme das die Dinger DMA können.
Adam P. schrieb: > Klingt logisch, aber warum sollte man sowas machen wollen? Manchmal weil es kompatibel ist mit alter HW (die nur 8 Bit hatte), bzw. mit neuer, die 12 oder 14 hat. Immer, wenn die untersten 3(!) Bit nicht signifikant sind oder anderweitig gebraucht werden.
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.