Hallo zusammen!
Ich versuche via SPI die Sensorwerte des LTC2498 abzufragen.
Der Beispielcode im Datenblatt des Atmega128rfa1 zeigt zwar die
notwendigen Einstellungen im Controlregister zum Betrieb als Master und
eine Transmit-Funktion, aber bei mir bleiben noch ein paar Fragen offen:
- das Beispiel enthält die Transmit-Funktion für ein char. Der ltc2498
benötigt als Daten-Input allerdings 13Bit - Kann ich diese übermitteln
bzw. wie?
- wie kann ich das 32-Bit lange word vom Sensor (MISO des Masters)
einlesen? Über das SPDR-Register? Da stehe ich allerdings wieder vor dem
Problem mit den 8-Bit-Begrenzung...
- Wie müsste der generelle Ablauf in der Schleife des main-Programms des
Masters sein?:
1. SlaveSelect des Slaves (ltc2498) auf low
2. MOSI des Masters schreiben (SDI des Slaves)
3. MISO des Masters lesen (SDO des Slaves)
4. SlaveSelect des Slaves auf high
Ist dies so richtig? bzw. wo bräuchte ich noch eventuelle Wartezeiten
etc.?
Hat zufällig jemand ein c-Beispiel, wie man wia einem ATmega und SPI die
Sensordaten des ltc2498 auslesen kann?
Danke Euch schon mal!
Ich bin inzwischen einen Schritt weiter und denke, dass ich prinzipiell
verstanden habe, wie's laufen muss.
Die Werte, die ich erhalte ergeben jedoch keinen Sinn (zB wenn ich den
Temperatursensor auf dem Chip auslesen will, steigen die Werte stetig
an) und ich finde das Problem nicht.
Mein Code ist eigentlich recht simple (uart-init etc. habe ich jetzt
hier mal weggelassen, da das problemlos funktioniert):
1
void SPI_MasterInit(void)
2
{
3
//Outputs: MOSI, SCK, SS
4
DDRB = (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_SS);
5
6
//Enable SPI, Master-Mode, set clock rate fck/16
7
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
8
}
9
10
11
int SPI_MasterTransmit(char MOSI)
12
{
13
//start Transmission
14
SPDR = MOSI;
15
16
//white for transmission complete
17
while(!(SPSR & (1<<SPIF)));
18
19
//returned data from slave to master
20
return SPDR;
21
}
22
23
24
int main()
25
{
26
27
char str[20];
28
29
// Thermoelement an CH0 und CH1
30
char masterOut1 = 0b10100000;
31
//char masterOut2 = 0b10000000;
32
33
// interne Temperaturmessung:
34
char masterOut2 = 0b11000000;
35
36
char result;
37
uint32_t masterIn = 0;
38
uint32_t Temp = 0;
39
40
uart_init();
41
42
SPI_MasterInit();
43
44
45
for(;;)
46
{
47
48
_delay_ms(500);
49
50
//CS des Thermochips auf low
51
PORTB &= !(1<<DD_SS);
52
53
54
//Byte1
55
result = SPI_MasterTransmit(masterOut1);
56
masterIn = (result & 0b00011111); //die ersten drei Bit löschen
57
58
//Byte2
59
result = SPI_MasterTransmit(masterOut2);
60
masterIn = (masterIn<<8) + result;
61
62
//Byte3
63
result = SPI_MasterTransmit(0);
64
masterIn = (masterIn<<8) + result;
65
66
//Byte4
67
result = SPI_MasterTransmit(0);
68
masterIn = (masterIn<<8) + result;
69
70
71
//CS des Thermochips auf high
72
PORTB |= (1<<DD_SS);
73
74
75
masterIn = (masterIn>>5); //die letzten 5 Bit löschen
76
77
sendestring(" masterIn: ");
78
sprintf(str, "%ld", masterIn);
79
sendestring(str);
80
81
//bei interner Temperaturmessung: Temperatur in °C berechnen laut
82
Datenblatt Seite21
83
Temp = (masterIn*4/1570)-273;
84
85
sendestring(" Temp: ");
86
sprintf(str, "%ld", Temp);
87
sendestring(str);
88
89
_delay_ms(2000);
90
}
91
92
93
return 0;
94
}
Sieht einer von Euch vielleicht, woran es liegen könnte?
Jeanette Seewald schrieb:> - das Beispiel enthält die Transmit-Funktion für ein char. Der ltc2498> benötigt als Daten-Input allerdings 13Bit - Kann ich diese übermitteln> bzw. wie?
Mit der Hardware-SPI kann man nur Vielfache von 8 bit übertragen.
Wenn der LTC2498 also auch mit 16 Bit klarkommt, dann geht es,
sonst müsste man auf Software-Bitbanging ausweichen. (Edit: hab'
mir das Datenblatt angeguckt, der kommt mit 4 x 8 Bit klar.)
> - wie kann ich das 32-Bit lange word vom Sensor (MISO des Masters)> einlesen? Über das SPDR-Register? Da stehe ich allerdings wieder vor dem> Problem mit den 8-Bit-Begrenzung...
SPI transportiert nur Daten gleichzeitig in beiden Richtungen.
Üblicherweise schiebt man, wenn man nur lesen will, dann auf der
Ausgabe (also über SPDR) entsprechend viele Dummybytes raus. Du
musst also jeweils:
. ein Nullbyte nach SPDR schreiben,
. warten, bis die SPI alles rausgetaktet hat (SPIF-Bit)
. ein Datenbyte von SPDR lesen,
. wieder von vorn beginnen, solange noch nicht alles da ist
Erst ganz am Ende wieder deselektieren.
So im Großen und Ganzen hast du das, glaub ich, schon aufgeschrieben.
Der einzige offensichtliche Fehler ist, dass die bitweise Negation
nicht durch „!“, sondern durch “~” erfolgt (beim Setzen des /SS-Pins).
Allerdings braucht das Teil natürlich Zeit zum Konvertieren. Beim
ersten Versuch wirst du also noch nichts zurück lesen können, sondern
erst bei den folgenden.
Vielleicht solltest du ja das /EOC-Bit auch nicht einfach nur
wegwerfen, sondern mal testen, ob da wirklich bereits das Ende einer
Konvertierung angezeigt worden ist. Ansonsten kannst du auch einfach
auf /EOC testen, indem du nur das /CS aktivierst und dann nachsiehst,
ob MISO auf low geht (ohne irgendwelche weiteren SPI-Aktionen):
Ein Tip:
Beim SPI kann man die Clock Polarity (CPOL), die Clock Phase (CPHA) und
die Data order (DORD) konfigurieren.
Wenn diese falsch sind, kann es zu seltsamen Phänomen kommen.
Ich hatte mal einen SPI-Sensor, der jeden zweiten Meßwert falsch
geschickt hat. Grund war, daß CPOL/CPHA falsch konfiguriert war, und
daher das 1.SPI-Telegram für den Sensor unvollständig war und erst mit
dem 2. SPI-Telegram die Kommunikation für ihn abgeschlossen war.
Hier hilft es sehr, SDO/SDI/SCK mit dem Oszi anzuschauen.
So ganz genau hab ich das DB zwar auch noch nicht verstanden, aber kann
es
sein, dass der Chip waehrend du das aktuelle Kommando schreibst, das
Ergebnis der vorherigen Messung ausgibt? So wuerde ich Bild 2 auf S. 14
deuten.
Am besten du rechnest erst mal nicht mit den Werten herum sondern dumpst
den Output vom SPI unveraendert (printf debugging) ... du solltest dann
die statischen Muster (feste 0/1 bits im Datenstrom) an den erwarteten
Stellen vorfinden.
Jörg Wunsch schrieb:> dass der Chip waehrend du das aktuelle Kommando schreibst, das>> Ergebnis der vorherigen Messung ausgibt
Ich versuche im Moment ja nur den Wert des internen Temperatursensors
auszulesen, welche relativ konstant sein müsste (liegt ja bei mir auf
dem Tisch). Da ich das jetzt sowieso jede Sekunde mal mache, müsste mir
das Problem des vorherigen Messwertes eigentlich im Moment egal sein,
oder nicht? Dann stimmt halt der erste Messwert nicht.
Bronco schrieb:> Beim SPI kann man die Clock Polarity (CPOL), die Clock Phase (CPHA) und> die Data order (DORD) konfigurieren.
Im Datenblatt des LTC2498 heißt es: The input data is then shifted via
SDI pin on each rising edge of SCK. The output data is shifted out the
SDO pin on each falling edge of SCK.
Müsste das bedeuten, dass ich CPOL und CPHA so einstellen muss:
CPOL=1, CPHA=0: Sample (Falling), Setup (Rising)
Oder muss ich genau gegengleich arbeiten?
A. W. schrieb:> Am besten du rechnest erst mal nicht mit den Werten herum sondern dumpst> den Output vom SPI unveraendert (printf debugging)
Das habe ich auch mal versucht (mir jedes result einzeln anschauen). Das
ganze verhält sich aber recht eigenartig. Entweder hat es extreme
Schwankungen, negative Werte, oder es bleibt komplett konstant, auch
wenn ich versuche, die Temperatur etwas zu ändern.
>Das habe ich auch mal versucht (mir jedes result einzeln anschauen). Das>ganze verhält sich aber recht eigenartig. Entweder hat es extreme>Schwankungen, negative Werte, oder es bleibt komplett konstant, auch>wenn ich versuche, die Temperatur etwas zu ändern.
Kannst du mal die Werte in hexadezimal anschauen? Da sieht man recht
schoen welches Bit wackelt. Im naechsten Schritt beim Debugging dieses
Problems kommt dann wohl der "Graf Oszillo" ins Spiel ;-).
Jeanette Seewald schrieb:> The output data is shifted out the> SDO pin on each falling edge of SCK.
Da wird der Datenpin am MISO-Pin auf den neuen Wert gesetzt, damit ist
das das Setup. Also Setup auf der falling edge.
Ob die falling edge jetzt die leading oder die trailing edge ist (ob SCK
also high oder ,ow active ist), kann man dem nicht entnehmen. Das sollte
aber auch irgendwie aus dem Datenbaltt ersichtlich sein.
Sehr vermutlich ist aber die rising edge auch die leading edge, damit
wären CPOL und CPHA beide auf 0 zu setzen.
Oliver
Jeanette Seewald schrieb:> Müsste das bedeuten, dass ich CPOL und CPHA so einstellen muss:> CPOL=1, CPHA=0: Sample (Falling), Setup (Rising)>> Oder muss ich genau gegengleich arbeiten?
Also ich hätte mal getippt: CPOL=0 und CPHA=0
Aber ob das stimmt, mußt Du ausprobieren.
Probier mal folgendes:
- Gib Dir das ganze SPI-Telegram als Hex- oder besser noch Binär-Werte
aus.
- Schaue Dir mehrere SPI-Telegramme hintereinander an und prüfe, ob es
zu "wandernden" Muster kommt.
- Probier mal die 4 möglichen CPOL/CPHA-Kombinationen durch, was sich
ändert, ob sich etwas stabilisert, usw.
Wie schon gesagt: am einfachsten siehst Du das am Oszi
PS: Zwischen SS-Aktivierung und Telegram-Beginn bzw. Telegram-Ende und
SS-Deaktivierung gibt es auch Wartezeiten, die im Datenblatt des LTC
angegeben sein sollten. Brücksichtigt?
Ich danke euch allen sehr für die Hilfe.
Leider musste ich das ganze Projekt (inkl. Hardware) heute abgeben (ich
fliege übermorgen für 6 Monate nach Singapur).
Die Werte, die ich zuletzt auslesen konnte, haben war quantitativ nicht
gepasst, aber zumindest qualitativ bei Erwärmung der Chips einen
eindeutigen Anstieg gezeigt.
Ich habe in meinem zusammenfassenden Bericht den Link zu diesem Thread
mit reingenommen - vielleicht wird sich mein Nachfolger mit weiteren
Fragen melden :)
Hallo zusammen!
Ich versuche via SPI die Sensorwerte des LTC2498 abzufragen wie meine
Vorgängerin Jeanette Seewald.
Ich wäre sehr dankbar für eure Tipps zu meiner derzeitigen
Problemstellung.
Ich denke dass, die kode am anfang das Bild 2 auf S.14(DATAsheet
LTC2498) folgt.
Ich habe versucht mit SPI (CPOL, CPHA) 4 Modus, MSB-LSB mit den DORD
ändern, die Clock-Bitrate mit SPRO Und SPR1.
Da dieser im DATAsheet LTC2498 sagt, dass der Konvertierungsprozess
endet bei Übertragung von 32-Bit oder ist unterbrochen, CS hoch und
setzen, die auf dem Datenblatt des ATmega128RFA1(seite 335) sagt:
"The system is single buffered in the transmit direction and double
buffered in the
receive direction.
This means that bytes to be transmitted cannot be written to the SPI
Data Register before the entire shift cycle is completed. When receiving
data, however,
a received character must be read from the SPI Data Register before the
next character
has been completely shifted in. Otherwise, the first byte is lost."
Ich habe versucht alles, zum beispiel:
Wie bekomme Ich nicht das erste byte ganz, das erste Byte der
Informationen zu verlieren, für die Umwandlung von der LTC Dies ist: Ich
habe 1. Byte des Getriebes in einem ersten Abstieg und Aufstieg über CS
genommen.(Dummy BYTE)
1
SPI_MasterInit();
2
3
PORTB&=~(1<<DD_SS);
4
SPI_MasterTransmit(0);
5
PORTB|=(1<<DD_SS);
6
7
for(;;)
8
{
9
10
_delay_ms(500);
11
12
//CS des Thermochips auf low
13
PORTB&=~(1<<DD_SS);
14
15
16
//Byte1
17
result=SPI_MasterTransmit(masterOut1);
18
masterIn=result;
19
20
//Byte2
21
result=SPI_MasterTransmit(masterOut2);
22
masterIn=(masterIn<<8)+result;
23
24
25
//Byte3
26
result=SPI_MasterTransmit(0);
27
masterIn=(masterIn<<8)+result;
28
29
30
//Byte4
31
result=SPI_MasterTransmit(0);
32
masterIn=(masterIn<<8)+result;
33
34
35
//CS des Thermochips auf high
36
PORTB|=(1<<DD_SS);
Jetzt 4-Byte empfange Ich ganz, aber das Ergebnis ist immer noch zu
wenig.
Ich bekomme daten mehr stabil aber DATAout Wert sollte etwa 80. 000,
aber ich bekomme über 1000.
Vielleicht sollte ich mehr Zeit zur Konversion geben?
Ich habe kein Oszilloskop, und ich habe keine Ideen mehr.
Danke Euch schon mal!
>Ich habe kein Oszilloskop,
Sag jetzt nicht, dass an der TU-Muenchen kein Oszi aufzutreiben ist und
sich das Forum deswegen den Gehirnfasching geben muss, den Code durch
angucken zu debuggen.
Was soll der 1 Byte 0-Befehl am Anfang machen? Der LTC braucht immer 32
bit?
Was steht in Masterout1/2? Ist das IM bit gesetzt?
Vielleicht, aber im Moment kann ich nicht. Glauben Sie, dass nur mit der
Oscilocopio ich wüsste wo das Problem liegt?
A. W. schrieb:> Was soll der 1 Byte 0-Befehl am Anfang machen?
Jetzt denke Ich war totaler Unfug meinerseits,
Ich dachte, dass da die SPI Verbindung verlieren das erste Byte macht,
könnte ein leeres Byte senden und dann in der zweiten Abfahrt des CS
würde das LTC eine neue datainput/dataoutput starten.
>Der LTC braucht immer 32 bit?
Das glaube ich, datasheetLTC2498(seite 16):
The LTC2498 serial output stream is 32 bits long.
> Was steht in Masterout1/2?
Entschuldigung! Jetzt zeige Ich Sie,
// Thermoelement an CH0 und CH1
char masterOut1 = 0b10100000;
//Interne Temperaturmessung:
char masterOut2 = 0b11000000;
Wie am anfang.
>Ist das IM bit gesetzt?
IM Bit ist aktiviert. Ich versuche im Moment ja nur den Wert des
internen Temperatursensors
auszulesen.
Ich zeige jede SPI-Telegramme hintereinander an und prüfe, ob es
zu "wandernden" Muster kommt. Das erste Byte kommt 11111, nicht 8 bit,
das verstehe Ich nicht.
Villeicht bekomme ich nicht gut die Daten aus LTC2498 mit Master(MOSI)
konfiguration?
Ich zeige das Kode und die Ergebnises aus Hterm:
Ich habe alle Dutzende Male geprüft und Ich habe Dutzende von Combos
versucht. Ich verstehe nicht, warum die Daten bekomme ich nicht logisch
sind.
Hat jemand eine ähnliche Erfahrung gehabt?
Danke Euch schon mal!
int ... char ...
Was ist ein "char"? Ein Zeichen in der Ein- oder Ausgabe.
Wenn man eine kleine Ganzzahl haben möchte (small integer), dann bitte
int8_t benutzen, wenn es vorzeichenbehaftet sein soll, und uint8_t,
wenn es kein Vorzeichen haben soll.
Dein "int" bei SPI_MasterTransmit() in Verbindung mit der Addition
für masterIn versaut dir hier das Ergebnis.
Deklariere SPI_MasterTransmit() mit einem Rückkehrtyp von "uint8_t",
gleichfalls alle Variablen, die bislang als "char" deklariert sind.
Normalerweise würde man auch schreiben:
Jörg Wunsch schrieb:> Dein "int" bei SPI_MasterTransmit() in Verbindung mit der Addition> für masterIn versaut dir hier das Ergebnis.> Deklariere SPI_MasterTransmit() mit einem Rückkehrtyp von "uint8_t",> gleichfalls alle Variablen, die bislang als "char" deklariert sind.
Ich habe gerade es geändert.
> masterIn = (masterIn<<8) | result;
Ich habe es geändert.
1
uint8_tSPI_MasterTransmit(uint8_tMOSI)
2
{
3
//start Transmission
4
SPDR=MOSI;
5
6
//white for transmission complete
7
while(!(SPSR&(1<<SPIF)));
8
9
//returned data from slave to master
10
returnSPDR;
11
}
12
13
14
15
16
intmain()
17
{
18
19
charstr[20];
20
21
// Thermoelement an CH0 und CH1
22
uint8_tmasterOut1=0b10100000;
23
//char masterOut2 = 0b10000000;
24
25
// interne Temperaturmessung:
26
uint8_tmasterOut2=0b11000000;
27
28
int8_tresult1;
29
int8_tresult2;
30
int8_tresult3;
31
int8_tresult4;
32
uint32_tmasterIn=0;
33
uint32_tTemp=0;
34
35
uart_init();
36
37
SPI_MasterInit();
38
39
40
for(;;)
41
{
42
43
_delay_ms(500);
44
45
//CS des Thermochips auf low
46
PORTB&=~(1<<DD_SS);
47
48
49
//Byte1
50
result1=SPI_MasterTransmit(masterOut1);
51
52
//für Debugging
53
sendestring(" result1: ");
54
itoa(result1,str,2);//binär darstellen
55
sendestring(str);
56
57
//Byte2
58
result2=SPI_MasterTransmit(masterOut2);
59
60
masterIn=(result1<<8)|result2;
61
62
63
//für Debugging
64
sendestring(" result2: ");
65
itoa(result2,str,2);//binär darstellen
66
sendestring(str);
67
68
//Byte3
69
result3=SPI_MasterTransmit(0);
70
71
masterIn=(masterIn<<8)|result3;
72
73
//für Debugging
74
sendestring(" result3: ");
75
itoa(result3,str,2);//binär darstellen
76
sendestring(str);
77
78
//Byte4
79
result4=SPI_MasterTransmit(0);
80
81
masterIn=(masterIn<<8)|result4;
82
83
//für Debugging
84
sendestring(" result4: ");
85
itoa(result4,str,2);//binär darstellen
86
sendestring(str);
87
88
89
PORTB|=(1<<DD_SS);//CS des Thermochips auf high
Ich habe versucht wieder 4 SPI modes mit die neue Konfigurationen aber
es funktionert nicht.
result1: 11 result2: 1111111111111111 result3: 1111111111111111 result4:
1111111111111111 resultmasterIn: 1111111111111111 masterIn: -1
Temp:2735374
SPI ist Duplexkommunikation und Ich sende und bekomme zur gleichen Zeit
bei "result" variable.
Villeicht mein inputData (MasterOut1, MasterOut 2) wird von LTC2498
nicht gut gelesen? Ich lese aus LTC2498Datasheet:
"A new configuration can be loaded into the device by
setting EN2 = 1"
So Ich glaube alles gut konfiguriert ist.
Hector Cuenca schrieb:> masterIn: -1
Beschaff' dir bitte das Oszilloskop.
Das sieht ja verdammt danach aus, als würde der LTC2498 einfach gar
nicht reagieren.
Überprüfe auch nochmal die Verdrahtung, ob da alles in Ordnung ist.
Hallo Zussamen,
Ich habe auch dem gleichen Problem. Ich werde endlich mit dem
Oszilloskop-Signal überprüfen. Ich will wissen vor der Prüfung des
Oszilloskops, wenn das Signal wie das Bild sein soll
Konnte Sie mir sagen, ob das Signal bekomme ich dem in Anlage ähneln
soll?
Weiß ich, dass es hängt die SPI-Verbindung konfigurieren, muss jedoch
wie in der Abbildung?
Danke Euch schon mal!