Hallo, ich kommuniziere per SPI zwischen einem STM und einem Atmel. Der Atmel ist hier der Master und würde laut Datenblatt einen SPI-Takt bis zu 66MHz schaffen. Die Daten werden bei steigender Flanke am clock übernommen. STM: STM32F105RC; core-clock = 72MHz Atmel: AT32UC3A0512 www.atmel.com/Images/doc32058.pdf core-clock = 66MHz Nun ist es in meinem Fall so, dass meine Kommunikation nur bis ca. 20MHz funktioniert. Bei höheren Frequenzen „empfängt“ der Atmel nur noch falsche Werte. In die andere Richtung ist es allerdings so, dass der STM (=slave) immer das richtige empfängt. Ich konnte mal ein Screenshot vom Oszi machen. Hier legt der Slave den Wert 0x34 bei einem Takt von 22MHz auf die MISO-Leitung. Der Atmel glaubt in diesem Fall jedoch ein 0x1E erkenne zu müssen. So wie ich das sehe, sollten die MISO-Werte aber zur richtigen Zeit anliegen und ich verstehe gar nicht, wie der Atmel hier auf 0x1E kommt. Hat jemand einen Tipp wie ich bei der Fehlersuche weiter vorgehen sollte? Zum Oszi: Es hat eine Auflösung von 500MHz bzw. 2,5GS/s
Was soll das denn für ein Dateutyp im Anhang sein?
Deine Hilfslinien sind aber alle bei einem unterschiedlichen Spannungspegel auf CLK eingezeichnet. Wenn ich die roten Linien alle etwas nach links verschiebe komme ich auf 0x1E.
natürlich noch der Code (ich verwende Atmels Framework ASF und freeRTOS):
1 | void spiInit(void) |
2 | {
|
3 | spiInitPins(); |
4 | spiInitModule(); |
5 | spiDmaInit(); |
6 | }
|
7 | |
8 | |
9 | void spiInitModule(void) |
10 | {
|
11 | struct spi_device spi_dev_conf_cam1 = { |
12 | .id = SPI_CS_CAM1 }; |
13 | |
14 | spi_master_init(&AVR32_SPI1); |
15 | spi_master_setup_device(&AVR32_SPI1, &spi_dev_conf_cam1, SPI_MODE_0, \ |
16 | 22000000, 1); |
17 | spi_enable(&AVR32_SPI1); |
18 | }
|
19 | |
20 | void spiDmaInit(void) |
21 | {
|
22 | /* PDCA channel options */
|
23 | static const pdca_channel_options_t PDCA_OPTIONS_FOR_TRANSFER = |
24 | {
|
25 | .addr = NULL, // memory address |
26 | .pid = AVR32_PDCA_PID_SPI1_TX, // select peripheral/SPI tx channel |
27 | .size = 0, // transfer counter |
28 | .r_addr = NULL, // next memory address |
29 | .r_size = 0, // next transfer counter |
30 | .transfer_size = PDCA_TRANSFER_SIZE_BYTE// select size of the transfer |
31 | };
|
32 | static const pdca_channel_options_t PDCA_OPTIONS_FOR_RECIEVE = |
33 | {
|
34 | .addr = NULL, // memory address |
35 | .pid = AVR32_PDCA_PID_SPI1_RX, // select peripheral/SPI rx channel |
36 | .size = 0, // transfer counter |
37 | .r_addr = NULL, // next memory address |
38 | .r_size = 0, // next transfer counter |
39 | .transfer_size = PDCA_TRANSFER_SIZE_BYTE// select size of the transfer |
40 | };
|
41 | |
42 | /* Disable all interrupts */
|
43 | Disable_global_interrupt(); |
44 | |
45 | INTC_register_interrupt( (__int_handler) &pdca_int_handler, \ |
46 | AVR32_PDCA_IRQ_0, AVR32_INTC_INT0); |
47 | INTC_register_interrupt( (__int_handler) &pdca_int_handler, \ |
48 | AVR32_PDCA_IRQ_1, AVR32_INTC_INT1); |
49 | |
50 | /* First disable all interrupts */
|
51 | SENSOR_SPI->idr = 0xFFFF; |
52 | |
53 | /* Enable SPI interrupt */
|
54 | SENSOR_SPI->IER.nssr = 1; |
55 | |
56 | /* Init PDCA channel with the pdca_options */
|
57 | pdca_init_channel(SPI1_PDCA_CHANNEL_TX, &PDCA_OPTIONS_FOR_TRANSFER); |
58 | pdca_init_channel(SPI1_PDCA_CHANNEL_RX, &PDCA_OPTIONS_FOR_RECIEVE); |
59 | |
60 | /* Enable all interrupts */
|
61 | Enable_global_interrupt(); |
62 | |
63 | /* Enable now the transfer */
|
64 | pdca_enable(SPI1_PDCA_CHANNEL_RX); |
65 | pdca_enable(SPI1_PDCA_CHANNEL_TX); |
66 | }
|
67 | |
68 | uint8_t spiRWCam1(uint8_t dataTx) |
69 | {
|
70 | uint16_t dataRx = 0; |
71 | // select SPI chip.
|
72 | spi_selectChip(SENSOR_SPI, SPI_CS_CAM1); |
73 | // Send the Status Register Read command.
|
74 | spi_write(SENSOR_SPI, (uint16_t)dataTx); |
75 | // Unselect SPI chip.
|
76 | spi_unselectChip(SENSOR_SPI, SPI_CS_CAM1); |
77 | |
78 | spi_read(SENSOR_SPI, &dataRx); |
79 | return (uint8_t)dataRx; |
80 | }
|
Blitzbirne schrieb: > Deine Hilfslinien sind aber alle bei einem unterschiedlichen > Spannungspegel auf CLK eingezeichnet. > Wenn ich die roten Linien alle etwas nach links verschiebe komme ich auf > 0x1E. Hmmm... ich fand es auch schwierig die tatsächlich richtige Position der Linien zu bestimmen, da ich ja nicht weiß wann der Master der Meinung ist die Daten übernehmen zu müssen. Ich finde auch, dass die Flanken recht unregelmäßig ausschauen. Das mit dem nach links verschieben ist schon mal ein super Hinweis. Danke schön (auch wenn ich noch nicht weiß was ich nun ändern könnte).
Die Funktion mit der ich die Daten per DMA in einen Puffer einlese habe ich noch vergessen:
1 | void spiRBuffCam(volatile uint8_t *buffAddr, uint32_t sizeOfBuff) |
2 | {
|
3 | spi_selectChip(&AVR32_SPI1, SPI_CS_CAM1); |
4 | |
5 | portENTER_CRITICAL(); |
6 | {
|
7 | pdca_enable_interrupt_transfer_complete(SPI1_PDCA_CHANNEL_RX); |
8 | /* load PDCA */
|
9 | pdca_load_channel( SPI1_PDCA_CHANNEL_RX, (void *)buffAddr, sizeOfBuff); |
10 | /* enable the PDCA Rx channel first then the Tx channel */
|
11 | pdca_enable(SPI1_PDCA_CHANNEL_RX); |
12 | /* send dummy data from the user page in flash */
|
13 | pdca_load_channel(SPI1_PDCA_CHANNEL_TX, (void *)dummy_0xff_filledBlockAtFlash, sizeOfBuff); |
14 | //pdca_enable(SPI1_PDCA_CHANNEL_TX); //already enabled at init
|
15 | }
|
16 | portEXIT_CRITICAL(); |
17 | }
|
Ich stelle allerdings gerade (leider erst jetzt) fest, dass ich mit der Funktion spiRWCam1() die Daten sogar bei 30MHz auslesen kann. Mein Problem ist dann also nur dann, wenn ich per DMA auslesen möchte. (also mit der Funktion: spiRBuffCam())
STM32 Reference: SPI Slave Frequency <= PCLK/2. Mehr als 36MHz sind also sowieso nicht drin. Bei den SPIs am APB1 mit halbem PCLK <= 18MHz. Wie sieht die Kabelei aus? Versorgungsspannung? SPI Pinmode vom STM32?
spi schrieb: > Nochmal das Bild im Anhang... Bei Frequenzen in diesem Bereich solltest du auf die Massekabel der Tastköpfe verzichten und mit Massefeder an der Tastkopfspitze arbeiten: https://www.mikrocontroller.net/attachment/27280/groundspring.png Mit Massekabel kann ein steilflankiges 20MHz Rechteck auf dem Oszi nämlich auch so aussehen: https://www.mikrocontroller.net/attachment/27258/74AC-Ausgang.PNG wobei man da nicht das Signal misst, sondern Artefakte im Tastkopf.
A. K. schrieb: > Massefeder an der Tastkopfspitze Was es alles gibt... Hardware und Messtechnik sind leider nicht meine Stärke. Habe auch ein wenig gebraucht um zu kapieren wo/wie die Massefeder an den Tastkopf angeschlossen werden soll. Hier mal ein Bild, falls sich jemand anderes mal die gleiche Frage stellen sollte: http://images.vogel.de/vogelonline/bdb/464000/464042/25.jpg Neue Messungen sind zur Zeit leider nicht möglich, da ich kein eigenes Oszi besitze. A. K. schrieb: > Mehr als 36MHz sind also sowieso nicht drin. Ja, 36MHz wären mein Ziel. Mittlerweile habe ich herausgefunden, dass schon ein delay von einem einzigen Takt zwischen den einzelnen Bytes ausreicht um die Übertragung mit 32MHz laufen zu lassen. Atmel bietet diese Möglichkeit netter weise per Konfiguration der Schnittstelle an:
1 | //! Default Config Spi Master Delay BCT ( delay between consecutive transfers)
|
2 | #define CONFIG_SPI_MASTER_DELAY_BCT 1
|
A. K. schrieb: > Wie sieht die Kabelei aus? Versorgungsspannung? SPI Pinmode vom STM32?
1 | /* ___ SPI1 configuration ________________________________________________*/
|
2 | SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; |
3 | SPI_InitStructure.SPI_Mode = SPI_Mode_Slave; |
4 | SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; |
5 | SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; |
6 | SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; |
7 | SPI_InitStructure.SPI_NSS = SPI_NSS_Hard; |
8 | SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; |
9 | SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; |
10 | SPI_InitStructure.SPI_CRCPolynomial = 7; |
11 | SPI_Init(SPI1, &SPI_InitStructure); |
Das mit der Kabelei könnte vielleicht wirklich der Grund sein, warum ich noch nicht ganz auf die 36MHz komme. Ich habe mal versucht den Aufbau meiner beiden Platinen/MCU's auf einer Skizze darzustellen.
spi schrieb: > Nochmal das Bild im Anhang... Bei solchen Signale kann man die Fehler gut verstehen. Grundsätzlich ist SPI eine digitale Signalübertragung und so sollten die Signale dann auch aussehen, bevor man erwarten kann, dass die Gegenstelle die richtig empfangen kann. Entweder liegt das an der Messtechnik oder die Signale sind tatsächlich so unsauber. Bevor die nicht ordentlich sind, ist da ohne Signalregenerierung nicht mehr zu erwarten.
spi schrieb: > Zum Oszi: Es hat eine Auflösung von 500MHz bzw. 2,5GS/s Was du da angibst, ist vermutlich die Analogbandbreite und die Abtastfrequenz. Hast du einen 1:10 Tastkopf verwendet? Welche Impedanz und Länge hat dein Kabel? Wie sehen Treiberimpedanz und Empfängerimpedanz/Leitungsabschluß aus?
spi schrieb: > Ich konnte mal ein Screenshot vom Oszi machen. Da sieht es für mich so aus, wie wenn sich die Daten annähernd gleichzeitig mit den steigenden Taktflanken, die an sich auch nur rudimentär und nach Erklärung sichtbar sind! Das wäre dann aber der falsche Zeitpunkt zur Abtastung. Besser wäre hier die fallende Flanke. Verwendest du den falschen SPI Modus? BTW: Wenn das Signal am uC-Pin wirklich so aussieht, dann gibt das nie eine sichere Übertragung.
Hallo, Bedenke auch, dass die Kabellaufzeit eine Rolle spielt. Bei 50MHz sind deine Zeitreserven sehr gering (10ns): die Taktflanke muss zum ST hin und die Datenflanke zum ATMEL zurück - bei 6ns/m geht das schon theoretisch nur bis weniger als 1m. Praktisch eher noch weniger, weil der ST auch noch Zeit braucht, seine Daten zu setzen. Probleme können also schon früher auftreten, z.B. bei 20cm. Schau dir mal die Setup und Holdzeiten im Datenblatt an und rechne dein Timing mal durch - mit Kabellaufzeit. Der ST hat dagegen nie ein Problem: der bekommt Takt und Daten gleichzeitig. Abhilfe: Frequenz runter, Kabel kürzer oder asynchrone Kommunikation.
spi schrieb: > Das mit der Kabelei könnte vielleicht wirklich der Grund sein, Die Länge der Kabel ist extrem wichtig, wenn du sie nicht passend mit Treiber versehen und abgeschlossen hast. Jenseitig einiger zig cm ist das nötig und angesichts RJ45 gehe ich davon aus, dass du weit jenseits davon liegst. Siehe Wellenwiderstand. Auf die Laufzeitfrage wurde ja schon hingewiesen. Mögliche Lösung wären 2 SPI-Master. Einer für AVR32=>STM32 und einer andersrum, jeweils unidirektional betrieben. Dann treten keine Laufzeiteffekte auf. Blöderweise gibts beim STM32 wohl nur ein SPI mit 36MHz, die anderen nur mit 18MHz. Oder Ethernet. > [c]/* _ SPI1 configuration Sorry, ich meinte die GPIO Pinkonfiguration der SPI-Pins. Die Grenzfrequenz der STM32 Pins hängt davon ab - und von der Höhe der Versorgungsspannung. Daher die Frage.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.

