Hallo zusammen, ich habe ein kleines Problem mit SPI und ich hoffe Ihr könnt mir helfen. Es geht um die Kommunikation eines AVR32 (AT32uc3c1512) und eines SPI-Slaves (ET1200 (EtherCAT)). Der AVR32 sendet die Addresse des zu lesenden Registers (2 Byte) aber danach passiert nichts mehr. Ich schreibe ein DUMMY-Byte aber das kommt nicht an. Wähle ich ein anderes CS sendet der AVR32 zwei Mal hintereinander. Am Logic analyzer sehe ich, dass der Slave die MISO-Leitung unten hält. Das steht auch so im Datenblatt und ist nicht zu ändern. Nun meine Frage: Kann ich dem AVR32 irgendwie abgewöhnen auf de MISO-Leitung zu lauschen? Würde es ausreichen wenn ich einfach das DUMMY-Byte in das TDR-Register schreibe? Implementiert habe ich das ganze wie hier beschrieben http://asf.atmel.com/docs/latest/common.components.memory.sd_mmc.unit_tests.evk1100/html/avr32_drivers_spi_quick_start.html beschrieben, nur halt mit 16 statt 8 Bit. In der while()-Schleife nach dem zweiten spi_put(...) bleibt er hängen. Auf der Leitung kommt nichts an. Habt Ihr einen Tipp für mich? Gruß Felix
Felix D. schrieb: > Kann ich dem AVR32 irgendwie abgewöhnen auf de MISO-Leitung zu lauschen? Nein. Bei SPI laufen die Daten immer auf beiden Datenleitungen synchron.
Felix D. schrieb: > Nun meine Frage: > Kann ich dem AVR32 irgendwie abgewöhnen auf de MISO-Leitung zu lauschen? Wozu sollte das gut sein? Dir ist das grundlegende Konzept des SPI mit den gekoppelten Schieberegistern bekannt? Es wird immer gleichzeitig gesendet und empfangen, mit jedem SCLK Takt ein Bit: http://www.lothar-miller.de/s9y/categories/17-SPI Ein Slave "sendet2 nicht von sich aus. Der Master muss vom Slave die Daten "abholen". Wenn du also von deinem Slave etwas willst, dann muss der SPI Takt weiterlaufen. Das wird gemacht, indem irgendwas vom Master zum Slave gesendet wird... Allgemein: lies deine Frage mal so, wie wenn du von deinem Problem absolut NICHTS wüsstest. So geht es uns: wir kennen dein Problem nicht. Wenn dir dann klar wird, was gemeint ist, dann drücke auf den "Absenden"-Knopf. Wenn nicht, dann füge die nötige Information (Bilder vom LA, Code, Schaltplan,...) dazu.
Hallo, danke für die Antworten und entschuldigt bitte meine missverständliche Ausdrucksweise. War spät gestern. Da, die grundlegende Funktionsweise von SPI ist bekannt. Mein Problem ist halt, dass der AVR32 nicht weiter taktet. Ich habe mal Screenshots vom LA hinzugefügt. Ich hoffe Ihr seht was ich meine. Bei dem zweiten Screenshot ist ein anderes CS ausgewählt. Der verwendete Code ist der aus dem Link im ersten Post mit marginalen Änderungen auf das verwendete Pinout. Ich habe das Ganze um eine Statusfunktion erweitert, damit ich sehen kann wo es hängt. Alle Chips, und auch der LA sprechen SPI-Mode 3.
1 | extern "C"{ |
2 | #include "spi.h" |
3 | #include "gpio.h" |
4 | #include "sysclk.h" |
5 | #include "scif_uc3c.h" |
6 | }
|
7 | |
8 | /* Connection of the AUDIO sensor */
|
9 | #define EXAMPLE_SPI_INSTANCE 1
|
10 | #define EXAMPLE_SPI1 (&AVR32_SPI1)
|
11 | #define EXAMPLE_SPI_MISO_PIN AVR32_SPI1_MISO_PIN
|
12 | #define EXAMPLE_SPI_MISO_FUNCTION AVR32_SPI1_MISO_FUNCTION
|
13 | #define EXAMPLE_SPI_MOSI_PIN AVR32_SPI1_MOSI_PIN
|
14 | #define EXAMPLE_SPI_MOSI_FUNCTION AVR32_SPI1_MOSI_FUNCTION
|
15 | #define EXAMPLE_SPI_CLK AVR32_SPI1_SCK_PIN
|
16 | #define EXAMPLE_SPI_CLK_FUNCTION AVR32_SPI1_SCK_FUNCTION
|
17 | #define EXAMPLE_SPI_NPCS_0_PIN AVR32_SPI1_NPCS_0_1_PIN
|
18 | #define EXAMPLE_SPI_NPCS_0_FUNCTION AVR32_SPI1_NPCS_0_1_FUNCTION
|
19 | #define EXAMPLE_SPI_NPCS_1_PIN AVR32_SPI1_NPCS_1_1_PIN
|
20 | #define EXAMPLE_SPI_NPCS_1_FUNCTION AVR32_SPI1_NPCS_1_1_FUNCTION
|
21 | #define EXAMPLE_SPI_PRESCALER_CLOCK FOSC0 / 2
|
22 | |
23 | #define EXAMPLE_SPI_CHIP_NUMBER 1
|
24 | #define EXAMPLE_SPI_BAUDRATE 100000
|
25 | #define EXAMPLE_SPI_BITS_PER_CHAR 16
|
26 | #define EXAMPLE_SPI_CLK_PULSE_DELAY 32
|
27 | #define EXAMPLE_SPI_TRANSFER_DELAY 16
|
28 | #define EXAMPLE_SPI_STAY_ACTIVE 1
|
29 | #define EXAMPLE_SPI_MODE SPI_MODE_3
|
30 | #define EXAMPLE_SPI_MODE_FAULT_DETECT 0
|
31 | #define EXAMPLE_SPI_ET1200_SLAVE 0
|
32 | |
33 | #define LED_FAULT AVR32_PIN_PB03
|
34 | #define LED_OK AVR32_PIN_PB02
|
35 | |
36 | static void init_gclk(void) |
37 | {
|
38 | // Setup Sampling Rate
|
39 | // Sampling Rate = (115200/100) = 1152Hz
|
40 | // Setup the generic clock for EVENT
|
41 | scif_gc_setup(AVR32_SCIF_GCLK_GCLK2_EVENT, |
42 | scif_gcctrl_oscsel_t{SCIF_GCCTRL_SLOWCLOCK}, |
43 | AVR32_SCIF_GC_DIV_CLOCK, |
44 | 100); |
45 | |
46 | // Now enable the generic clock
|
47 | scif_gc_enable(AVR32_SCIF_GCLK_GCLK2_EVENT); |
48 | }
|
49 | |
50 | const spi_options_t spi1_options { |
51 | EXAMPLE_SPI_CHIP_NUMBER, |
52 | EXAMPLE_SPI_BAUDRATE, |
53 | EXAMPLE_SPI_BITS_PER_CHAR, |
54 | EXAMPLE_SPI_CLK_PULSE_DELAY, |
55 | EXAMPLE_SPI_TRANSFER_DELAY, |
56 | EXAMPLE_SPI_STAY_ACTIVE, |
57 | EXAMPLE_SPI_MODE, |
58 | EXAMPLE_SPI_MODE_FAULT_DETECT
|
59 | };
|
60 | |
61 | uint16_t data[] = { |
62 | 0x0000
|
63 | };
|
64 | |
65 | uint16_t address1 = { |
66 | 0b0000101000000010 // 0x0a02 |
67 | };
|
68 | |
69 | uint16_t address2 = { |
70 | 0x0000
|
71 | };
|
72 | |
73 | |
74 | |
75 | |
76 | void enable_gpios(void) { |
77 | gpio_disable_pin_pull_up(LED_OK); |
78 | gpio_enable_gpio_pin(LED_OK); |
79 | gpio_set_pin_low(LED_OK); |
80 | gpio_disable_pin_pull_up(LED_FAULT); |
81 | gpio_enable_gpio_pin(LED_FAULT); |
82 | gpio_set_pin_low(LED_FAULT); |
83 | }
|
84 | |
85 | void set_fl(void) { |
86 | gpio_enable_pin_pull_up(LED_FAULT); |
87 | gpio_set_pin_high(LED_FAULT); |
88 | }
|
89 | |
90 | void set_ol(void) { |
91 | gpio_enable_pin_pull_up(LED_OK); |
92 | gpio_set_pin_high(LED_OK); |
93 | }
|
94 | |
95 | void clear_fl(void) { |
96 | gpio_disable_pin_pull_up(LED_FAULT); |
97 | gpio_set_pin_low(LED_FAULT); |
98 | }
|
99 | |
100 | void clear_ol(void) { |
101 | gpio_disable_pin_pull_up(LED_OK); |
102 | gpio_set_pin_low(LED_OK); |
103 | }
|
104 | |
105 | void set_status(spi_status_t pStatus) { |
106 | clear_ol(); |
107 | clear_fl(); |
108 | switch (pStatus) { |
109 | case SPI_OK: |
110 | set_ol(); |
111 | break; |
112 | case SPI_ERROR: |
113 | set_fl(); |
114 | break; |
115 | case SPI_ERROR_TIMEOUT: |
116 | set_fl(); |
117 | set_ol(); |
118 | break; |
119 | default:
|
120 | break; |
121 | }
|
122 | }
|
123 | |
124 | void spi_init_module(void) |
125 | {
|
126 | spi_status_t status = SPI_ERROR; |
127 | set_status(status); |
128 | status = SPI_OK; |
129 | //Init SPI module as master
|
130 | status = spi_initMaster(EXAMPLE_SPI1,&spi1_options); |
131 | set_status(status); |
132 | //Setup configuration for chip connected to CS1
|
133 | status = spi_setupChipReg(EXAMPLE_SPI1,&spi1_options,sysclk_get_pba_hz()); |
134 | set_status(status); |
135 | //Allow the module to transfer data
|
136 | spi_enable(EXAMPLE_SPI1); |
137 | }
|
138 | |
139 | int main(void) |
140 | {
|
141 | enable_gpios(); |
142 | spi_status_t status = SPI_ERROR; |
143 | set_status(status); |
144 | status = SPI_OK; |
145 | // GPIO pin/SPI-function map
|
146 | gpio_map_t SPI1_GPIO_MAP = { |
147 | {EXAMPLE_SPI_MISO_PIN, EXAMPLE_SPI_MISO_FUNCTION}, |
148 | {EXAMPLE_SPI_MOSI_PIN, EXAMPLE_SPI_MOSI_FUNCTION}, |
149 | {EXAMPLE_SPI_CLK, EXAMPLE_SPI_CLK_FUNCTION}, |
150 | {EXAMPLE_SPI_NPCS_0_PIN, EXAMPLE_SPI_NPCS_0_FUNCTION}, |
151 | {EXAMPLE_SPI_NPCS_1_PIN, EXAMPLE_SPI_NPCS_1_FUNCTION} |
152 | };
|
153 | |
154 | // Initialize the system clocks
|
155 | sysclk_init(); |
156 | |
157 | // Assign and enable GPIO pins to the SPI function
|
158 | gpio_enable_module(SPI1_GPIO_MAP, sizeof(SPI1_GPIO_MAP) / |
159 | sizeof(SPI1_GPIO_MAP[0])); |
160 | |
161 | // Initialize Generic Clock
|
162 | init_gclk(); |
163 | |
164 | spi_init_module(); |
165 | |
166 | status = spi_selectChip(EXAMPLE_SPI1,EXAMPLE_SPI_CHIP_NUMBER); |
167 | //Wait for the transmitter to be ready
|
168 | while(!spi_is_tx_ready(EXAMPLE_SPI1)) {}; |
169 | |
170 | uint16_t tx_data = 0x0a02; |
171 | spi_put(EXAMPLE_SPI1,tx_data); |
172 | |
173 | while(!spi_is_tx_empty(EXAMPLE_SPI1)) {}; |
174 | |
175 | // set_status(SPI_ERROR_TIMEOUT);
|
176 | while(!spi_is_tx_ready(EXAMPLE_SPI1)) {}; |
177 | |
178 | tx_data = 0x0000; |
179 | spi_put(EXAMPLE_SPI1,tx_data); |
180 | set_status(SPI_ERROR); |
181 | while(!spi_is_tx_empty(EXAMPLE_SPI1)) { |
182 | set_status(SPI_ERROR_TIMEOUT); |
183 | };
|
184 | uint16_t rx_data = 0x0000; |
185 | rx_data = spi_get(EXAMPLE_SPI1); |
186 | if(rx_data == 0x1100) { |
187 | set_status(SPI_OK); |
188 | } else { |
189 | set_status(SPI_ERROR); |
190 | }
|
191 | |
192 | spi_unselectChip(EXAMPLE_SPI1,EXAMPLE_SPI_CHIP_NUMBER); |
193 | |
194 | while(true) |
195 | {
|
196 | ;
|
197 | }
|
198 | }
|
In der vorletzten while()-Schleife, also da wo das SPI_ERROR_TIMEOUT gesetzt wird, bleibt er hängen. Das setzen des Status bedeutet bei mir nur, dass meine beiden Status-LEDs beide leuchten. Ich hoffe damit den Problemnebel der Glaskugel ein wenig gelichtet zu haben.
Schreib Dir ein ganz einfaches Programm, dass 3 Bytes in das SPDR schreibt (immer schön auf das SPIF warten zwischendurch). Dann sollte die Clock-Leitung 3x8 = 24 mal zappeln. Wenn nicht, hast Du ein Verständnisproblem. Wenn es klappt, guck was Dien Programm anders macht.
Ich hab's :-) Das Problem saß, wie zu erwarten, wieder zwischen Stuhl und Tastatur. Den define für die Mode fault detection disable habe ich blöde benahmt, es handelt sich ja schließlich um einen disable.
1 | #define EXAMPLE_SPI_MODE_FAULT_DETECT 1
|
brachte das gewünschte Ergebnis. Ich hab's dann auch gleich anders genannt. Vielen Dank an alle die sich darüber Gedanken gemacht haben. Nächstes Mal bemühe ich mich die Fragen von Anfang an präziser zu stellen. Das Bild zeigt, wie es jetzt am LA aussieht. Gruß Felix
Felix D: schrieb: > War spät gestern. Und noch ein Tip. Achte auf die Bildformate: JPEG ist für Photos optimiert. In Graphiken entstehen bei dieser Kompressionsmethode häßliche Artefakte, weil der Algorithmus mit scharfen Linien und harten Kanten soetwas von überhaupt nicht gut zurecht kommt. PNG ist für solche Dinge das Format der Wahl. Und weder die Icons vom Programm, noch die ungenutze schwarze Fläche des Fensters interessieren hier irgend jemand. Fokusiere deine Darstellung auf den wesentlichen Teil. Und längeren Code kann man in einen Anhang packen. So bekommt man vom Scrollen fast wunde Finger.
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.