Forum: Mikrocontroller und Digitale Elektronik SPI - Probleme mit der MISO Leitung


von Felix D. (skyfox) Benutzerseite


Lesenswert?

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

von Wolfgang (Gast)


Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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.

von Felix D: (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Rainer U. (r-u)


Lesenswert?

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.

von Felix D. (skyfox) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von Meckerziege (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.