mikrocontroller.net

Forum: Compiler & IDEs [AVR] SPI wartet endlos auf SPIF Flag


Autor: Malte __ (malte) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich versuche gerade die SPI Schnittstelle eines MEGA128 als Master für 
die Ansteuerung einer MMC Karte zu verwenden, wobei der MMC Treiber 
bereits von Nut/OS bereit gestellt wird.
Nur scheint das SPIF Flag nie gesetzt zu werden und meine Anwendung 
hängt endlos.

#define SPIDDR        DDRB
#define SPIPORT       PORTB
#define SCLK          0x02
#define MOSI          0x04
#define MISO          0x08

static uint8_t SpiMmCardIo(uint8_t val)
{
    SPDR = val;               /* put byte to send in SPDR, which initiates xmit  */
    while(!(SPSR & (1<<SPIF))) { /* wait for completion */
        printf("spi wait\n");
     }
    return SPDR;               /* return with byte shifted in from slave */
}


static int SpiMmcIfcInit(NUTDEVICE * dev)
{
    SPIDDR = SCLK + MOSI;
    SPIPORT = 0x00;
    NutSleep(500);
    SpiMmCardSelect(0);
    SPCR = (1 << SPE) | (1 << MSTR);  /* enable SPI as master, set clk divider and max speed */
    NutSleep(250);
    /* start off with 80 bits of high data with card deselected */
    int i;
 printf("\nSend dummy bytes\n");
    for (i = 0; i < 10; i++) {
      SpiMmCardIo(0xff);
      printf("byte send\n");
    }
 printf("\nInit device\n");
    return MmCardDevInit(dev);
}

Die Warteschleife sieht aber genau so aus, wie in der ATMEL Doku und 
auch wird erst SPDR geschrieben, bevor das Flag zum ersten mal abgefragt 
wird.

Auf dem UART erscheint endlos die "spi wait" Meldung und niemals "byte 
send". Was geht hier schief?

Autor: VonNixNeAhnung (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hmmm...

Ist /SS als Ausgang definiert?!
Master Mode When the SPI is configured as a master (MSTR in SPCR is set), the user can determine the
direction of the SS pin.
If SS is configured as an output, the pin is a general output pin which does not affect the SPI
system. Typically, the pin will be driving the SS pin of the SPI slave.
If SS is configured as an input, it must be held high to ensure Master SPI operation. If the SS pin
is driven low by peripheral circuitry when the SPI is configured as a master with the SS pin
defined as an input, the SPI system interprets this as another master selecting the SPI as a
slave and starting to send data to it. To avoid bus contention, the SPI system takes the following
actions:
1. The MSTR bit in SPCR is cleared and the SPI system becomes a slave. As a result of the
SPI becoming a slave, the MOSI and SCK pins become inputs.
2. The SPIF flag in SPSR is set, and if the SPI interrupt is enabled, and the I-bit in SREG is
set, the interrupt routine will be executed.
Thus, when interrupt-driven SPI transmission is used in master mode, and there exists a possibility
that SS is driven low, the interrupt should always check that the MSTR bit is still set. If the
MSTR bit has been cleared by a slave select, it must be set by the user to re-enable SPI master
mode.
siehe auch Datenblatt S.167

mfg

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Auf dem UART erscheint endlos die "spi wait" Meldung und niemals "byte
send". Was geht hier schief?

Endlos? Es sollte doch eher einmal kommen und dann hängt es. Wenn es 
endlos kommt stimmt was anderes nicht.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast wrote:
>> Auf dem UART erscheint endlos die "spi wait" Meldung und niemals "byte
> send". Was geht hier schief?
>
> Endlos? Es sollte doch eher einmal kommen und dann hängt es. Wenn es
> endlos kommt stimmt was anderes nicht.

Quatsch.

Autor: Malte __ (malte) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ist /SS als Ausgang definiert?!
Danke, den Teil im Datenblatt hatte ich übersehen. Jetzt funktionierts.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon K. (simon) wrote:
> Quatsch.

Selber Quatsch. Jetzt lieste nochmal durch was der OP geschrieben hat.
Einmal hängt die Anwendung endlos und einmal wird endlos spi wait 
ausgegeben.

Entweder hängt es oder es gibt dauernd spi wait aus.

Autor: Malte __ (malte) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Entweder hängt es oder es gibt dauernd spi wait aus.
Die Anwendung hing in der Warteschleife fest. Und um sicher zu gehen, 
dass es auch wirklich die Warteschleife und nichts anderes (wie z.B. 
Sprünge ins Nirvana) ist, hatte ich dann da die Meldung eingebaut, die 
dann eben dauerhaft ausgegeben wurde.

Autor: VonNixNeAhnung (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>> Ist /SS als Ausgang definiert?!
>>Danke, den Teil im Datenblatt hatte ich übersehen. Jetzt funktionierts.
Gern geschehen! Zumal, hatte ich ähnliches Problem (den interessanten 
Teil des Datenblattes zuvor geflissentlich ignoriert) auch schon mal.

mfg

Autor: Philipp Burch (philipp_burch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
SPCR = (1 << SPE) | (1 << MSTR);  /* enable SPI as master, set clk divider and max speed */
Entweder solltest du da noch den Kommentar oder den Code ändern. 
Maximale Frequenz des SPIs erreichst du erst, wenn auch SPI2X in SPSR 
gesetzt ist (F_CPU / 2). Das nur so am Rande.

Autor: Daniel Luscher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, ich habe das gleiche Problem - bei mir hängt wird ebenfalls auf 
SPIF gewartet und es geht nicht weiter.


Ich initialisiere als Master:
void SPI_InitMaster()
{
  SPI_DDR |= (1<<SPI_MOSI) | (1<<SPI_SCK) | (1<<SPI_SS);    // outputs
  SPI_DDR &= ~(1<<SPI_MISO);                  // input
  SPI_PORT |= (1<<SPI_MISO);                  // pull-up

  SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPIE);  // enable SPI, Master mode, enable Interrupt
  SPCR = (1<<SPR0 | 1<<SPR1);          // set clock rate /128
}

Danach wird ein byte gesendet:
void SPI_MasterTransmit(uint8_t byte)
{
  SPDR = byte;
  while( !(SPSR & (1<<SPIF)) );  // wait until transmission complete
}

Wenn ich das richtig verstehe, wird SPIF gesetzt, nachdem das byte durch 
das Schieberegister durch ist, es muss also nichtmal ein zweites Gerät 
angeschlossen sein, oder? Man empfängt im Gegenzug praktisch 0x00...

Also Kontroller wird bei mir vor Ausführung des Befehls eine LED 
ausgeschaltet und nach dem Befehl danach wieder eingeschaltet. Sie geht 
aus, aber nicht wieder an, entprechend wird es an der Schleife liegen.

Slave Select wird in der Initialisierung als Output gesetzt, das löst 
das Problem leider nicht.

Vielen Dank schonmal!

Autor: Daniel Luscher (danielschlumpf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch ein Nachtrag zu meinem vorigen Post:

Ich verwende einen ATMega32 bei 8Mhz und folgenden Port-Definitionen:
#define SPI_PORT    PORTB
#define SPI_PIN      PINB
#define SPI_DDR      DDRB  // direction
#define SPI_MOSI    5    // master out / slave in
#define SPI_MISO    6    // master in / slave out
#define SPI_SCK      7    // clock
#define SPI_SS      4    // slave select

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>  SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPIE);  // enable SPI, Master mode, >enable 
Interrupt

Mach das SPIE da weg.

Autor: Daniel Luscher (danielschlumpf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey Holger,

danke für den Tipp, jetzt geht's! Super.

Heißt das, ich kann nur entweder den Interrupt oder die SPIF flag 
verwenden? Der Interrupt ist bei mir nämlich ausgelöst worden, habe ich 
festgestellt... jetzt ist er natürlich deaktiviert.

Übrigens: habe in dem Code noch einen anderen Fehler entfernt, es muss 
natürlich
SPCR |= (1<<SPR0 | 1<<SPR1);

heißen, mit dem "|=" anstelle "=", sonst wird der ISP direkt wieder 
deaktivert.

Danke nochmal!

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.