Forum: Compiler & IDEs Mit Sensor über SPI (ATMega32) kommunizieren


von Richie R. (richierich)


Lesenswert?

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

von Udo (Gast)


Lesenswert?

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

von RichieRich (Gast)


Lesenswert?

...

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;
}

von Udo (Gast)


Lesenswert?

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

von RichieRich (Gast)


Lesenswert?

Hallo Udo,

vielen Dank für die ausführe Antwort!

Gruß
Richie

von Udo (Gast)


Lesenswert?

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
  }

von Wilhelm W. (tt-elek)


Lesenswert?

@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

von Wilhelm W. (tt-elek)


Lesenswert?

Entwarnung
Der Prozessorport scheint eine Macke zu haben. Nach Umstellen auf einen 
anderen Port funktioniert das Auslesen nun.

Gruß Wilhelm

von Michael (Gast)


Lesenswert?

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

von Michael (Gast)


Angehängte Dateien:

Lesenswert?

Hab den Anhang vergessen...

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
Noch kein Account? Hier anmelden.