C USARTD0 als SPI?

So komme ich auf den Wert, den ich eigentlich haben wollte.. Sieht das richtig aus?


CodeBox C
#define SPI_USART_CALC_BSEL(BAUD) ([I]uint16_t[/I])((F_CPU/(BAUD*2))-1)
#define SPI_USART_CALC_FBAUD(BSEL) ([I]uint16_t[/I])(F_CPU/(2*(BSEL+1)))
 
Okay. Scheint jetzt auch erst einmal zu funktionieren. Zumindest taktet die USART (im Master SPI Mode) die Bits raus.

Nun habe ich ja mein Development Board wieder vor mir. Dort ist ein Dataflash drauf (AT45DB161E).

Wenn ich MISO und MOSI brücke, empfange ich genau das wieder, was ich auch sende. Das lässt doch darauf schließen das eigentlich

Der Xmega256A3BU im USARTD0 (SPI Master Mode) richtig Konfiguriert ist oder?... Habe mal wieder das Problem das dass Device keine Bits auf den Bus legt.

Unter „0x9F“ kann ich die ID des Chips auslesen (Diese sollte „0x1F“ sein).

Wenn ich die Brücke wieder entferne, passiert bei MISO nichts (Dieser Eingang ist die ganze Zeit High, wegen den aktivierten PullUps..).

Was könnte das Problem sein? Slave Select klappt auch einwandfrei..

Mein bisheriger Code mal im Anhang..

Hier versuche ich die ID zu lesen..



CodeBox C
int main(void)

{
      PORTR.DIR = 1<<0;
     /* configure Pins for SPI (USARTD0) */
     FlashSPI.PORT = &PORTD;
     FlashSPI.SCK = 1;
     FlashSPI.MOSI = 3;
     FlashSPI.MISO = 2;
     FlashSPI.SS = 4;

     Spi_Master_USARTD0_Init(&FlashSPI,1000,3,0);

     PORTR.OUTCLR=1<<0; // led_on

      while (1) 

      {
         Spi_USARTD0_Slave_Select_Low();
         uint8_t TestByte=Spi_USARTD0_Rx_Tx(0x9f);
         Spi_USARTD0_Slave_Select_High();

         if (TestByte==0x1f)
         {
            PORTR.OUTCLR=1<<0; // led_on
         }else{
            PORTR.OUTSET=1<<0;
         }
      }

}

 

Anhänge

  • spi.c
    5,2 KB · Aufrufe: 8
Ich habe mir nun deinen Code nicht genau angesehen, was mir aber aufgefallen ist ...

Du sendest ja nur ein Byte, da kann das Dataflash überhaupt keine Daten zurücksenden.

Hier ein Beispiel aus einem Projekt von mir, wie ich das Statusword lese ...


CodeBox C
uint16_t Read_DF_status (void)
{
   uint16_t result;
         
   DF_CS_low;    
          
   DF_SPI_RW(StatusReg);      
   result = DF_SPI_RW(0x00);          
   result |= (DF_SPI_RW(0x00)<<8);     
    
   DF_CS_high;   

   return result;                  
}
 
Er sendet zwar die Daten, bloß kommt nichts zurück. Da war meine Frage mehr oder weniger ob der Slave die Daten überhaupt versteht. Habe ich was falsch konfiguriert..?
 
Er sendet zwar die Daten, bloß kommt nichts zurück.

Wie schon erwähnt, du brichst nach einem Byte ab, da kann dann nichts zurück kommen. Auch dann nicht, wenn SPI richtig konfiguriert ist.
Du musst also mindestens ein Dummy-Byte senden, je nachdem was du empfangen möchtest.
Schau dir mein obiges Beispiel an oder probiere erst mal dies ...



CodeBox C
while (1)

      {
         Spi_USARTD0_Slave_Select_Low();

         Spi_USARTD0_Rx_Tx(0x9f);
         uint8_t TestByte=Spi_USARTD0_Rx_Tx(0x00); // Dummy Byte

         Spi_USARTD0_Slave_Select_High();

         if (TestByte==0x1f)
         {
            PORTR.OUTCLR=1<<0; // led_on
         }else{
            PORTR.OUTSET=1<<0;
         }
      }
 
Habe ich beides Ausprobiert. Auf dem Oszi. wackeln alle I/Ó bis auf MISO. Da passiert nichts. Der bleibt nach wie vor auf High
 
Ok, ich schaue mir später mal die Initialisierung an (habe im Moment leider keine Zeit), eventuell kann ja auch jemand anderes noch Tipps geben.
 
Hier geben fast immer nur die selben Leute Tipps :D
Aber danke :)
 
Hier geben fast immer nur die selben Leute Tipps
Ja. Schade, dass sonst keiner helfen kann. :(

Ich habe mir den Code angesehen. Ich sehe direkt keinen Fehler, den Code finde ich allerdings nicht so übersichtlich. Es kann sein, dass ich etwas übersehen habe.

Du nutzt keinen Reset für das Dataflash, ist das auf dem Board nicht vorgesehen? Falls Reset doch vorhanden ist, ist das Dataflash eventuell permanent im Reset-Zustand?! Also das zuerst mal prüfen.

Du nutzt SS (CS) vom SPI Modul auf dem Port. Der Portpin ist frei verfügbar und wird nicht von einem anderen Modul verwendet?

Hier ein Beispiel aus einem Xmega Projekt von mir.
Es ist ein anderer Xmega, die Pin-Positionen sind nicht identisch zu deinem Xmega.
Dies könntest du aber einfach anpassen und austesten.


CodeBox C
// USART im MasterSPI Mode auf PORTE (MOSI, MISO, SCK), MISO ist im Reset-Zustand, da konfiguriere ich hier nichts.
// CS bzw. SS frei, ebenfalls auf PORTE
// RESET Dataflash auf RORTD PIN2


void dataflash_init (void)
{

  PORTE.OUTSET = (1<<PIN0);  // 1: DF_CS_
  PORTD.OUTSET = (1<<PIN2);  // 1: DF_RESET_

  PORTE.DIRSET = (1<<PIN3) | (1<<PIN1) | (1<<PIN0);  // OUTPUT: DF_CS_, DF_MOSI, DF_SCK
  PORTD.DIRSET = (1<<PIN2);        

  USARTE0.CTRLA = 0;
  USARTE0.CTRLC = USART_CMODE_MSPI_gc;  // MasterSPI, UDORD=0, UCPHA=0

  // Condition: fboud = fperi / 2
  // fbout = fperi / (2 * (BSEL+1))
  // 16MBit/s, fperi = 32MHz
  USARTE0.BAUDCTRLA = 0; // BSEL
  USARTE0.BAUDCTRLB = 0; // SCALE, BSEL

  USARTE0.CTRLB = USART_RXEN_bm | USART_TXEN_bm;


  DF_RES_low
  _delay_ms(10);
  DF_RES_high
  _delay_ms(10);

}


uint8_t DF_SPI_RW(uint8_t data_out)
{

  while((USARTE0.STATUS & USART_DREIF_bm) == 0);  // Warte bis DREIF=1 ist (=Transmit Buffer empty)
  USARTE0.DATA = data_out;                        // Daten senden

  while ((USARTE0.STATUS & USART_RXCIF_bm) == 0); // Warte bis RXCIF=1 ist (=Data in Receive Buffer)
  return USARTE0.DATA;

}  
 
Also das ist ein XPlained Board. Dort ist der Reset mit einem PullUp auf VCC gezogen

Und den SS Pin kann ich nicht nutzen da auf dem Board ein anderer Pin verwendet wird. .
 
PORTE.OUTSET = (1<<PIN0); // 1: DF_CS_ PORTD.OUTSET = (1<<PIN2);

Was genau bringt das? Du setzt die Pins auf einen bestimmten Zustand bevor du sie überhaupt als Ausgang konfiguriert hast?
 
Was genau bringt das? Du setzt die Pins auf einen bestimmten Zustand bevor du sie überhaupt als Ausgang konfiguriert hast?
Genau. Der Pin ist erst Tristate, und geht dann high. Würdest Du den erst als Ausgang schalten (und danach high), würde er erstmal low gehen, und dann auf high wechseln. Auf Ausgang wird in Zeile 12, 13 geschaltet.
Was soll Pin2 für eine Funktion haben?
Steht in Zeile 3 (als Kommentar).;)
Hier geben fast immer nur die selben Leute Tipps :D
Aber danke :)
Nunja, der "harte Kern" hier ist recht klein... und von denen programmieren meiner(!) Meinung nach die wenigsten in C.
(natürlich gibt es hier auch kompetente aktive C-Member (abgesehen von Dirk mein ich), aber ich fühle mich nicht angesprochen - wenn Du Fragen zur Controller-Hardware (insbesondere Tinies) oder Assembler hast...
 
LotadaC hat ja bereits alles beantwortet, Danke :)

Jan,
ach ich sehe du nutzt SS auf Pin4 vom PORTF.
FlashSPI.SS = 4
In Spi_Master_USARTD0_Init wird der Pin von PORTF als Ausgang geschaltet.

Später schaltest du den Pin mit Position SS_bp, das ist eine Definition von den SPI Modulen.
SS_bp ist auch 4, soweit ich weiss. Muss es auch, sonst klappt dein Code nicht. Das ist also so in Ordnung, ist allerdings auch eine mögliche Fehlerquelle.



CodeBox C
   // ...
   FlashSPI.SS = 4;
   Spi_Master_USARTD0_Init(&FlashSPI,1000,3,0);
   // ...

void Spi_Master_USARTD0_Init(spi_t *SPI, uint16_t baud, uint8_t mode, uint8_t dataOrder)
{
   // ...
   PORTF.DIR       |= 1<<SPI->SS;
   // ...
}

void Spi_USARTD0_Slave_Select_Low(void)
{
   PORTF.OUTCLR = (1<<SS_bp);
}

void Spi_USARTD0_Slave_Select_High(void)
{
   PORTF.OUTSET = (1<<SS_bp);
}


In meinem obigen Code Beispiel verwende ich SPI Mode 0
USARTE0.CTRLC = USART_CMODE_MSPI_gc; // MasterSPI, UDORD=0, UCPHA=0
Teste mal mit Mode 0.

Falls es immer noch nicht funktioniert, könnte ich meinen Code für dein Board anpassen, falls du Schwierigkeiten damit hast.

Dirk :ciao:
 
Jan,
ach ich sehe du nutzt SS auf Pin4 vom PORTF.
FlashSPI.SS = 4
In Spi_Master_USARTD0_Init wird der Pin von PORTF als Ausgang geschaltet.

Später schaltest du den Pin mit Position SS_bp, das ist eine Definition von den SPI Modulen.
SS_bp ist auch 4, soweit ich weiss. Muss es auch, sonst klappt dein Code nicht. Das ist also so in Ordnung, ist allerdings auch eine mögliche Fehlerquelle.


Ich habe mit dem Oszi. alle Pins durch, die sehen alle soweit gut aus und zappeln so wie ich das will, bis auf MISO halt. Was mir noch aufgefallen ist im Gegensatz zu deinem Code, dass ich den PullUp für MISO eingeschaltet hatte, ist das tragisch? Könnte das eine Fehlerquelle sein? Wenn die Hardware vom Slave das nicht mag?
 
dass ich den PullUp für MISO eingeschaltet hatte, ist das tragisch? Könnte das eine Fehlerquelle sein? Wenn die Hardware vom Slave das nicht mag?
Ich denke das dürfte nichts ausmachen. Ist eventuell dann sinnvoll, wenn der Slave entfernbar ist (SD Karte zum Beispiel), ich würde es hier mal abschalten bzw. erst gar nicht aktivieren.

Teste mal mit SPI Mode 0.
 
@LotadaC Du Nachteule :p

@Dirk
Habe den Code jetzt auf mein Board angepasst und muss feststellen, dass es nach wie vor nicht klappt. MISO zappelt kein bisschen, bis auf den Unterschied das MISO jetzt ganze Zeit auf Low liegt.



CodeBox C
void dataflash_init (void)
{
   //PORTF.OUTSET = (1<<SPI_SS_bp);  // 1: DF_CS_
   
   PORTD.DIRSET = (1<<SPI_MOSI_bp) | (1<<SPI_SCK_bp);  // OUTPUT: DF_CS_, DF_MOSI, DF_SCK
   PORTF.DIRSET = (1<<SPI_SS_bp); // SlaveSelect

   USARTD0.CTRLA = 0;
   USARTD0.CTRLC = USART_CMODE_MSPI_gc;  // MasterSPI, UDORD=0, UCPHA=0
   
   // Condition: fboud = fperi / 2
   // fbout = fperi / (2 * (BSEL+1))
   // 16MBit/s, fperi = 32MHz
   USARTD0.BAUDCTRLA                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    = 0; // BSEL
   USARTD0.BAUDCTRLB = 0; // SCALE, BSEL
   
   USARTD0.CTRLB = USART_RXEN_bm | USART_TXEN_bm;
}

uint8_t DF_SPI_RW(uint8_t data_out)
{
   while((USARTD0.STATUS & USART_DREIF_bm) == 0);  // Warte bis DREIF=1 ist (=Transmit Buffer empty)
   USARTD0.DATA = data_out;                        // Daten senden
   
   while ((USARTD0.STATUS & USART_RXCIF_bm) == 0); // Warte bis RXCIF=1 ist (=Data in Receive Buffer)
   return USARTD0.DATA;
}

uint16_t Read_DF_status (void)
{
   uint16_t result;
   
   PORTF.OUTCLR = 1<<4;
   
   DF_SPI_RW(0xD7);
   result = DF_SPI_RW(0x00);
   result |= (DF_SPI_RW(0x00)<<8);
   
   PORTF.OUTSET = 1<<4;
   
   return result;
}
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)