Jetzt ist meine Frage was sind Commando Byte, Register und solange
Messung für Register?
Ich hab mal was von SPSR und SPDR gelesen, doch mehr dazu nicht
gefunden.
Meine Frage:
Ist mein ansatzt richtig?
Gibts irgendwo eine Übersicht wie die Register heissen?
Ich arbeite das erste mal mit SPI.
Gruss
Rebi schrieb:> Gibts irgendwo eine Übersicht wie die Register heissen?
Wie immer?
Im Datenblatt?
Dort finden sich sogar Routinen, wie man SPI benutzt.
> Ich arbeite das erste mal mit SPI.
Das ist kein Argument, nicht ins Datenblatt zu sehen. Irgendwann ist
immer das erste mal. Und dann ist das entsprechende Kapitel im
Datenblatt die erste Anlaufstelle.
Rebi schrieb:> Karl Heinz schrieb:>> Von welchem µC reden wir eigentlich?>> ATMEGA 32>> ADC war das einzige was ich im Datenblat gefunden habe.
Da gibt es ein schönes Kapitel über SPI.
Vielleicht mal im PDF-Reader das Inhaltsverzeichnis einschalten?
Hinweis: Für deinen µC ist es erst mal unerheblich, ob am SPI Anschluss
ein ADC hängt oder ein Schieberegister oder ein Temperatursensor. Du
konfigurierst das SPI und nicht den Sensor. Das kommt später (falls
überhaupt notwendig).
Du musst zwischen dem Transportmedium und dem was über dieses
Transportmedium abgewickelt wird unterscheiden. Wenn du ein FAX
übertragen willst, dann läuft das über die Telefonleitung. D.h. erst mal
muss die Telefonverbindung konfiguriert werden und stehen und erst dann
stellt sich die Frage: wie funktioniert eigentlich FAX da drüber.
So auch hier. Erst mal muss SPI stehen und erst dann geht es um die
Fragestellung: wie spreche ich jetzt mit bestehender SPI-Verbindung den
(in deinem Fall) daran angeschlossenen Sensor an.
Karl Heinz schrieb:> Da gibt es ein schönes Kapitel über SPI.>> Vielleicht mal im PDF-Reader das Inhaltsverzeichnis einschalten?
Ich hab im falschen Datenblatt geschaut, ich hab die ganze Zeit im
Datenblatt des Temperatur Sensor gesucht.
Danke für deine antworten.
Und immer dran denken: SPI ist eigentlich mehr ein 'wir tauschen Bytes
aus' als ein geordnetes Senden und Empfangen.
Im Grunde braucht man nur 1 Übertragungsfunktion auf Seiten des Masters.
1
uint8_texchangeByte(uint8_tbyte)
2
{
3
SPDR=byte;
4
while(!(SPSR&(1<<SPIF))
5
;
6
returnSPDR;
7
}
Das ist aber auch schon der einzige Kritikpunkt, den ich am AVR
Datenblatt anbringen könnte, dass diese Sache nicht so klar
herausgearbeitet wird, wie es notwendig wäre.
while(!(SPSR&(1<<SPIF)))//zweite 8 Bit Warten bis Daten gesendet und empfangen wurden
19
{
20
}
21
returnbyte;
22
}
23
24
25
unsignedlongSPI_Temperatur()
26
{
27
unsignedlongTemp=0;
28
PORTB&=~(1<<PB4);// Chip Select
29
SPI_exchangeByte(0x42);//Register auswahl
30
Delay_10us(20);//benötigte Pause
31
Temp=ADC;//Temperatur
32
PORTB|=(1<<PB4);// Chip Select
33
return(Temp/16);//wandeln
34
}
Erhalte immer noch 0, Datenblatt habe ich jetzt schon 10min gesucht,
doch bringt mich nicht weiter.
Ich vermute mal ich mach das mit dem Senden und Empfangen immer noch
nicht richtig, doch habe nirgends eine passende Erklärung gefunden.
Erstmal solltest du, wenn es dir schon einer vormacht, den Code richtig
kopieren
Karl Heinz schrieb:> uint8_t exchangeByte( uint8_t byte )> {> SPDR = byte;> while( ! (SPSR & (1<<SPIF) )> ;> return SPDR;> }Rebi schrieb:> uint8_t SPI_exchangeByte( uint8_t byte )> {> SPDR = byte;> while (!(SPSR & (1<<SPIF))) //zweite 8 Bit Warten bis> Daten gesendet und empfangen wurden> {> }> return byte;> }
byte wird in deinem Fall nie beschrieben. Das heißt du liest immer das
aus was du eig. rausschreiben wolltest.
Rebi schrieb:> Temp = ADC; //Temperatur
ADC kommt hier ebenso aus dem nichts, das ist sicher nicht das Register
was du auslesen möchtest.
Außerdem ist das ein 16bit Sensor mit 13bit Standardausgabe bei
Power-On. Da reicht ein byte auslesen nicht um deine Temperatur zu
erhalten.
Johannes schrieb:> ADC kommt hier ebenso aus dem nichts, das ist sicher nicht das Register> was du auslesen möchtest.>> Außerdem ist das ein 16bit Sensor mit 13bit Standardausgabe bei> Power-On. Da reicht ein byte auslesen nicht um deine Temperatur zu> erhalten.
Dann so?
Johannes schrieb:> byte wird in deinem Fall nie beschrieben. Das heißt du liest immer das> aus was du eig. rausschreiben wolltest.
Ups das war ein dummer fehler danke.
Das wird dir keiner sagen können ob das so richtig ist. Denn wer weiß
schon was die Funktion SPI_send_recive(); macht.
Rebi schrieb:> uscSPI_High = SPI_send_recive (?); // Highbyte empfangen> uscSPI_Low = SPI_send_recive (?); // Lowbyte empfangen
Mit deiner Scheibchentaktik vergraulst du dir nur potenzielle Helfer.
Also poste deinen ganzen Code als Anhang, dann kann man dir auch besser
helfen. So innovativ und geheim wird es schon nicht sein was du da
machst, dass du es vor allen verbergen müsstest.
Mit dem CS High direkt nach dem SPI_send_receive() wäre ich vorsichtig.
Je nach SPI Implementierung (weiss nicht, ob's auf den AVR zutrifft),
könnte es nämlich sein, dass Du dem Slave das CS wegziehst, solange
die Übertragung auf den Leitungen noch läuft. Am besten mal mit einem
Skop
draufschauen.
Johannes schrieb:> Mit deiner Scheibchentaktik vergraulst du dir nur potenzielle Helfer.> Also poste deinen ganzen Code als Anhang, dann kann man dir auch besser> helfen. So innovativ und geheim wird es schon nicht sein was du da> machst, dass du es vor allen verbergen müsstest.
Der eigentlich Code ist nicht von mir. Ich hab eigentlich alles
verstanden ausser der SPI Teil.
Sein Programm sieht so aus:
while(!(SPSR&(1<<SPIF)))//erste 8 Bit Warten bis Daten gesendet und empfangen wurden
67
{
68
}
69
Delay_10us(1);
70
returnSPDR;
71
}
72
73
elseif((ucData1>0)&&(ucData2>0)&&ucData0>0)
74
{
75
SPDR=ucData0;// Daten senden/ empfangen
76
while(!(SPSR&(1<<SPIF)))//erste 8 Bit Warten bis Daten gesendet und empfangen wurden
77
{
78
}
79
80
SPDR=ucData1;// Daten senden/ empfangen
81
while(!(SPSR&(1<<SPIF)))//zweite 8 Bit Warten bis Daten gesendet und empfangen wurden
82
{
83
}
84
85
SPDR=ucData2;// Daten senden/ empfangen
86
while(!(SPSR&(1<<SPIF)))//zweite 8 Bit Warten bis Daten gesendet und empfangen wurden
87
{
88
}
89
Delay_10us(1);
90
returnSPDR;// SPI Daten zurück an main
91
}
92
93
}
Aber da habe ich nur Bahnhof verstanden, also habe ich es versucht neu
zu schreiben aber irgendwie nicht hingebraucht.
Aber morgen ist jemand hier der es mir erklären kann, trodzdem danke an
alle die geholfen haben.
mper schrieb:> Mit dem CS High direkt nach dem SPI_send_receive() wäre ich vorsichtig.> Je nach SPI Implementierung (weiss nicht, ob's auf den AVR zutrifft),> könnte es nämlich sein, dass Du dem Slave das CS wegziehst, solange> die Übertragung auf den Leitungen noch läuft.
Nope, das kann nicht passieren.
Denn wenn die exchange Funktion zurückkehrt, ist die SPI Übertragung
bereits abgeschlossen. Die Funktion wartet darauf.
Rebi schrieb:> Aber da habe ich nur Bahnhof verstanden, ....
Hier
1
SPDR=ucData1;// Daten senden/ empfangen
2
while(!(SPSR&(1<<SPIF)))//zweite 8 Bit Warten bis Daten gesendet und empfangen wurden
3
{
4
}
findet sich doch immer wieder der gleiche 'Building Block' wieder. UNd
genau den hast du in der exchange Funktion auch.
Das funktioniert so
Durch die Zuweisung an SPDR wird das SPI angestossen. Ab dann läuft der
Austausch der Bytes.
Der Teil hier
1
while(!(SPSR&(1<<SPIF)))
2
;
wartet drauf, dass dieser Austausch abgeschlossen wird.
Ist er das, dann kann man sich das Byte, weilches per SPI mit dem Slave
getauscht wurde aus dem SPDR Register abholen.
Daher findet sich hier in deiner send_receive Funktion
1
SPDR=ucData2;// Daten senden/ empfangen
2
while(!(SPSR&(1<<SPIF)))//zweite 8 Bit Warten bis Daten gesendet und empfangen wurden
3
{
4
}
5
Delay_10us(1);
6
returnSPDR;// SPI Daten zurück an main
auch der return mit dem Wert in SPDR wieder (der Delay ist so
überflüssig wie ein Kropf.
Die exchange Funktion liefert auch den Inhalt vom SPDR. In manchen
Fällen brauchst du den nicht und kannst ihn ignorieren und in manchen
Fällen brauchst du den eben um ihn aus der send_receive Funktion
zurückzugeben.
Also ersetzt du die vielen SPDR Dinge in der send_receive Funktion durch
entsprechende Aufrufe von SPI_exchangeByte
Diese Version der Funktion macht genau dasselbe, wie die originale. Nur
dass sie nicht durch den immer gleichen SPI Teil so dermassen in die
Länge gezogen und unübersichtlich gemacht wurde.
Wozu die Funktion als Rückgabewert aber einen unsigned long vereinbart
hat, ist auch mir nicht klar. Das deutet, genauso wie der ganze Aufbau
der Originalfunktion, darauf hin, dass derjenige der die Funktion
geschrieben hat, auch nur gerade mal so lala irgendwie programmieren
kann.
Im Prinzip schon nicht so schlecht.
Nur eben mit der exchange Funktion
>> Doch was kommt dann bei SPI_send_recive rein?
Was steht denn im Datenblatt des ADC Bausteins, was er gerne haben
möchte?
Wenn da nichts dazu steht, dann eben irgendwas. Zum Beispiel 0xFF
SPI funktioniert als Austausch von Bytes. Du musst was zum ADC schicken,
damit er beim Austausch was zurück geben kann. Wenn es den ADC nicht
interessiert was du ihm gibst (weil er sowieso nach dem Chip Select
seinen Messwert als 2 Bytes loswerden will), dann schickst du eben
irgendwas rüber. Aber schicken musst du was. Denn der Austausch
funktioniert nur, wenn der Master was rübergibt. Bei SPI liegt die
komplette Aktivität beim Master.
Edit: eventuell nach dem Chip Select zur Aktivierung des ADC_Bausteins
ein klein wenig warten. Du brauchst ja auch nach dem Aufwachen in der
früh ein bisschen Zeit. Ob das notwendig ist oder nicht, findest du, wie
könnte es anders sein, im Datenblatt das ADC Bausteins.
Karl Heinz schrieb:> Was steht denn im Datenblatt des ADC Bausteins, was er gerne haben> möchte?> Wenn da nichts dazu steht, dann eben irgendwas. Zum Beispiel 0xFF
Hab nur schnell das verlinkte Datenblatt überflogen.
So einfach ist es doch nicht.
Allerdings bin ich gerade in Eile.
Aber so schwer ist das nun auch wieder nicht.
Karl Heinz schrieb:> Karl Heinz schrieb:> Hab nur schnell das verlinkte Datenblatt überflogen.> So einfach ist es doch nicht.>> Allerdings bin ich gerade in Eile.> Aber so schwer ist das nun auch wieder nicht.
einfach nur geil!
;-)
ich bin dein grösster fan!
Ich möchte mich nochmals für deine Ausführlichen erklärungen danken Karl
Heinz. Hab jetzt ein bisschen verstanden wie die Kommunikation mit SPI
funktioniert.
Karl Heinz schrieb:> Wozu die Funktion als Rückgabewert aber einen unsigned long vereinbart> hat, ist auch mir nicht klar. Das deutet, genauso wie der ganze Aufbau> der Originalfunktion, darauf hin, dass derjenige der die Funktion> geschrieben hat, auch nur gerade mal so lala irgendwie programmieren> kann.
Es wird auch noch ein Display angesteuert. Dies braucht Werte wie 0xFE45
deswegen das long.
Rebi schrieb:> Ich möchte mich nochmals für deine Ausführlichen erklärungen danken Karl> Heinz. Hab jetzt ein bisschen verstanden wie die Kommunikation mit SPI> funktioniert.>> Karl Heinz schrieb:>> Wozu die Funktion als Rückgabewert aber einen unsigned long vereinbart>> hat, ist auch mir nicht klar. Das deutet, genauso wie der ganze Aufbau>> der Originalfunktion, darauf hin, dass derjenige der die Funktion>> geschrieben hat, auch nur gerade mal so lala irgendwie programmieren>> kann.>> Es wird auch noch ein Display angesteuert. Dies braucht Werte wie 0xFE45> deswegen das long.
Das ist aber kein Grund dafür, dass die Funktion einen unsigned long
zurükgeben muss.
Wenn es nur Ausgabefunktionen gibt, die lediglich einen unsigned long
ausgeben können, dann ist der richtige Zeitpunkt zum 'Hochwandeln' kurz
vor der Ausgabe gegeben. Aber eine Funktion, die einen Wert liefert,
darf den Aufrufer nicht dazu zwingen einen wesentlich größeren
Datentyp zu verwenden, als notwendig. Einen int würde ich mir ja noch
einreden lassen, aber ein unsigned long ist aus 2 Gründen unsinnig:
Selbst wenn man mit Fixpunkt Arithmetik arbeitet, machen mehr als 2
künsltiche Nachkommastellen keinen sinn. D.h. mit einem int kann man
(als Zahlenwerte) alle Zahlen im Bereich -32768 bis +32767 darstellen.
Mit besagten 2 Nachkommastellen würde das dann einem Temperaturbereich
von -327.68° bis +327.67° darstellen. Für den Hausgebrauch mehr als
genug, zumal ich die 2 Nachkommastellen schon mal grundsätzlich wegen
Sinnhaftigkeit in Frage stelle.
Zum anderen ist unsigned schon mal komplett daneben. Denn (abgesehen von
Grad Kelvin) soll es ja auch schon mal negative Temperaturen geben.
Ich bin am WE nicht dazu gekommen, mir das Datenblatt mal näher
anzusehen.
Hier die für dich wichtigsten Punkte
* Nach dem Anlegen der Spannung ist der Sensor bereits auf Dauermessung
eingestellt. D.h. der misst von sich aus laufend die Temperatur
* Es gibt Register, von denen du dir die Werte abholen musst, bzw. in
die du Konfigurationen schreibst
1
Register Address Description Power-On Default
2
0x00 Status 0x80
3
0x01 Configuration 0x00
4
0x02 Temperature value 0x0000
5
0x03 ID 0xC3
6
0x04 TCRIT setpoint 0x4980 (147°C)
7
0x05 THYST setpoint 0x05 (5°C)
8
0x06 THIGH setpoint 0x2000 (64°C)
9
0x07 TLOW setpoint 0x0500 (10°C)
Da der Sensor auch ohne spezielle Konfiguration von sich aus erst mal
misst, reicht es also das Register 0x02 auszulesen.
* um ein bestimmtes Register auszulesen, musst du dem Sensor nach dem
Chip Select ein Kommando-Byte geben. Erst danach beginnt dann die
Übertragung der Daten.
1
SPI COMMAND BYTE
2
All data transactions on the bus begin with the master taking CS from
3
high to low and sending out the command byte. The command byte indicates
4
to the whether the transaction is a read or a write and provides the
5
address of the register for the data transfer. shows the command byte. ADT7320Table 15
6
Table 15. Command Byte
7
C7 C6 C5 C4 C3 C2 C1 C0
8
0 R/W Register address 0 0 0
D.h. hier ist dein erstes Byte, dass du per SPI an den Sensor überträgst
in Bitform aufgeführt.
Karl Heinz schrieb:> Ich bin am WE nicht dazu gekommen, mir das Datenblatt mal näher> anzusehen.
Ich hab es schon geschafft, wollte nur danke sagen wegen deinen
Beiträgen.
Karl Heinz schrieb:> Das ist aber kein Grund dafür, dass die Funktion einen unsigned long> zurükgeben muss.
Stimmt der ist unnötig.