ATmega8: Grundlagen SPI

Gast #905869
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
Gast #905949
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.
Gast #905953
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?
Gast #905956
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?
Gast #905960
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.
Gast #905965
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
Gast #905969
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.
Gast #906435
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
Gast #907895
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren