Hallo zusammen,
ich bin kurz vorm verzweifeln.
Kurz zu meinem vorhaben:
Ich möchte mit einem Atmega2560 digitale Werte eines externen 14bit
AD-Wandler einlesen(LTC2356-14) und diese auf einem Display an einem
Graph anzeigen lassen.
Wie SPI grob funktioniert, verstehe ich. Allerdings nicht wie ich 8bit
einlesen kann. Ich finde auch keine geeigneten Beispiele dazu im netz.
Ich probiere es bisher mit einer Library in der es die folgende funktion
gibt:
Es will einfach nicht klappen...
Vielleicht hat jemand soetwas schonmal gemacht und ein Beispiel an dem
ich mir das abschauen kann?
Danke und viele Grüße
Matthias
Matthias H. schrieb:> ich versuche es immer mitspi_transfer_sync(0xAA,Buffer[2],2]> Es will einfach nicht klappen...> Vielleicht hat jemand soetwas schonmal gemacht und ein Beispiel an dem> ich mir das abschauen kann?
Das kann nicht klappen....
Bei SPI werden immer pro Übertragung in beide Richtungen Daten
transportiert.
Sprich gleichzeitig gesendet und empfangen.
SPDR = dataout[i]; sendet deine Daten zum Chip
while((SPSR & (1<<SPIF))==0); Wartet bis die Übertragung fertig
ist
datain[i] = SPDR; liest deine Daten erhalten vom
Chip
spi_transfer_sync(0xAA,Buffer[2],2]
0xAA ist kein Zeiger auf den dataout buffer sondern NIX
Buffer[2] ist ein Zeiger mitten in einen Buffer
das was stimmen könnte ist, dass du 2 Bytes übertragen willst.
Schreib mal was du genau willst
Gruß Thomas
Schau dir mal das an. Da sind insbesondere auch die ganzen Register
beschrieben. Wenn man die einmal verstanden hat ist der Rest
einleuchtend. Das Datenblatt hilft an dieser Stelle auch. Zumindest
besser als einfach irgendeine Lib aus dem Netz zu verwenden.
http://maxembedded.com/2013/11/the-spi-of-the-avr/#Master_Init
Übernimmt der 2560 noch weitere Aufgaben? Ansonsten ist er eventuell
auch ein wenig überdimensioniert. Für "kleinere" Atmels findet man
relativ viele Beispiele zu SPI.
Thomas schrieb:> das was stimmen könnte ist, dass du 2 Bytes übertragen willst.
Ich möchte die 14bit des AD-Wandlers auslesen. Deshalb muss ich die
schleife zweimal durchlaufen.
Dem AD-Wandler brauche ich ja nichts senden, deshalb dachte ich ist es
egal was ich ihm bei DATAOUT übergebe.
Und da SPDR immer 8 Bit groß ist, muss ich das ganze in einen String
speichern...
Matthias H. schrieb:> Dem AD-Wandler brauche ich ja nichts senden, deshalb dachte ich ist es> egal was ich ihm bei DATAOUT übergebe.
Das Glaube ich nicht, dass der keine Config braucht...
Schreib mal den TYP AD Wandler. dann lese ich mal nach...
Gruß Thomas
Thomas schrieb:> Das Glaube ich nicht, dass der keine Config braucht...> Schreib mal den TYP AD Wandler. dann lese ich mal nach...
Mist habe es gerade gesehen....
hast du ja ganz oben schon geschrieben
Gruß Thomas
PS ich les mal ....
So Hab gelesen....
Der hat mit einfachen SPI nicht viel zu tun.
Schau dir mal Seite 11 von 20 an.
SCK = Low -->
Steigende Flanke von CONV -->
im CONV High erste steigende Flanke von SCK -->
bei der dritten fallenden Flanke von SCK = D13 von SDO
bei der 16'ten fallenden Flanke von SCK = D0 von SDO
SCK Takt 17 & 18 durchlaufen und gehen ins leere
(insgesamt muss SCK 18 mal Takten)
dann geht es wieder los
SCK = Low -->
Die erste Wandlung kannst du in die Tonne treten.
Also das ganze 2 x Durchlaufen. Dann ist die erste gültige Wandlung
durch
und du hast einen reellen Wert.
Das kannst du nur zu Fuss ohne SPI lösen.
Mach das Ganze mit einer Statemachine...
SCK = Low;
CONV = Low;
int State;
switch (State)
case 0:
CONV = High;
....
State +=1;
break;
case 1:
usw.....
Gruß Thomas
Thomas schrieb:> Das kannst du nur zu Fuss ohne SPI lösen.
Okay aber warum steht dann im Datenblatt auf Seite 1 3 Wire SPI
Compatible? Das war der Grund warum ich den AD-Wandler kaufte.
State Machine... so etwas habe ich noch nie gemacht. Enstpricht der
State dann quasi meiner CLK Sprich State 1=Low State 2=High State3=Low??
Ich versuche den Code mal zu schreiben und werde Fehler machen.
Vielleicht kannst du ja mal drüber schauen
Hallo Thomas,
ich hab es mal versucht, hänge hier und da und weiß vorallem nicht ob
ich auf einem grünen Zweig bin.
Probleme habe ich vorallem:
-Wie lese ich das Datenwort ein? Muss ich die Bits in einen String
speichern und wie wandle ich diese in ein int?
-Klappt das, dass ich die FUnktion readdata() aufrufe und dann den Wert
auf meinem Display anzeige und anschließen wieder die Funktion aufrufe?
Ich hänge meinen Code jetzt mal an. Wie gesagt ich weiß nicht ob das
überhaupt annähernd richtig ist. Vielleicht ist die Sache für mich als
Schüler noch ein bisschen zu kompliziert
Die erste Entscheidung ist, Hardware- oder Software-SPI.
Nehmen wir mal wegen der 18 Bits SW.
Die Idee mit der State-Machine ist eher akademischer Natur.
Außerdem würde ich -wenn überhaupt- nur 18 States verwenden.
Du musst unterscheiden, ob Du Dummy-Bits überträgst oder Nutzdaten.
Ungetesteter Code aus dem Stegreif:
1
intmain(void){
2
uint16_tmask,data;
3
DDRB|=0x03;//SCK=PB1 CONV=PB0 SDO=PB3
4
PORTB&=~(1<<PB1);//SCK=LOW
5
PORTB&=~(1<<PB0);//CONV=LOW
6
while(1){
7
PORTB|=(1<<PB0);//CONV=HIGH
8
PORTB|=(1<<PB1);//SCK=High Beginn Sample #1
9
PORTB&=~(1<<PB0);//CONV=LOW
10
PORTB&=~(1<<PB1);//SCK=LOW
11
PORTB|=(1<<PB1);//SCK=High #2
12
PORTB&=~(1<<PB1);//SCK=LOW
13
data=0;mask=0x2000;do{//14 mal (1 << 13 = 0x2000) #3..16
Also leider kam ich erst heute zum testen.
Das Programm habe ich wie von eprofi übernommen und getestet. die
einzelnen Schritte arbeitet er sauber ab. Dennoch erhalte ich immer
16383 als Data. Ich habe gelesen der AD-Wandler gibt mir Data als
Zweierkomplement aus. Sprich ich erhalte immer 0.
So wo kann jetzt der Fehler liegen?
Ist der Code doch nicht richtig?
Oder liegt der Fehler eventuell am AD-Wandler? Kann ich die richtige
funktionsweise des Wandlers denn testen?
Danke und viele Grüße
Matthias
@ Matthias H. (streno)
>Das Programm habe ich wie von eprofi übernommen und getestet. die>einzelnen Schritte arbeitet er sauber ab. Dennoch erhalte ich immer>16383 als Data.
Dann sit was faul. Auch beimbesten AD-Wandler wackeln die untersten
Bits, erst recht bei 14 Bit.
Wie sieht dein Hardwareaufbau aus? Zeig uns ein Bild davon. Und einen
Schaltplan.
>So wo kann jetzt der Fehler liegen?>Ist der Code doch nicht richtig?
Wahrscheinlich.
>Oder liegt der Fehler eventuell am AD-Wandler?
Eher nicht. Bestenfalls an der Verdrahtung zu deinem Arduino.
> Kann ich die richtige>funktionsweise des Wandlers denn testen?
Nennt sich Fehlersuche.
Beitrag "Re: Atmega2560 SPI-Verbindung zu ext. AD-Wandler"
Dein Code ist GRAUSAM! Außerdem gehören lange Quelltexte in den Anhang,
siehe Netiquette.
Der IC ist zwar nicht 100% normales SPI, aber man kann ihn mit normalem
SPI abfragen.
CONV Signal HIGH
CONV SIGNAL LOW
3x1 Byte senden/empfangen. Die Sendedaten sind beliebig, die kommen
sowieso nicht am ADC an
Aus den 3 empfangenen Bytes durch entsprechendes Bitschieben das
Ergebnis extrahieren, ggf. vorzeichenrichtig erweitern.
Ist nicht wirklich schwer, wenn gleich auch kein totales
Anfängerprojekt.
Noch ein Tip. Mehrere Daten speichert man in einem Array, nicht in einem
String. Denn ein String ist im Normalfall ein Array, das ASCII-Zeichen
(Text) enthält, aber keine Binärdaten.
Falk B. schrieb:> Dann sit was faul. Auch beimbesten AD-Wandler wackeln die untersten> Bits, erst recht bei 14 Bit.> Wie sieht dein Hardwareaufbau aus? Zeig uns ein Bild davon. Und einen> Schaltplan.
Hier ein Bild meines Aufbaus ab dem AD-Wandler. Davor ist denke ich
alles richtig, da die Spannung am AD-Wandler messbar anliegt...
Falk B. schrieb:> Eher nicht. Bestenfalls an der Verdrahtung zu deinem Arduino.
Ich programmiere den Atmega nicht als Arduino, sondern in AtmelStudio.
DIe UTFT Bibliothek habe ich mir nur umgeschrieben
@Matthias H. (streno)
>Hier ein Bild meines Aufbaus ab dem AD-Wandler.
Kaum. Das ist der Schaltplan. Mit Aufbau meine ich den realen
Hardwareaufbau. Deinen Arduino + Kabel + AD-Wandler-Board.
>Davor ist denke ich>alles richtig, da die Spannung am AD-Wandler messbar anliegt...
Denken? Du GLAUBST! Nur wenn du es gewissenhaft PRÜFST, kann es
vielleicht stimmen. Papier ist geduldig.
>Ich programmiere den Atmega nicht als Arduino, sondern in AtmelStudio.
OK.
>DIe UTFT Bibliothek habe ich mir nur umgeschrieben
Dieser komische Pegelwandler KANN im Einzelfall Probleme machen. Da muss
ich mal ins Datenblatt schauen.
// last dummy byte is for fullfilling the minimum of 17 clocks / cycle rule
17
18
SPDR=0x00;// dummy data
19
while(!(SPSR&(1<<SPIF)));// wait for transmission end
20
tmp=(int16_t)SPDR<<8;
21
22
SPDR=0x00;// dummy data
23
while(!(SPSR&(1<<SPIF)));// wait for transmission end
24
tmp|=SPDR&0xFF;
25
26
SPDR=0x00;// dummy data
27
while(!(SPSR&(1<<SPIF)));// wait for transmission end
28
SPDR;// dummy read
29
30
// sign extention
31
32
tmp&=0x3FFF;// clear MSBs
33
if(tmp&(1<<13))tmp|=0xC000;// copy bit 13 to 14 and 15
34
35
returntmp;
36
}
37
38
39
intmain(void){
40
41
// IO init
42
43
DDRB|=(1<<PB1)|(1<<PB0);// set SCK und SS to output
44
45
// SPI init
46
47
SPCR=(1<<SPE)|(1<<MSTR);
48
SPSR=(1<<SPI2X);
49
50
51
read_LT2356();
52
}
Aber der MAX3391 ist mir nicht ganz geheuer. Diese bidirektionalen
Pegelwandler ohne Richtungsumschaltung sind tückisch! Da kann viel
schief gehen, denn dort sind diverse Tricks eingebaut! Bei
unidirektionalen Signalen sollte so weit wie immer möglich immer
unidirektionale Pegelwandler nehmen!