Testen kannst du die SPI-Kommunikation indem du MISO mit MOSI direkt verbindest. Stimmt der SPI-Modus (Polarität + Phase)?
mfG
Markus
Hi und hallo,
ich versuche mich gerade daran einen Sensor per SPI anzusprechen. Leider funktioniert es bis jetzt noch
nicht.
Der Chip-Select Pin funktioniert. Das habe ich messen können.
Das Ganze läuft zwar durch, aber es steht hinterher nur Müll in der Variable "daten". Ich habe das Gefühl, dass die Kommunikation erst gar nicht anspringt.
Ich habe es zwar nicht richtig messen können, aber anscheinend läuft die Clock des SPI nicht an.
Wäre klasse, wenn mir da jemand weiter helfen könnte. Vielleicht gibt es ja schon einen fehler bei der Initialisierung des SPI.
Vielen Dank schon einmal!
Hier einmal die Teile meines Codes:
Die Kommunikation mit dem Sensor soll dann wie folgt laufen:Code:#define SPI_PIN PINB #define SPI_DDR DDRB #define SPI_PORT PORTB #define MISO 3 #define MOSI 2 #define Clock 1 #define SS 0 CS_PIN PINE void SPI(void) { SPI_PORT_DDR &=~(1<<MISO); // miso auf input SPI_PORT_DDR |= (1<<Clock); // clock auf output SPI_PORT_DDR |= (1<<MOSI); // mosi auf output SPI_PORT_DDR |= (1<<SS); // wird nicht gebraucht, ss auf output CS_PIN |= (1<<PE2); // chip selet auf high SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1); }
Code:#include <avr\io.h> #include <stdlib.h> #include <avr/interrupt.h> int main(void) { cli(); Ports(); SPI(); sei(); CS_PIN &= ~(1<<CS_TEMP); // CS auf LOW _delay_us(10); // kurz warten SPDR= 0x10; // Daten senden while(!(SPSR & (1<<SPIF))); daten= (SPDR<<8) & 0x3FFF; // Ersten 8 Bit als MSBs ablegen SPDR= 0x01; while(!(SPSR & (1<<SPIF))); daten+= SPDR; // Letzten 8 Bit dazu addieren CS_PIN |= (1<<PE2); // cs High while(1) { ..... } }/* main */
Testen kannst du die SPI-Kommunikation indem du MISO mit MOSI direkt verbindest. Stimmt der SPI-Modus (Polarität + Phase)?
mfG
Markus
Tiny ASURO Library: Thread und sf.net Seite
Hallo,
Ich denke doch. ich habe die SPI INitialisierung mal ein wenig überarbeitet:Stimmt der SPI-Modus (Polarität + Phase)?
Mein Aufruf sieht nun so aus:Code:void initSPI(void) // Initialisierung der SPI Schnittstelle { SPI_PORT_DDR &=~(1<<SPI_MISO); // miso auf input SPI_PORT_DDR |= (1<<SPI_Clock); // clock auf output SPI_PORT_DDR |= (1<<SPI_MOSI); // mosi auf output SPI_PORT_DDR |= (1<<SPI_SS); Disable(); SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPI2X)|(1<<SPR0)|(1<<SPR1)|(1<<CPOL)|(1<<CPHA); // SPI Enable // Master Select // f_clkio/64 // Leading Edge -> Falling // Trailing Edge -> Rising
Was ich sagen kann, ist, dass das CS funktioniert. Geht am Anfang auf High, zum Auslesen wird es dann eben LOW gesetzt und danach wieder High. Anscheinen läuft die Clock nicht.Code:volatile uint16_t data= 0; Enable(); _delay_us(10); SPDR= 0x10; while(!(SPSR & (1<<SPIF))); data= (SPDR<<8) & 0x3FFF; SPDR= 0x10; while(!(SPSR & (1<<SPIF))); data+= SPDR; _delay_us(10); Disable();
Der Code läuft aber so durch. Danach habe ich einfach noch Kontrollausgaben per LED auf meinem Board. Daher sehe ich, dass der komplette Code durchlaufen wird.
In der Variable data steht aber am Ende nur eine Null drin, wird der Variable am Anfang ja auch zugewiesen. Also ändert sich da nichts, d.h. der Sensor sendet keine Daten. Wie oben schon geschreiben, anscheinend läuft die Clock nicht, somit kann ja auch nichts empfangen werden.
Wie es scheint, läuft die Clock auch nicht, wenn ich MISO und MOSI direkt verbinde.
Hat jemand noch eine Idee, woran es liegen könnte?
Ich habe da große Zweifel.
Aber wirklich eindeutig kann ich das nicht sagen, denn das, was du in deinem ersten Post an Code gepostet hast, ist schon einigermaßen ärgerlich. Das sind offenbar nicht sonderlich sorgfältig zusammen kopierte Fragmente. Anscheinend gehören diese Fragmente noch nicht mal zum selben Code, denn es gibt die Defines "SPI_DDR" und "SPI_PORT", benutzt wird dann aber "SPI_PORT_DDR".
Was ist das für eine Zeile? [1]Code:CS_PIN PINE
Wieso wird der CS-Pin einmal als "PE2" angesprochen, und einmal als "CS_TEMP"? Was ist "CS_TEMP"?Code:CS_PIN &= ~(1<<CS_TEMP); // CS auf LOW ... CS_PIN |= (1<<PE2); // cs High
Jedenfalls wenn ich die Ungereimtheiten per Raten interpoliere ([1] um "#define" ergänzt, und CS_TEMP=PE2), dann funktioniert dein CS sicher nicht.
MfG
Stefan
Hallo,
dass der Code ein wenig durcheinander ist, liegt nicht daran, dass es wild zusammenkopiert ist, sondern daran, dass ich das eine Menge rumprobiert habe und dabei die Ordnung habe schleifen lassen.
Ich habe das Ganze einmal aufgeräumt, siehe unten.
Das CS funktioniert sicher. erst ist der Pin HIGH, dann setze ich ihn auf LOW und dann wieder auf HIGH. Das habe ich mir mit dem Oszi angeschaut.
Ich habe einfach mal den SPI-Kram auskommentiert, ein delay zwischen Sensor-aktivieren und Sensor-deaktivieren eingefügt, CS am Oszi angeschaut und das springt eben wie gewünscht HIGH - LOW - HIGH.
Bei der Clock sehe ich aber leider nichts.
Ich habe das Gefühl, dass ich vor lauter Bäumen den Wald nicht mehr sehe.
SPI - Init:
Code aus der main:Code:#define SPI_PIN PINB #define SPI_DDR DDRB #define SPI_PORT PORTB #define SPI_MISO PB3 #define SPI_MOSI PB2 #define SPI_Clock PB1 #define SPI_SS PB0 SPI_DDR &=~(1<<SPI_MISO); // miso auf input SPI_DDR |= (1<<SPI_Clock); // clock auf output SPI_DDR |= (1<<SPI_MOSI); // mosi auf output SPI_DDR |= (1<<SPI_SS); // ss auf output PORTE |= (1<<PE2); // Sensor deaktivieren SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPI2X)|(1<<SPR0)|(1<<SPR1)|(1<<CPOL)|(1<<CPHA); // SPI Enable // Master Select // f_clkio/64 // Leading Edge -> Falling // Trailing Edge -> Rising
Code:PORTE &= ~(1<<PE2); // Sensor aktivieren, CS -> LOW _delay_us(10); // wait SPDR= 0x10; while(!(SPSR & (1<<SPIF))); data= (SPDR<<8) & 0x3FFF; // 8 Bit auslesen SPDR= 0x01; while(!(SPSR & (1<<SPIF))); data+= SPDR; // Weitere 8 Bit auslesen _delay_us(10); // wait PORTE |= (1<<PE2); // Sensor deaktivieren
Was ist das für ein µC?
MfG Hannes
Hallo,
das ist ein AT90CAN128. Der Sensor ist ein Temperatursensor ADT 7301.
SPI2X befindet sich im Register SPSR (DORD wäre noch im SPCR Register).
Versuche es einmal zu ändern.
MfG Hannes
Hallo,
das mit dem SPI2X ist mir voll durchgegangen. Ich habe es jetzt mal rausgenommen und lasse das Ganze einfach auf f_clkio/64 laufen nur mit SPR1 gesetzt.
Leider bringt das noch nicht den erwünschten Erfolg. Auch die Einstellung DORD bringt erst einmal scheinbar keine sichtbare Änderung.
Ich habe so langsam das Gefühl, dass es irgendwie an dem Sensor liegt oder eben am Zusammenspiel. Wenn ich den Sensor abnehme und das Programm laufen lasse, habe ich in "data" immer eine "Null" stehen. Wenn ich ihn anschließe, scheinen Daten empfangen zu werden, allerdings nur Müll wie es scheint.
Laut Datenblatt muss das 3te Bit eine 1 sein (Shutdown Bit). Die restlichen 15Bit müssen 0 sein. Bei einem 8Bit Register (wie bei deinem µC) musst du einmal 0x20 senden und dann 0x00.
MfG Hannes
Lesezeichen