www.mikrocontroller.net

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


Autor: Richie Rich (richierich)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Udo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: RichieRich (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;
}

Autor: Udo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
  void SpiMasterInit(void)
  {
    unsigned char tmp;

   PORTB |= (1 << PB4); // #SS auf HIGH
   DDRB  | (1 << PB4);  // #SS als Ausgang
   

   SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0) | (1 << CPOL) | (1 << CPHA); //SPI enable,as Master,MSB first,CLK/16,Mode3
  } 

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:
   unsigned char SpiByte(unsigned char data) //Frame senden
   {
    PORTB &= ~(1 << PB4);  // SS auf LOW zum Senden und Empfangen

    SPDR = data;  //Bit 15 - 8, Bit 15=1, Bit14=0
    loop_until_bit_is_set(SPSR, SPIF);

    SPDR = data;  //Bit 7-0
    loop_until_bit_is_set(SPSR, SPIF);

    PORTB |= (1 << PB4); // SS auf HIGH zum Beenden der Datenübertragung
   }


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

Autor: RichieRich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Udo,

vielen Dank für die ausführe Antwort!

Gruß
Richie

Autor: Udo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nachtrag:
Das hier sollte so aussehen:
 void SpiMasterInit(void){
 
   DDRB = (1<<PB4)|(1<<PB5)|(1<<PB7);
   SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0) | (1 << CPOL) | (1 << CPHA); //SPI enable,as Master,MSB first,CLK/16,Mode3
   PORTB |= (1 << PB7)|(1 << PB4);
  }

Autor: Wilhelm W. (tt-elek)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Wilhelm W. (tt-elek)
Datum:

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

Gruß Wilhelm

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.:
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

Autor: Michael (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hab den Anhang vergessen...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.