Forum: Mikrocontroller und Digitale Elektronik ATmega8: Grundlagen SPI


von Tom (Gast)


Lesenswert?

Hallo Profis,

ich hab mal wieder ein Grundlagenproblem:

Und zwar habe ich anhand des Datenblatts vom ATmega8 und einiger Threads 
dieses Forums den Controller nun so weit gebracht, dass er sendet.

Der Code:

********************************************************************

//HAUPTPROGRAMM
int main (void)
{
  SPI_MasterInit();
  sei();

  for(;;)
  {
    SPI_MasterTransmit(0xff);
    _delay_us(20);
    SPI_MasterTransmit(0x00);
    _delay_us(20);
  }

  return 0;
}




//Funktionen

void SPI_MasterInit(void)
{
/* Set MOSI and SCK output, all others input */
DDRB |= (1<<PB2) | (1<<PB3) | (1<<PB5);

/* Enable SPI, Master, set clock rate fck/16 */
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}


void SPI_MasterTransmit(char cData)
{
/* Start transmission */
SPDR = cData;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)))
;
}

***********************************************************************

Nun meine Frage:

Ich will SPI nutzen, um einen Sensor auszulesen. Dazu muss erst ein char 
an den Sensor gesendet werden, damit dieser weiß was ich von ihm will. 
Anschließend sendet dieser ein 11Bit-Wort zurück an den Controller.

Nur: Wie empfange ich?? Vor allem ein 11Bit-Wort.

Danke für Eure Hilfe.

Gruß

Tom

von Tom (Gast)


Lesenswert?

Ist das so eine blöde Frage??

von Gast (Gast)


Lesenswert?

Was ist mit dem /SS Signal. Benötigst du eins?
P.S. Is das ein VTI Sensor????

von Gast (Gast)


Lesenswert?

So nochmal. Hatte das Problem auch mal mit nem VTI Sensor. Wenn der vom 
Sensor ein 11Bit Signal bekommen hat habe ich zuerst einen 8Bit Befehl 
gesendet und im Anschluss 2 Dummybytes gesendet (0x00). Die ausbleibende 
Frequenz war dem Sensor egal, da er seinen Takt vom Controller bekommen 
hat. Zwischen den Dummybefehlen natürlich den Speicher auslesen.

von Tom (Gast)


Lesenswert?

Ja, es ist ein Sensor von VTI. Und zwar der SCA1000. Dieser wird dann in 
der Prototypenphase durch den SCA61T getauscht. Ich hoffe jedoch, dass 
beide identische Werte über SPI senden/erwarten.

Verwendest Du ähnliche Sensoren?

Bzgl. /SS:

Muss ich erst PB2 (also /SS) auf Low, dann senden und dann auf Antwort 
vom Sensor warten?

von Tom (Gast)


Lesenswert?

Hallo Gast,

könntest Du mir das evtl etwas genauer erklären mit den Dummybytes?

Heißt das:

- 8Bit Kommando
- 1. Dummybyte
- Speicher auslesen
- 2. Dummybyte
- Speicher auslesen

Oder verstehe ich das falsch?

von Michael Wilhelm (Gast)


Lesenswert?

Wenn der Mega8 als Master fungiert, kannst du einen X-beliebigen Portpin 
nehmen. Als Slave allerdings wird durch externes Low-ziehen des SS-Pins 
die Empfangsroutine angeworfen.

MW

von Bruno (Gast)


Lesenswert?

Ich hatte den SCA100T.

1. /SS auf low (so war es bei mir mußte im Datenblatt gucken ob high 
oder low)
2. 8Bit-Befehl senden
3. Dummybyte 0x00 senden
4. Empfangsspeicher auslesen
5. Dummybyte 0x00 senden
6. /SS auf high

So war das bei mir. Habe leider kein Codebeispiel zur Hand, kann das 
aber heute Abend nachlegen bei Bedarf.

von Tom (Gast)


Lesenswert?

Hallo Gast,

das wäre echt super nett von Dir, wenn ich den Code bekommen könnte. Es 
sind nämlich (fast) identische Sensoren.

Nun die vielleicht blödeste aller Fragen:

Wie sieht die Funktion fürs Empfangen aus und wo/was ist der 
Empfangsspeicher?

Vielen Dank und

Beste Grüße

Tom

von Michael Wilhelm (Gast)


Lesenswert?

Der Empfangsspeicher ist das SPDR.

MW

von Bruno (Gast)


Lesenswert?

Einfach das Register auslesen und feddich. Mußt event noch die SPI 
danach wieder freischalten (Flags)??!!?? Das weiß ich aber nicht so 
genau. Atmel is schon zu lange her. Werde den Code später mal posten.

von Bruno (Gast)


Lesenswert?

Anbei wie versprochen der Code für den SCA100T
1
int read_x_channel(void)
2
{
3
short x1,x2;
4
int x3, xGes;
5
6
 PORTB = (0 << PB0);                   //SS auf low setzen
7
 SPDR = 0x10;                          //Befehl read X-Channel in SPDR
8
 while(!(SPSR & (1<<SPIF)));          //Warten bis Empfangsende
9
 x1 = SPDR;                            //Wert x1 aus DR wird gespeichert
10
 x3 = x1<<3                            //x1 wird um 3 verschoben
11
 SPDR = 0x0c;             //Dummybyte
12
 while(!(SPSR & (1<<SPIF)));           //s.o.
13
 x2 = SPDR;               //Wert x2 aus DR wird gespeichert
14
 x2 = x2 >> 5;    //x2 wird korregiert/ Verschieben um 5 Stellen
15
                       
16
 xGes = x3 + x2;           //Endwert wird berechnet    
17
 PORTB = (1 << PB0);                   //SS auf high setzen                 
18
 
19
 return (xGes);              //Endwert wird zurück gegeben
20
}

Nicht schön aber läuft

von Kai F. (kai-) Benutzerseite


Lesenswert?

oder du machst das ganze über Software SPI, dann kannst du tatsächlich 
genau 11 Bit auslesen, aber wie heißt es so schön: "Never change a 
working system"

von Tom (Gast)


Lesenswert?

Hallo zusammen,

nochmals vielen Dank für Eure Hilfe. Heute hab ich den neuen Sensor 
bekommen (SCA61T) mit folgendem Code will ich dem an den Pelz:

***********************************************************************+

//HAUPTPROGRAMM
int main (void)
{
  SPI_MasterInit();
  sei();

  DDRD = 0xff;

  while(1)
  {
    short x1, x2;
    int x3, xGes;

    PORTB = (0 << PB2);    //SS auf Low
    SPDR = 0x10;  //Kommando "Read X-Channel" in SPDR
    while(!(SPSR & (1<<SPIF)));  //Warten auf Empfangsende
    x1 = SPDR;  //Wert x1 aus SPDR auslesen
    x3 = x1>>3;  //x1 um drei Stellen verschieben
    SPDR = 0x0c;  //Dummybyte senden
    while(!(SPSR & (1<<SPIF))); //Warten auf Empfangsende
    x2 = SPDR; //Wert x2 aus SPDR auslesen
    //x2 = x2 >> 5; //Wert x2 um fünf Stellen verschieben
    xGes = x3 + x2; //Gesamtwert errechnen

    PORTB = (1<<PB2); // /SS auf High

    PORTD = x2;

    _delay_ms(50);
  }

  return 0;
}




//Funktionen

void SPI_MasterInit(void)
{
/* Set MOSI and SCK output, all others input */
DDRB |= (1<<PB2) | (1<<PB3) | (1<<PB5);

/* Enable SPI, Master, set clock rate fck/32 */
SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR1);
}

********************************************************************

Zur Visualisierung während den Tests will gebe ich immer ein Byte an 
PORTD aus (hier x2). x2 wird auch super ausgelesen, alles passt. Aber 
wenn ich x1 ausgebe, erhalte ich nur 1en. Was muss ich ändern, damit das 
funzt?

Beste Grüße

Tom

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.