Hallo, ich habe bereits viele Einträge über SPI durchgesucht, jedoch nichts brauchbares zu meinem Problem gefunden. Mein Ziel ist es Daten von einem "Tri-Axis Inertial Sensor - ADIS16350" auszulesen. Durch das Ansprechen von bestimmten Adressen sendet der Sensor mir die jeweiligen Daten zu, jedoch bekomme ich nichts. Ich habe folgende Konfiguration: ATMega32 als Master, Sensor(ebenfalls TTL) als Slave. Der Takt wurde auf 1MHZ gesetzt. Diesen kann man auch schön am Oszi sehen, die gesendeten Bits sieht man ebenfalls am Sensor ankommen. Jedoch wenn ich mit dem Oszi an den MISO am Microcontroller gehe bzw. an den PIN woher daten aus dem Sensor kommen müssten, bekomme ich HIGH-Pegel mit einem "Rauschen" im Bereich von ca. 1 Volt, was aber erstaunlicherweise gute Rechteckform hat, jedoch eine zu geringe Amplitude um vom Microcontroller erkannt zu werden. So nun meine Frage an euch, habe ich irgendwo Fehler im Quellcode oder ist möglicherweise der Sensor im Eimer(was ich nicht hoffe) ? Der Quellcode sieht folgendermaßen aus: // ---------### IMU Test über SPI ------------- #define F_CPU 16000000 #include <avr/io.h> void SpiMasterInit(void) { unsigned char tmp; /* Check whether PB4 is an input. */ if (bit_is_clear(DDRB, 4)) { /* If yes, activate the pull-up. */ PORTB |= (1 << PB4); } /* Switch SCK and MOSI pins to output mode. */ DDRB |= (1 << PB7) | (1 << PB5); /* Enable MISO pull-up. */ PORTB |= (1 << PB6); /* Activate the SPI hardware. */ SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0); /* Clear status flags. */ tmp = SPSR; tmp = SPDR; } unsigned char SpiByte(unsigned char data) { SPDR = data; loop_until_bit_is_set(SPSR, SPIF); return SPDR; } int main(void) { SpiMasterInit(); while(1) { sendUSART( SpiByte(0x09) ); } } // Über USART(Bluetooth) wird anschließend der empfangene Wert am PC Terminal ausgegeben Ich hoffe ihr könnt mir weiterhelfen ... Danke Gruß Richie
Hallo Richie, ich geh mal davon aus, das die Datenübertragung zum und vom Sensor wie folgt abläuft: 1. du sendest als Master Daten zum Sensor (#SS als Input über PullUp auf High-Pegel gelegt) 2. Der Sensor antwortet indem er #SS auf Low zieht und damit deinen Master auf Slave umschaltet. 3. Dein Programm setzt nach dem Empfang der Daten vom Sensor das MSTR-Bit im SPSR-Register wieder auf 1, damit du wieder eine Anfrage an den Sensor senden kannst. Punkt 3 kann ich in deinem Programm nicht entdecken.... Das MSTR-Bit wird beim umschalten in den Slave-Modus laut Atmel gelöscht. Gruß Udo
... also müsste die letzte Funktion folgendermaßen ergänzt werden? unsigned char SpiByte(unsigned char data) { PORTB |= (1 << PB4); // SS auf HIGH und Controller ist Master SPDR = data; loop_until_bit_is_set(SPSR, SPIF); PORTB &= ~(1 << PB4); // SS auf LOW und Controller ist Slave return SPDR; }
Hallo Richie, ich hab mir mal das Datenblatt von dem Sensor vorgenommen, meine obige Überlegung ist falsch. Lt. Datenblatt arbeitet die SPI-Schnittstelle des Sensors im Voll-Duplex-Mode. Das Timing der SPI des Sensors entspricht dem Mode3 . D.h. du musst CPOL und CPHA im SPCR-Register auf 1 setzen:
1 | void SpiMasterInit(void) |
2 | {
|
3 | unsigned char tmp; |
4 | |
5 | PORTB |= (1 << PB4); // #SS auf HIGH |
6 | DDRB | (1 << PB4); // #SS als Ausgang |
7 | |
8 | |
9 | SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0) | (1 << CPOL) | (1 << CPHA); //SPI enable,as Master,MSB first,CLK/16,Mode3 |
10 | }
|
Gesteuert wird die SPI des Sensors über #SS des Masters. D.h. vorm Senden und Empfangen muß der Master #SS auf LOW ziehen und danach auf HIGH. Du mußt also den PB4(#SS) als Ausgang einstellen und vor dem Senden(Empfangen) auf LOW setzen und nach dem Senden(Empfangen) auf High setzen:
1 | unsigned char SpiByte(unsigned char data) //Frame senden |
2 | {
|
3 | PORTB &= ~(1 << PB4); // SS auf LOW zum Senden und Empfangen |
4 | |
5 | SPDR = data; //Bit 15 - 8, Bit 15=1, Bit14=0 |
6 | loop_until_bit_is_set(SPSR, SPIF); |
7 | |
8 | SPDR = data; //Bit 7-0 |
9 | loop_until_bit_is_set(SPSR, SPIF); |
10 | |
11 | PORTB |= (1 << PB4); // SS auf HIGH zum Beenden der Datenübertragung |
12 | }
|
Die Datenübertragung erfolgt als 16Bit Frame, wobei Bit15 die Datenrichtung vorgibt: Write=1, Read=0, gefolgt von Bit14 das immer 0 ist. Gruß Udo
Hallo Udo, vielen Dank für die ausführe Antwort! Gruß Richie
Nachtrag: Das hier sollte so aussehen:
1 | void SpiMasterInit(void){ |
2 | |
3 | DDRB = (1<<PB4)|(1<<PB5)|(1<<PB7); |
4 | SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0) | (1 << CPOL) | (1 << CPHA); //SPI enable,as Master,MSB first,CLK/16,Mode3 |
5 | PORTB |= (1 << PB7)|(1 << PB4); |
6 | }
|
@Richie Hallo Richie, hast du mittlerweile den ADIS16350 auslesen können. Ich habe ein ähnliches Problem. Nämlich dass der Ausgang Dout des Sensors hochfreqent (ca 1,5 MHz) schwingt. Zwischendurch mit kleinerer Amplitude, scheinbar im Takt der Daten. Eventuell könnte eine Lösung von dir helfen. Gruß Wilhelm
Entwarnung Der Prozessorport scheint eine Macke zu haben. Nach Umstellen auf einen anderen Port funktioniert das Auslesen nun. Gruß Wilhelm
Hallo, kann mir jemand helfen, ich möchte mittels eines C8051 auf einen ADIS16350 zugreifen. Ich verstehe allerdings nicht, wie ich das am besten realisieren soll. Der Sensor erwartet 16bit. Ich verstehe nicht, wie ich die Daten übertragen soll. Aufbauend auf einer Demo für den 8051 (siehe Anhang, ich habe da schon ein wenig auskommentiert) versuche ich das über ein Array. Kann ich in das Array einfach zB.:
1 | unsigned char test_array[MAX_BUFFER_SIZE] = {1,0,1,1,0,1,1,0,0,0,0,0,1,0,0,1} |
und über den MOSI geht die Bitfolge dann genau so an den DIN vom Sensor? Oder wie kann ich das noch machen??? Danke im Voraus! Michael
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.