SPI mit Xmega - Senden funktioniert, empfangen nicht

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    Aufgrund technischer Veränderungen ist der Mailverkehr innerhalb des Forums (Private Nachrichten) nur noch eingeschränkt möglich. Die Einschränkung ist notwendig, um zusätzliche Betriebskosten für das Forum zu vermeiden. Näheres zu den Hintergründen im Thread "Aktuelles zum Forum".Wir bitten um Verständnis.

    Hinweis kann nach Kenntnisnahme deaktiviert werden!

    • SPI mit Xmega - Senden funktioniert, empfangen nicht

      Hallo Forum,

      ich verwende das XPlain-Board mit dem ATxMega 128A1 und möchte per SPI mit einem anderen µC kommunizieren.

      Source Code

      1. 'SPI Port F
      2. Config Portf.0 = Input : Int_spi_f Alias Pinf.0 'INT_SPI_F
      3. Config Portf.4 = Output: Cs_f Alias Portf.4 'CS_SPI
      4. Config Portf.5 = Output 'MOSI
      5. Config Portf.6 = Input : Portf_pin6ctrl = &B00_011_000 'MISO, PullUp enabled
      6. Config Portf.7 = Output 'SCK_SPI
      7. 'config SPI on PORTF
      8. Spif_ctrl = &B01010010 'SPI clock double no, SPI enable, SPI master
      9. 'send to SPI
      10. Cs_f = 0
      11. Spif_data = &HAA
      12. Do : Loop Until Spif_status.7 = 1
      13. Cs_f = 1
      14. 'read from SPI
      15. Cs_f = 0 'Chipselect auf Low ziehen
      16. Spif_data = Spi_read 'zu lesende Adresse festlegen
      17. Do : Loop Until Spif_status.7 = 1
      18. Data_in = Spif_data 'Datenbyte auslesen
      19. Do : Loop Until Spif_status.7 = 1
      20. Cs_f = 1
      Display All

      Das Senden des Datenbyte &HAA (vgl. Zeile 11 ff) funktioniert.
      Das Auslesen des Datenbytes (vgl. Zeile 18 ff) funktioniert nicht.
      Nach dem Senden des Adressbytes wird kein weiterer Takt vom µC an SCK erzeugt, so dass das zu lesende Datenbyte nicht ausgegeben wird und das Programm in der Do:LOOP hängt.
      Lege ich nach dem Senden des Adressbytes manuell einen Takt an SCK an, wird an MISO das zu lesende Byte richtig ausgegeben (mit Oszilloskop geprüft).

      Wie lautet die Richtige Syntax in Bascom für das Auslesen via SPI ?

      Vielen Dank, Dani
      Wir können das so machen aber dann funktioniert es halt nicht ...
    • Ich versuche mein Anliegen nochmal anders zu schildern:

      Ich möchte ein Datenbyte per SPI von einem externen µC abrufen.

      Dazu sendet der Master per SPI ein Datenbyte an den externen µC welches festlegt welches Byte abgerufen werden soll (vl. Zeile 20 ff).
      Danach muss der Master weiter ein Clocksignal an den externen µC senden, damit dieser das Datenbyte an der MISO Leitung ausgeben kann.
      Wenn das Byte empfangen wurde sollte dieses im Register "spif_data" des xMega stehen und der xMega das Bit IF setzen.

      Das Problem:
      Nach dem Senden des Adressbytes sendet der xMega kein Clocksignal mehr so dass der externe µC auch kein Byte ausgeben kann.

      Bei den AtMega konnte mit "SPIIN var,1" z.B. ein Byte gelesen werden.
      Ich suche jetzt den passenden Befehl bzw. Syntax für den xMega.
      Wir können das so machen aber dann funktioniert es halt nicht ...
    • @ Michael

      Ich bin momentan bei 1600 Zeilen Code, alles zu posten wäre sicher zu viel.
      Deshalb hatte ich nur den SPI Teil gepostet.

      Eine Verständnissfrage zu SPI beim xMega.
      Wenn ich das Datenblatt richtig interpretiere gibt es für SPI nur einen Interruptvector und die 4 Register CTRL, INTCTRL, STATUS, DATA.
      Mit CTRL wird SPI konfiguriert und initialisiert.
      Mit INTCTRL wird der Level des IRQ festgelegt.
      In STATUS wird BIT 7 gesetzt wenn alle Bits aus dem DATA register per SPI ausgegeben bzw. empfangen wurden. In diesem Fall wird auch der IQR ausgelöst.

      Wenn ich jetzt per "SPIF_DATA = var" ein Byte in das Register DATA schreibe, steuert der xMega die CS, SCK und MOSI PINs an und shiftet das Byte per SPI an den externen µC.
      Dementsprechend war ich der Meinung, das mit "var = SPIF_DATA" der xMega solange ein SCK sendet bis der externe µC per MISO alle 8 Bit in das DATA Register geschoben hat.
      Aber genau das funktioniert nicht. Der xMega sendet kein SCK. Wenn ich manuell ein Clocksignal an SCK lege schiftet der externe µC die 8 Bits an den xMega.

      Deshalb meine Frage: ist, unabhängig vom Programmcode, diese Überlegung prinzipiell richtig?
      Wir können das so machen aber dann funktioniert es halt nicht ...
    • kleine Ausschnitte aus dem SUSI Projekt:

      BASCOM Source Code

      1. Config Spic = Hard , Master = Yes , Mode = 0 , Clockdiv = Clk2 , Data_order = Msb , Ss = None
      2. Open "SPIC" For Binary As #15
      3. Spiinit
      4. '-------------------------------------------------------------------------------
      5. ' Write Wiznet Base Register Adress Data
      6. '-------------------------------------------------------------------------------
      7. Sub Wiz_write(byval Address_a As Word , Byval Data_a As Byte)
      8. Adres16 = Address_a
      9. Call W5100_spi_cs(1)
      10. #if _xmega = 1
      11. Print #15 , Adres16_h
      12. Print #15 , Adres16_l
      13. Print #15 , W5100_opcode_write
      14. Print #15 , &H01
      15. Print #15 , Data_a , 1
      16. #else
      17. Spiout Adres16_h , 1
      18. Spiout Adres16_l , 1
      19. Adres16_l = W5100_opcode_write
      20. Spiout Adres16_l , 1
      21. Adres16_l =&H01
      22. Spiout Adres16_l , 1
      23. Spiout Data_a , 1
      24. #endif
      25. Call W5100_spi_cs(0)
      26. End Sub
      27. '-------------------------------------------------------------------------------
      28. ' Read Wiznet Base Register Adress Data
      29. '-------------------------------------------------------------------------------
      30. Function Wiz_read(byval A As Word) As Byte
      31. Adres16 = A
      32. Transmit_len = 1
      33. Reset Transmit_len.15
      34. Call W5100_spi_cs(1)
      35. #if _xmega = 1
      36. Print #15 , Adres16_h
      37. Print #15 , Adres16_l
      38. Print #15 , W5100_opcode_read
      39. Print #15 , &H01
      40. Input #15 , Adres16_l
      41. #else
      42. Spiout Adres16_h , 1
      43. Spiout Adres16_l , 1
      44. Adres16_l = W5100_opcode_read
      45. Spiout Adres16_l , 1
      46. Adres16_l = &H01
      47. Spiout Adres16_l , 1
      48. Spiin Adres16_l , 1
      49. #endif
      50. Call W5100_spi_cs(0)
      51. Wiz_read = Adres16_l
      52. End Function
      Display All
      Code first, think later - Natural programmer :D
    • @ SIX1

      Dankeschön, genau das habe ich gesucht.
      Print # und Input # wäre heute mein nächster Versuch gewesen.

      Ich möchte aber auch verstehen was da genau im Hintergrund passiert.

      Microchip beschreibt das SPI im xMega wie folgt:


      Microchip wrote:

      General Operation

      The master always initiates transmission. The slave simply has to wait for its SS line to be asserted and the SCLK to appear, or prompt the master using other I/O. To initiate transmission, the SS line for the respective slave device must be driven low and a data byte must be placed in the master's DATA register. As soon as a byte is written to the DATA register, the SCLK will start and data will simultaneously start shifting out on the MOSI line and in on the MISO line. Xmega devices use a single DATA register for transmit and receive. Data gets shifted in/out one bit at a time until all 8-bits have been shifted. Once all 8-bits have been shifted, the SPI Interrupt Flag (IF) will be set. The user must make sure this flag is set before reading data from the buffer, or writing new data to the buffer. This flag can be used to trigger an interrupt, or the flag can be used in a polling method to halt program execution until transmission is complete.
      Ich verstehe das so:

      Damit der Slave ein Byte auf der MISO-Line "senden" kann muss der Master zwangsläufig irgend ein Byte an den slave senden.
      Dieser shiftet dann "sein" Byte gleichzeitig in das DATA Register. Anschließend kann das Byte das vom Slave "gesendet" wurde aus dem DATA Register augelesen werden.
      Wichtig ist dann nur, dass das "irgend ein Byte" keine Funktion im Slave hat ...

      Wie wird das mit dem "input#" Befehl umgesetzt?
      Wird in diesem Fall auch ein Byte an den externen µC gesendet?
      Wir können das so machen aber dann funktioniert es halt nicht ...
    • @tschoeatsch

      Dankeschön, hatte ich aber schon gelesen.
      Ich dachte nur das es sich ausschließlich auf den ATMega und nicht die xMega bezieht. Dieser unterstützt ja fullduplex SPI.


      mcselec wrote:

      That means that the master has to send data to the slave to read data from the slave.
      Das bestätigt meine Vermutung.
      Bleibt die Frage welches Byte sendet der Master bei "input #" an den Slave um diesen zur Herausgabe von seinem Datenbyte zu bewegen.
      Ich werde das heute mit dem Logicanalyzer prüfen ...

      Mit "SPIIN var, 5" konnte man ja festlegen das z.B. 5 Byte gelesen werden.
      Das dürfte dann mit "INPUT #" nicht mehr funktionieren?
      Wir können das so machen aber dann funktioniert es halt nicht ...
    • Ohne jetzt wirklich Ahnung zu haben, in der Hilfe finde ich unter input:
      SPI
      With an optional parameter you can provide how many bytes must be received. You must use a semicolon (;) to specify this parameter. This because the comma (,) is used to receive multiple variables.
      Dim Tmparray(5) As Byte, Spi_send_byte As Byte , W as Word
      Input #12 , Spi_receive_byte ; 1 ' READ 1 byte
      Input #12 , Tmparray(1) ; 1 , Tmparray(2) ; B ' read 1 byte and 'b' bytes starting at element 2
      und daraus schließe ich, man kann gleich mehrere bytes einlesen.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Dankeschön an alle die etwas dazu geschrieben haben.

      Trotz durchlesen der Datenblätter und Posts sieht man manchmal den Wald vor lauter Bäumen nicht ...

      Ich habe es jetzt wie folgt gelöst:

      Source Code

      1. Spif_data = &H00 'Dummybyte senden
      2. Do : Loop Until Spif_status.7 = 1 'warten bis alle Bits gesendet wurden
      3. rx_byte = Spif_data '"empfangenes Byte" auslesen
      Input # "sendet" auch ein &H00 an den slave ...
      Wir können das so machen aber dann funktioniert es halt nicht ...