Hey, ich baue gerade eine Ansteuerung für zwei LCDs aus, die über SPI angesprochen werden. Irgendwie wollte das aber nicht so richtig funktionieren, weshalb ich erstmal eine SPI Dummyschaltung aufgebaut habe zum Testen. Ich benutze das STM32Discovery Board und habe SPI1 und SPI2 direkt miteinander verbunden. Jetzt schicke ich aus beiden SPI Daten raus und schaue nach, ob die auch angekommen sind. Eigentlich ganz simpel, dazu gibt es schließlich auch ein Beispielprogramm in der Firmware Lib. Leider ist es dann doch nicht so einfach, es will bei mir schlichtweg nicht klappen. Beide SPI senden die Daten raus, aber empfangen wird iwie gar nichts. Zig Codevariationen später habe ich mal das Beispiel aus der FW Lib draufgespielt, das läuft natürlich... Kann mir bitte jemand sagen, wo der Fehler liegt? Im Prinzip ist alles genau gleich wie in dem Beispielprogramm, nur das Resultat leider nicht :( Programmablauf: Clock wird auf 24MHz gestellt, alle möglichen IOs initalisiert, dann wird meine SPI_Test() aufgerufen: void SPI_Test(void) { /* 1. SPI1 als Master, SPI2 als Slave initialisieren * 2. Daten von SPI1 zu SPI2 schicken */ /* Schritt 1 */ SPI_InitTypeDef SPIInit1; GPIO_InitTypeDef GPIOInit1; RCC_APB2PeriphClockCmd(LCD_SPI_CLK_GPIO_CLK | LCD_SPI_MISO_GPIO_CLK | LCD_SPI_MOSI_GPIO_CLK | RCC_APB2Periph_AFIO, ENABLE); RCC_APB2PeriphClockCmd(LCD_SPI_CLK, ENABLE); GPIOInit1.GPIO_Pin = LCD_SPI_CLK_PIN; GPIOInit1.GPIO_Speed = GPIO_Speed_50MHz; GPIOInit1.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(LCD_SPI2_CLK_GPIO_PORT, &GPIOInit1); GPIOInit1.GPIO_Pin = LCD_SPI_MISO_PIN; GPIOInit1.GPIO_Mode = GPIO_Mode_IN_FLOATING; //GPIOInit1.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(LCD_SPI2_MISO_GPIO_PORT, &GPIOInit1); GPIOInit1.GPIO_Pin = LCD_SPI_MOSI_PIN; GPIOInit1.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(LCD_SPI_MOSI_GPIO_PORT, &GPIOInit1); SPI_I2S_DeInit(SPI1); SPIInit1.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPIInit1.SPI_Mode = SPI_Mode_Master; SPIInit1.SPI_DataSize = SPI_DataSize_16b; SPIInit1.SPI_CPOL = SPI_CPOL_Low; SPIInit1.SPI_CPHA = SPI_CPHA_2Edge; SPIInit1.SPI_NSS = SPI_NSS_Soft; SPIInit1.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; /* gegebenenfalls anpassen an 72MHz Connectivity Line */ SPIInit1.SPI_FirstBit = SPI_FirstBit_LSB; SPIInit1.SPI_CRCPolynomial = 7; SPI_Init(LCD_SPI, &SPIInit1); /* SPI1 starten */ SPI_Cmd(LCD_SPI, ENABLE); SPI_InitTypeDef SPIInit2; GPIO_InitTypeDef GPIOInit2; RCC_APB2PeriphClockCmd(LCD_SPI2_CLK_GPIO_CLK | LCD_SPI2_MISO_GPIO_CLK | LCD_SPI2_MOSI_GPIO_CLK, ENABLE); RCC_APB1PeriphClockCmd(LCD_SPI2_CLK, ENABLE); GPIOInit2.GPIO_Pin = LCD_SPI2_CLK_PIN; GPIOInit2.GPIO_Speed = GPIO_Speed_50MHz; GPIOInit2.GPIO_Mode = GPIO_Mode_IN_FLOATING; //GPIOInit2.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(LCD_SPI2_CLK_GPIO_PORT, &GPIOInit2); GPIOInit2.GPIO_Pin = LCD_SPI2_MISO_PIN; GPIOInit2.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(LCD_SPI2_MISO_GPIO_PORT, &GPIOInit2); GPIOInit2.GPIO_Pin = LCD_SPI2_MOSI_PIN; GPIOInit2.GPIO_Mode = GPIO_Mode_IN_FLOATING; //GPIOInit2.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(LCD_SPI2_MOSI_GPIO_PORT, &GPIOInit2); SPI_I2S_DeInit(SPI2); SPIInit2.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPIInit2.SPI_Mode = SPI_Mode_Slave; SPIInit2.SPI_DataSize = SPI_DataSize_16b; SPIInit2.SPI_CPOL = SPI_CPOL_Low; SPIInit2.SPI_CPHA = SPI_CPHA_2Edge; SPIInit2.SPI_NSS = SPI_NSS_Soft; SPIInit2.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; /* gegebenenfalls anpassen an 72MHz Connectivity Line */ SPIInit2.SPI_FirstBit = SPI_FirstBit_LSB; SPIInit2.SPI_CRCPolynomial = 7; SPI_Init(LCD_SPI2, &SPIInit2); /* SPI2 starten */ SPI_Cmd(LCD_SPI2, ENABLE); /* Schritt 2*/ uint16_t test=0; uint16_t test2=0; /* SPI senden 0x1111 */ SPI_I2S_SendData(SPI1, 0x1111); SPI_I2S_SendData(SPI2, 0x1111); while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) != RESET) { } while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) != RESET) { } /* Beide LED aus, wenn Daten empfangen */ test = SPI_I2S_ReceiveData(SPI1); if(test==0) { LED_On(LED1); } else { LED_Off(LED1); } test2 = SPI_I2S_ReceiveData(SPI2); if(test2==0) { LED_On(LED2); } else { LED_Off(LED2); } } Code läuft bis zum Ende durch, nur die LEDs bleiben aus. Findet jemand den Fehler? Achso, die ganzen Defines LCD_SPI_PIN_abc sollten stimmen. DEr Übersichtlichkeit halber hier: #define LCD_SPI2 SPI2 #define LCD_SPI2_CLK RCC_APB1Periph_SPI2 #define LCD_SPI2_CLK_PIN GPIO_Pin_13 #define LCD_SPI2_CLK_GPIO_PORT GPIOB #define LCD_SPI2_CLK_GPIO_CLK RCC_APB2Periph_GPIOB #define LCD_SPI2_MISO_PIN GPIO_Pin_14 #define LCD_SPI2_MISO_GPIO_PORT GPIOB #define LCD_SPI2_MISO_GPIO_CLK RCC_APB2Periph_GPIOB #define LCD_SPI2_MOSI_PIN GPIO_Pin_15 #define LCD_SPI2_MOSI_GPIO_PORT GPIOB #define LCD_SPI2_MOSI_GPIO_CLK RCC_APB2Periph_GPIOB #define LCD_SPI SPI1 #define LCD_SPI_CLK RCC_APB2Periph_SPI1 #define LCD_SPI_CLK_PIN GPIO_Pin_5 #define LCD_SPI_CLK_GPIO_PORT GPIOA #define LCD_SPI_CLK_GPIO_CLK RCC_APB2Periph_GPIOA #define LCD_SPI_MISO_PIN GPIO_Pin_6 #define LCD_SPI_MISO_GPIO_PORT GPIOA #define LCD_SPI_MISO_GPIO_CLK RCC_APB2Periph_GPIOA #define LCD_SPI_MOSI_PIN GPIO_Pin_7 #define LCD_SPI_MOSI_GPIO_PORT GPIOA #define LCD_SPI_MOSI_GPIO_CLK RCC_APB2Periph_GPIOA Danke schonmal!
Wenn du zuerst über SPI1 sendest, dann hat der Slave noch nichts im Datenregister. Dann sendest du über SPI2, welcher jedoch auf den Master warten muss. Eventuell spielt die Reihenfolge hier mit.
Ok, ich habe die Reihenfolge gedreht, aber es läuft immer noch nicht :( Das Receive Buffer Flag zeigt immer an, dass der Buffer leer ist von SPI2 (Slave). Wenn ich aber SPI1 als Slave und SPI2 als Master programmiere, dann funktioniert es. Wie kann man das verstehen? Das FW Beispiel läuft einwandfrei in beide Richtungen mit beiden Master/Slave Einstellungen.
>Das FW Beispiel läuft einwandfrei in beide Richtungen mit beiden >Master/Slave Einstellungen. Überprüf mal deine SlaveSelect Einstellungen.
Und zieh auch mal die SlaveSelect Leitung runter bevor der Master was sendet.
>Und zieh auch mal die SlaveSelect Leitung runter >bevor der Master was sendet. Hmm, braucht man bei den Dingern wohl nicht. >Das FW Beispiel läuft einwandfrei in beide Richtungen mit beiden >Master/Slave Einstellungen. Dort werden die SPI Pins aber auch fleissig von Input auf Output, oder Output auf Input umgeschaltet wenn Master und Slave wechseln. Vermutlich machst du da einen Fehler.
Ja, die NSS Pins sind gar nicht miteinander verbunden. Beim Initialisieren des SPI setze ich das SSM Bit für den NSS Software Mode. Das fleißige Umsetzen von Input auf Output habe (jetzt) ich auch mit drin. Ich bin ungefähr einen halben Schritt weiter gekommen: Konfiguriere ich SPI2 als Master, SPI1 als Slave, dann funktioniert die Datenübertragung manchmal. SPI1 empfängt immer meine 0x11, SPI2 hat aber fast immer ein 0xFF im Empfangsregister stehen. Einmal hat es aber schon geklappt. Drehe ich den Code um und lasse SPI1 als Master senden, SPI2 als Slave agieren, dann funktioniert die Kommunikation gar nicht mehr. SPI1 empfängt angeblich einmal 0x00. SPI2 empfängt gar nichts, scheint nichtmal zu senden. Das Sendeflag ist dauerhaft low, als ob noch Daten im Sendebuffer drin wären, die eigentlich mit SPI1 raus gehen sollten. Ich würde fast sagen, dass SPI2 kaputt ist, aber das FW Beispiel geht immer noch. Hier ist mein Code. Am Anfang das #define SPI1_MASTER konfiguriert SPI1 als Master und SPI2 als SLave oder andersrum. Die Reihenfolge beim Senden beachte ich jetzt auch. Auch die Konfiguration der SPIs und des Taktes ist jetzt identisch wie im FW Lib. Hilfe!
1 | void SPI_Test(void) |
2 | {
|
3 | /* 1. SPI1 als Master, SPI2 als Slave initialisieren
|
4 | * 2. Daten von SPI1 zu SPI2 schicken
|
5 | * 3. Daten von SPI2 zu SPI1 schicken
|
6 | */
|
7 | |
8 | #define SPI1_MASTER
|
9 | |
10 | /* Schritt 1 */
|
11 | SPI_InitTypeDef SPIInit1; |
12 | GPIO_InitTypeDef GPIOInit1; |
13 | |
14 | RCC_APB2PeriphClockCmd(LCD_SPI_CLK_GPIO_CLK | LCD_SPI_MISO_GPIO_CLK | LCD_SPI_MOSI_GPIO_CLK | RCC_APB2Periph_AFIO, ENABLE); |
15 | RCC_APB2PeriphClockCmd(LCD_SPI_CLK, ENABLE); |
16 | |
17 | GPIOInit1.GPIO_Pin = LCD_SPI_CLK_PIN; |
18 | GPIOInit1.GPIO_Speed = GPIO_Speed_50MHz; |
19 | #ifdef SPI1_MASTER
|
20 | GPIOInit1.GPIO_Mode = GPIO_Mode_AF_PP; |
21 | #endif
|
22 | #ifndef SPI1_MASTER
|
23 | GPIOInit1.GPIO_Mode = GPIO_Mode_IN_FLOATING; |
24 | #endif
|
25 | GPIO_Init(LCD_SPI2_CLK_GPIO_PORT, &GPIOInit1); |
26 | |
27 | GPIOInit1.GPIO_Pin = LCD_SPI_MISO_PIN; |
28 | #ifdef SPI1_MASTER
|
29 | GPIOInit1.GPIO_Mode = GPIO_Mode_IN_FLOATING; |
30 | #endif
|
31 | #ifndef SPI1_MASTER
|
32 | GPIOInit1.GPIO_Mode = GPIO_Mode_AF_PP; |
33 | #endif
|
34 | GPIO_Init(LCD_SPI2_MISO_GPIO_PORT, &GPIOInit1); |
35 | /*
|
36 | GPIOInit1.GPIO_Pin = LCD_SPI_NSS_PIN;
|
37 | #ifdef SPI1_MASTER
|
38 | GPIOInit1.GPIO_Mode = GPIO_Mode_AF_PP;
|
39 | #endif
|
40 | #ifndef SPI1_MASTER
|
41 | GPIOInit1.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
42 | #endif
|
43 | GPIO_Init(LCD_SPI_NSS_GPIO_PORT, &GPIOInit1);
|
44 | */
|
45 | GPIOInit1.GPIO_Pin = LCD_SPI_MOSI_PIN; |
46 | #ifdef SPI1_MASTER
|
47 | GPIOInit1.GPIO_Mode = GPIO_Mode_AF_PP; |
48 | #endif
|
49 | #ifndef SPI1_MASTER
|
50 | GPIOInit1.GPIO_Mode = GPIO_Mode_IN_FLOATING; |
51 | #endif
|
52 | GPIO_Init(LCD_SPI_MOSI_GPIO_PORT, &GPIOInit1); |
53 | |
54 | SPI_I2S_DeInit(SPI1); |
55 | SPIInit1.SPI_Direction = SPI_Direction_2Lines_FullDuplex; |
56 | #ifdef SPI1_MASTER
|
57 | SPIInit1.SPI_Mode = SPI_Mode_Master; |
58 | #endif
|
59 | #ifndef SPI1_MASTER
|
60 | SPIInit1.SPI_Mode = SPI_Mode_Slave; |
61 | #endif
|
62 | SPIInit1.SPI_DataSize = SPI_DataSize_8b; |
63 | SPIInit1.SPI_CPOL = SPI_CPOL_Low; |
64 | SPIInit1.SPI_CPHA = SPI_CPHA_2Edge; |
65 | SPIInit1.SPI_NSS = SPI_NSS_Soft; |
66 | SPIInit1.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; /* gegebenenfalls anpassen an 72MHz Connectivity Line */ |
67 | SPIInit1.SPI_FirstBit = SPI_FirstBit_LSB; |
68 | SPIInit1.SPI_CRCPolynomial = 7; |
69 | SPI_Init(LCD_SPI, &SPIInit1); |
70 | |
71 | /* SPI1 starten */
|
72 | SPI_Cmd(LCD_SPI, ENABLE); |
73 | |
74 | |
75 | |
76 | SPI_InitTypeDef SPIInit2; |
77 | GPIO_InitTypeDef GPIOInit2; |
78 | |
79 | RCC_APB2PeriphClockCmd(LCD_SPI2_CLK_GPIO_CLK | LCD_SPI2_MISO_GPIO_CLK | LCD_SPI2_MOSI_GPIO_CLK, ENABLE); |
80 | RCC_APB1PeriphClockCmd(LCD_SPI2_CLK, ENABLE); |
81 | |
82 | GPIOInit2.GPIO_Pin = LCD_SPI2_CLK_PIN; |
83 | GPIOInit2.GPIO_Speed = GPIO_Speed_50MHz; |
84 | #ifdef SPI1_MASTER
|
85 | GPIOInit2.GPIO_Mode = GPIO_Mode_IN_FLOATING; |
86 | #endif
|
87 | #ifndef SPI1_MASTER
|
88 | GPIOInit2.GPIO_Mode = GPIO_Mode_AF_PP; |
89 | #endif
|
90 | GPIO_Init(LCD_SPI2_CLK_GPIO_PORT, &GPIOInit2); |
91 | |
92 | GPIOInit2.GPIO_Pin = LCD_SPI2_MISO_PIN; |
93 | #ifdef SPI1_MASTER
|
94 | GPIOInit2.GPIO_Mode = GPIO_Mode_AF_PP; |
95 | #endif
|
96 | #ifndef SPI1_MASTER
|
97 | GPIOInit2.GPIO_Mode = GPIO_Mode_IN_FLOATING; |
98 | #endif
|
99 | GPIO_Init(LCD_SPI2_MISO_GPIO_PORT, &GPIOInit2); |
100 | /*
|
101 | GPIOInit2.GPIO_Pin = LCD_SPI2_NSS_PIN;
|
102 | #ifdef SPI1_MASTER
|
103 | GPIOInit2.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
104 | #endif
|
105 | #ifndef SPI1_MASTER
|
106 | GPIOInit2.GPIO_Mode = GPIO_Mode_AF_PP;
|
107 | #endif
|
108 | GPIO_Init(LCD_SPI2_NSS_GPIO_PORT, &GPIOInit2);
|
109 | */
|
110 | GPIOInit2.GPIO_Pin = LCD_SPI2_MOSI_PIN; |
111 | #ifdef SPI1_MASTER
|
112 | GPIOInit2.GPIO_Mode = GPIO_Mode_IN_FLOATING; |
113 | #endif
|
114 | #ifndef SPI1_MASTER
|
115 | GPIOInit2.GPIO_Mode = GPIO_Mode_AF_PP; |
116 | #endif
|
117 | GPIO_Init(LCD_SPI2_MOSI_GPIO_PORT, &GPIOInit2); |
118 | |
119 | SPI_I2S_DeInit(SPI2); |
120 | SPIInit2.SPI_Direction = SPI_Direction_2Lines_FullDuplex; |
121 | #ifdef SPI1_MASTER
|
122 | SPIInit2.SPI_Mode = SPI_Mode_Slave; |
123 | #endif
|
124 | #ifndef SPI1_MASTER
|
125 | SPIInit2.SPI_Mode = SPI_Mode_Master; |
126 | #endif
|
127 | SPIInit2.SPI_DataSize = SPI_DataSize_8b; |
128 | SPIInit2.SPI_CPOL = SPI_CPOL_Low; |
129 | SPIInit2.SPI_CPHA = SPI_CPHA_2Edge; |
130 | SPIInit2.SPI_NSS = SPI_NSS_Soft; |
131 | SPIInit2.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; /* gegebenenfalls anpassen an 72MHz Connectivity Line */ |
132 | SPIInit2.SPI_FirstBit = SPI_FirstBit_LSB; |
133 | SPIInit2.SPI_CRCPolynomial = 7; |
134 | SPI_Init(LCD_SPI2, &SPIInit2); |
135 | |
136 | /* SPI2 starten */
|
137 | SPI_Cmd(LCD_SPI2, ENABLE); |
138 | |
139 | |
140 | /* Schritt 2*/
|
141 | |
142 | |
143 | uint16_t test=0; |
144 | uint16_t test2=0; |
145 | /* SPI senden 0x1111 */
|
146 | |
147 | #ifdef SPI1_MASTER
|
148 | //GPIO_WriteBit(LCD_SPI_NSS_GPIO_PORT, LCD_SPI_NSS_PIN, Bit_RESET);
|
149 | SPI_I2S_SendData(SPI2, 0x11); |
150 | SPI_I2S_SendData(SPI1, 0x11); |
151 | while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) |
152 | {
|
153 | }
|
154 | test2 = SPI_I2S_ReceiveData(SPI2); |
155 | while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) |
156 | {
|
157 | }
|
158 | test = SPI_I2S_ReceiveData(SPI1); |
159 | //GPIO_WriteBit(LCD_SPI_NSS_GPIO_PORT, LCD_SPI_NSS_PIN, Bit_SET);
|
160 | #endif
|
161 | #ifndef SPI1_MASTER
|
162 | //GPIO_WriteBit(LCD_SPI2_NSS_GPIO_PORT, LCD_SPI2_NSS_PIN, Bit_RESET);
|
163 | SPI_I2S_SendData(SPI1, 0x11); |
164 | SPI_I2S_SendData(SPI2, 0x11); |
165 | while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) |
166 | {
|
167 | }
|
168 | test2 = SPI_I2S_ReceiveData(SPI1); |
169 | while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) |
170 | {
|
171 | }
|
172 | test = SPI_I2S_ReceiveData(SPI2); |
173 | //GPIO_WriteBit(LCD_SPI2_NSS_GPIO_PORT, LCD_SPI2_NSS_PIN, Bit_SET);
|
174 | #endif
|
175 | |
176 | /* Beide LED aus, wenn Daten empfangen */
|
177 | |
178 | if(test==0) |
179 | {
|
180 | LED_On(LED1); |
181 | }
|
182 | else
|
183 | {
|
184 | LED_Off(LED1); |
185 | }
|
186 | |
187 | if(test2==0) |
188 | {
|
189 | LED_On(LED2); |
190 | }
|
191 | else
|
192 | {
|
193 | LED_Off(LED2); |
194 | }
|
195 | |
196 | |
197 | }
|
Omg, zweimal der selbe Typo: GPIO_Init(LCD_SPI2_CLK_GPIO_PORT, &GPIOInit1); GPIO_Init(LCD_SPI2_MISO_GPIO_PORT, &GPIOInit1); heißt natürlich GPIO_Init(LCD_SPI_CLK_GPIO_PORT, &GPIOInit1); GPIO_Init(LCD_SPI_MISO_GPIO_PORT, &GPIOInit1); ... Nur komisch, dass es mit falscher Konfiguration ungefähr jedes 10. Mal funktioniert hat, in einer der 4 Kommunikationsrichtungen.
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.