Forum: Mikrocontroller und Digitale Elektronik Probleme mit DAC und SPI


von Stefan G. (Gast)


Lesenswert?

Hallo,
ich möchte einen DAC (12 bit DAC7611 von Texas) an meinen ATmega323
anschliessen. Verkabelt habe ich eigentlich schon alles, nur komme ich
nun nicht damit klar, wie ich das Teil ansteuern soll. Ich benutze
Codevision, dort gibt es so einen Wizard, wo man schon gleich SPI
auswählen kann. Nur bin ich mir mittlerweile garnicht mehr sicher, ob
der DAC tatsächlich SPI benötigt. In der Doku steht zwar "3-wire
interface", und ich hatte mir ihn auch bei Texas also SPI kompatiblen
ausgewählt, jedoch steht im Datenblatt meines uC´s, daß für SPI 4
Leitungen vorgesehen sind: MISO, MOSI, SCK und SS. Im Datenblatt des
DAC´s steht, daß nur 3 Leitungen mit dem uC verbunden werden müssen:
Serial Clock, Serial Data und Load Strobe. Meint ihr daß das so
kompatibel ist?

Ein weiteres Problem ist, daß über Serial Data (SDI) ein 12 bit Wort
übertragen werden muß. Nun weiß ich auch nicht ob das überhaupt mit
meinem uC bzw. mit Codevision kompatibel ist, da die glaube ich immer
von Byte-langen Wörtern (also 8 oder 16 bit) ausgehen.

Wie man wahrscheinlich merkt, ist es das erste mal, daß ich was mit SPI
mache, dementsprechend verwirrt bin ich...

Vielleicht hat trotzdem jemand einen Tipp.
Gruß,
Stefan

von Frank Linde (Gast)


Lesenswert?

Hallo Stefan,

nach meinem naiven Verständnis der Datenblätter (bin kein SPI-Experte)
verbindest Du SCK mit CLK, MOSI mit SDI und SS mit CS. Den LD-Impuls
mußt Du Dir mit einem separaten PIN am AVR generieren. Die MISO-Leitung
entfällt, weil vom DAC keine Daten zurückkommen. Von Codevision habe
ich keine Ahnung.

Aber wie gesagt, habe selbst noch nichts mit SPI gemacht. Warte besser
noch auf fundierte Meinungen. Oder benutze die Forum-Suchfunktion, SPI
dürfte schon häufiger Thema gewesen sein.

Gruß, Frank

von Stefan G. (Gast)


Lesenswert?

Hallo Frank, danke erstmal für Deine Antwort. Ich habe immer noch meine
Probleme mit dem Verständnis von SPI. Wie funktioniert das genau. Hat
da vielleicht irgend jemand einen brauchbaren Link? Ansonsten probiere
ich mich nochmal anhand der Datenblätter schlau zu machen, das hatte
jedoch bisher nicht soo viel gebracht.
Bis dann,
Stefan

von ERDI - Soft (Gast)


Lesenswert?

Ist eigentlich nicht so schwer. Du benötigst lediglich MoSi
(MasterOutSlaveIn), welches du mit SDI (oder Serial Data oder wie auch
immer) des DAC's verbindest. Dann hängst du noch den SCK an den
Clock-Eingang des DAC's. (So, wie es Frank schon gesagt hat.)
Den SS brauchst du nicht, stattdessen nimmst du irgend nen anderen Pin
des Controllers.
Somit ist dein Interface fertig.
Für die anderen beiden Pins des DAC (/LD und /CLR) nimmst du wieder 2
andere Pins oder legst sie auf nen definierten Pegel.
/CLR auf Low und dein DAC gibt ne Spannung von 0V aus.
/CLR auf High gibt die Spannung, die digital im Latch steht, aus.
/LD auf Low gibt alle Spannungsdaten sofort an die DAC-Switches.
/LD auf High speichert die Daten zwischen, bis /LD auf Low geht.
D.h. im prinzip kannst du /CLR immer auf High lassen, und /LD immer auf
Low. (Wobei ich letzteres nicht empfehlen würde, da sonst deine
Spannung am Ausgang erst mal in der Gegend rumhüpft, bis die kompletten
Daten geschrieben worden sind.)

Steht aber alles im Datenblatt drin, auch wie die Daten auszusehen
haben, die der DAC erwartet.

Sollten meine Überlegungen irgend welche Fehler beinhalten, bitte ich
diese zu entschuldigen. Hab das nur mal schnell hingeschrieben.

Gruß, ERDI - Soft.

von Stefan G. (Gast)


Lesenswert?

Hallo ERDI,
was SPI angeht hast du mir auf jedem Fall schonmal sehr gut
weitergeholfen. Ist eigentlich ziemlich klar.
Das einzige Problem was ich nun noch habe, ist folgendes: im Datenblatt
http://focus.ti.com/lit/ds/symlink/dac7611.pdf steht, daß das input
Format "straight binary und MSB first" ist. Der DAC erwartet offenbar
ein 12 bit langes Wort, von dem ich nicht weiß wie ich es
"generieren" soll. Wenn ich alles richtig verstanden habe, werden die
Daten die per SPI verschickt werden sollen ins SPI Data Register meines
uC geschrieben. Dies ist jedoch nur 8 bit lang, und somit habe ich da
ein Problem wo und wann die restlichen 4 bit´s geschrieben werden.
Hat jemand von Euch eine Ahnung?
Gruß,
Stefan

ps: Und was genau ist ein "Latch"?

von ERDI - Soft (Gast)


Lesenswert?

Ist doch eigentlich relativ einfach. Du hast 3 Nibbles (4bit), die der
DAC erwartet, kannst aber mit Hardware-SPI immer nur 8bit verschicken,
wobei man, soweit ich weiß, das Startbit angeben kann. (Also MSB oder
LSB zuerst).
Du nimmst also dein zweites Byte und schickst es mit dem MSB (most
signigicant bit) zuerst an den DAC, dann das erste Byte auf die gleiche
Art. Dabei gehen die 4 höchstwertigen bits von Byte zwei (das, welches
zuerst geschrieben wurde) verloren, werden ins Nirvana geschoben.

[          Byte 2          ] [          Byte 1          ]
[D8 D7 D6 D5 D4 D3 D2 D1 D0] [D8 D7 D6 D5 D4 D3 D2 D1 D0]
 ++ ++ ++ ++

Byte zwei zuerst mit D8 in den DAC schieben, sobald Byte 1
reingeschoben wird, sind die mit den ++ gestorben.

Wenn du jetzt nen Pegelwechsel an /LD iniziierst (von High auf Low),
werden die Daten vom Latch (Zwischenspeicher) an die DAC-Switches
transferiert und dein eingestellter Wert erscheint am Ausgang.

Alles klar?

von BernhardT (Gast)


Lesenswert?

Hallo Stefan,
da das Teil bis 20 MHz  Daten einlesen kann werden kann würde auch eine
Softwareroutine sehr schnell abgearbeitet. Das ist ein reines 12 bit
Schieberegister.  Unsigned Word laden, /LD Pin low. Schleife (12*) Wenn
Word and h'0800' > 0: Portpin setzen sonst löschen. Word links
schieben, clock setzen, clock löschen, ende Schleife.  /LD Pin high -
fertig .
Wenn du während die Daten reingeschoben werden, lieber 0V am Ausgang
haben willst, statt Zufallswerte musst du  /CLR  mitverwenden.
Gruß Bernhard

von ERDI - Soft (Gast)


Lesenswert?

@BernhardT:

Ne, erst /LD high, sonst werden die Daten im DAC gleich als Spannung
umgesetzt. Erst wenn alle 12bit geschrieben sind, /LD kurz auf Low, um
die Daten vom Latch in den DAC-Switch zu übernehmen, dann wieder auf
High.
Bei deiner Methode springt der Ausgang unkontrolliert zwischen 0 und
4.096 Volt rum.

Den /CLR braucht man eigentlich nur, wenn man mal ganz schnell auf 0V
muß.

Es sei denn, du hast /LD und /CS verwechselt. Dann paßts. :-)

von Stefan G. (Gast)


Lesenswert?

Hallo ERDI und BernhardT, vielen Dank für Eure Tipps, ich werde gleich
mal probieren sie in die Tat umzusetzen.
Bis später,
Stefan

von Stefan G. (Gast)


Lesenswert?

Hallo,
ich habe nun meinen DAC komplett an den uC angeschlossen. Das sollte
eigentlich alles stimmen. Nur tut sich am Ausgang des DAC´s irgendwie
noch nichts. Ich habe mir folgende Routine gebastelt:

void send_dac(char high, char low)
{
  char sende;
    sende = spi(high);
    sende = spi(low);
    delay_us(10);
    PORTB.3=0;             // Load Strobe Pin
    delay_us(100);
    PORTB.3=1;
}

Wenn ich dann z.B. send_dac(0x0F,0xFF) sage, so müßte der DAC
eigentlich 4 Volt (also volle Spannung) ausgeben. Ich habe jedoch
permanent 0 Volt am Ausgang. Hat jemand noch eine Idee, wo hier der
Wurm drin sein könnte?
Gruß,
Stefan

ps: Die Funktion spi() wurde mir von Codevision vorgefertigt und macht
folgendes: unsigned char spi(unsigned char data)
this function sends the byte data, simultaneously receiving a byte.
Daß kein Byte empfangen wird (vom DAC wird nichts zurückgeschickt, da
ich nur den MOSI Pin benutze) sollte doch eigentlich nicht weiter
stören.

von ERDI - Soft (Gast)


Lesenswert?

Solltest vielleicht vor dem Senden der Daten den /CS Pin noch auf Low
legen. könnte evtl. helfen. :-)

von Stefan G. (Gast)


Lesenswert?

Aber ich dachte, wenn ich nur ein Bauteil am SPI Bus hängen habe, dann
muss der /CS Pin nicht unbedingt auf Low gezogen werden. Oder sollte
man das bei nur einem Bauteil ebenfalls machen, damit man da nicht
irgendwelche undefinierten Zustände hat?
Stefan

von Stefan G. (Gast)


Lesenswert?

Ach ja, noch was: kann ich wenn ich den Pin benutze ihn permanent auf
Ground legen? Oder sollte ich das jedesmal vor der Datenübertragung mit
dem uC auf Low ziehen?
Stefan

von ERDI - Soft (Gast)


Lesenswert?

Du mußt den Pin AUF JEDEN FALL beschalten.
Des DAC weiß ja sonst nicht, dass er gemeint ist. Man könnte den Pin
theoretisch dauerhaft auf Low legen, würde ich aber nicht unbedingt
empfehlen, da sonst u.U. auch irgendwelche Störsignale den DAC-Wert
verändern könnten.

von Stefan G. (Gast)


Lesenswert?

Ich setze den /CS Pin nun ganz zu Beginn meines Programms auf low. Aber
es funzt immer noch nicht: Ich habe permanent volle Spannung am Ausgang
meines DAC´s. Irgendwas ist da noch faul. Meinst Du denn daß diese
kleine Routine in meinem Programm so funktioniert wie sie soll?
Stefan

von Uwe Seidel (Gast)


Lesenswert?

Mooooooment,

weiter oben stand:
Ich habe jedoch permanent 0 Volt am Ausgang.

Jetzt
Ich habe permanent volle Spannung am Ausgang.

Bin ich verwirrt oder Du? :-)
Das Zweite Ergebnis wäre ja zu erwarten bei gesendetem 0x0FFF.

Dann bin ich mir auch nicht ganz sicher, was in deinem SPDR steht.
Da der Datenpuffer ja beim Senden mit dem "pinzustand" von MISO
geladen wird.
Wenn das MISO-Pin high ist , dann stehen nach senden des ersten Bytes
evntl. 0xFF im SPDR. Vielleicht ist da ja was falsch gelaufen.
Würde mich interessieren , welche Funktion von Codevision sowas fertig
generiert.

Uwe (auch nur ein Anfänger auf dem Gebiet)

von Stefan G. (Gast)


Lesenswert?

Hallo Uwe,
daß ich gestern immer 0 Volt und heute 4 am Ausgang habe ist natürlich
verdächtig. Aber mit den 4 Volt hat es schon seine Richtigkeit. Was
genau in der spi Funktion passiert probiere ich gerade rauszufinden.
Ich habe bisher erst folgendes gefunden, was mir nicht viel
weiterhilft:

#ifndef SPI_INCLUDED
#define SPI_INCLUDED

unsigned char spi(unsigned char data);

#endif

Ich glaube statt MISO meinst du MOSI (also Master Out, Slave In),
oder?
Da müßte ich erstmal überprüfen ob die Sachen die im MOSI drinstehen
mit meinen vorgegebenen Daten übereinstimmen.
Stefan

von Uwe Seidel (Gast)


Lesenswert?

Hi, also ich habe das so in Erinnerung:
Wenn du ein Datenbyte ins SPDR schreibst wird ein Takt erzeugt und das
Byte seriell an MOSI ausgegeben (rechts_shift oder links.. je nachdem
ob MSBfirst oder LSBfirst), gleichzeitig wird bei jedem Takt ein Bit
von MISO in SPDR eingeschoben.
Am Ende ist dein Byte raus und dafür das , was an MISO stand während
der Takte drin im SPDR.

Wenn also deine MISO nicht belegt ist und "1" führt, dann steht nach
dem ersten gesendeten Byte 0xFF im SPDR. Jetzt muss nur noch das
einschreiben des zweiten Bytes falsch laufen...warum auch immer, und
schon steht im SPDR immer 0xFF und wird gesendet.--> Volldampf am
Ausgang des DAC.

Aber das ist nur so eine Idee.
Vielleicht ist auch das Data_IN_Pin vom DAC immer
high(schaltungstechnischer Fehler ? ) dann kommt das auf das gleiche
raus.

Bin mal gespannt woran das gelegen hat, wenn du es gefunden hast.

Ciao Uwe (immernoch Anfänger)

von Stefan G. (Gast)


Lesenswert?

Hallo Uwe,
an dem MOSI Pin meines uC´s liegen tatsächlich permanent 5 Volt. Das
kann ja irgendwie schonmal nicht stimmen. Nun weiß ich jedoch nicht
warum der permanent auf high ist, da ich nicht genau weiß was diese
verdammte von Codevision erzeugte spi() funktion genau macht.
Vielleicht sollte ich probieren die gesamt Kommunikation "manuell" zu
realisieren, und nicht mir von Codevision irgendwas vorfertigen
lassen.
Stefan

von Stefan G. (Gast)


Lesenswert?

Verdammte Axt!!!!!!!

Hier kommt die Lösung meines Problems:

Das Data Direction Register war falsch gesetzt, die Pins für Chip
Select (CS) und Load Strobe (LD) waren nicht als Ausgang gesetzt.
Ansonsten stimmte alles.
Immer wieder erstaunlich, wieviel Zeit man verwenden kann um dann
irgendwo triviale Fehler zu finden....

Nochmals danke für Eure Hilfe,
Stefan

von Uwe Seidel (Gast)


Lesenswert?

HEHE,
"verdammte Axt" rutscht mir auch ab und zu mal raus.

Gut , dass du es gefunden hast....

Ciao Uwe

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
Noch kein Account? Hier anmelden.