Hi Leute, ich habe eine Frage bezüglich der Kommunikation zweier STM32 mit DMA SPI. Ich möchte mittels SPI 7 16 Bit variablen von Slave zu Master und dementsprechend umgekehrt schicken. Hardwaremäßig habe ich Ich habe MOSI mit MOSI, CLK mit CLK, NSS mit NSS und MISO mit MISO verbunden (PORT A4 bis A7). In meiner Software habe ich für den SPI1 den DMA Channel 2 als RX und den DMA Channel 3 als TX Buffer definiert. Der Aufbau der Software besteht aus einem endlosen loop der u.a. abfragt ob der SPI Bus frei ist (Ich setzte beim senden der Daten vom Master eine Variable auf 0 und setze sie in der ISR des RX DMA Kanals wieder auf 1) Daher sollten niemals zwei Transfers gleichzeitig stattfinden. Ich habe für den Transfer drei Puffer definiert, einen RX Puffer und einen TX Puffer und einen Puffer mit dem das Programm arbeitet. In der ISR (void spi_handleDMA1Ch2Interrupt(void), s.u.)des RX DMA warte ich bis der Transfer komplett ist, schalte den DMA Kanal ab, kopiere den Inhalt des RX Puffers in den Programm Puffer. Dann setze ich noch das FLAG für den SPI Bus auf 1. Der DMA wird dann aus dem Programmcode neu gestartet sobald Daten gesendet werden sollen (void SPI2_send(void), s.u.) Auf Slave Seite ist der Code ähnlich, bis auf das natürlich nicht die NSS Leitung gezogen wird und der DMA unmittelbar nach dem Austausch der Puffer gestartet wird, damit auch Daten anliegen wenn der Master erneut eine Transaktion einleitet. Mein Problem ist nun das folgende. Es werden anscheinend Daten übermittelt, ich übertrage mit den Daten immer noch eine vier bittige Message Nummer von 0 bis 14, 15 ist für den Start des Programmes reserviert, damit ich im RX auch sehe auf welche anfrage der Slave antwortet. Diese übertrage ich im letzten byte also in Puffer[6] Der Master sendet erst eine neue Nachricht insofern er als Bestätigung eine Antwort mit der gleichen ID empfangen hat, sonst sendet er die vorherige Nachricht noch einmal. Nach dem übertragen finde ich die Zahl manchmal in Puffer[4], manchmal in Puffer[5] und so weiter. Es scheint als ob sie immer eine Stelle weiter im Array shiftet. Zudem habe ich das Programm gerade testweise so geschrieben, das in den ersten drei übertragenen Wörtern der gleiche Wert stehen soll. Steht aber meistens nur in den ersten beiden oder im ersten. Meine Frage daher, Kann es sein, das es den SPI stört wenn man mit einem Debugger gleichzeitig im Programm unterwegs ist? Ich nutze den JLink im SWD Modus mit eclipse IDE und gdb. Die Breakpoints habe ich auch schon nur ausserhalb der ISR gesetzt. Ist meine überlegung das ein RX und ein TX Puffer benutzt wird falsch, ich habe auch schon Code Beispiele mit nur einem Puffer gesehen. Hat jemand eine Idee woran so ein verhalten liegen kann?? ich habe den Clock Prescaler auch schon auf 256 gesetzt damit die Kommunikation etwas verlangsamt wird. Vielen Dank, Willem
1 | void spi_handleDMA1Ch2Interrupt(void){ |
2 | uint8_t i; |
3 | //Test on DMA1 Channel2 Transfer Complete interrupt
|
4 | if(DMA_GetITStatus(DMA1_IT_TC2)) |
5 | {
|
6 | //Clear DMA1 Channel1 Half Transfer, Transfer Complete and Global interrupt pending bits
|
7 | DMA_ClearITPendingBit(DMA1_IT_GL2); |
8 | while (DMA_GetFlagStatus(DMA1_FLAG_TC3) == RESET) {} |
9 | // wait for tx to complete - page 692
|
10 | while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) {} |
11 | while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET) {} |
12 | DMA_ClearFlag(DMA1_FLAG_GL3); // Clear the global flag |
13 | |
14 | // Disable DMA
|
15 | DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, DISABLE); |
16 | SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx | SPI_I2S_DMAReq_Tx, DISABLE); |
17 | DMA_Cmd(DMA1_Channel2, DISABLE); |
18 | DMA_Cmd(DMA1_Channel3, DISABLE); |
19 | // wait until DMA is actually off
|
20 | while (DMA1_Channel2->CCR & DMA_CCR2_EN); |
21 | while (DMA1_Channel3->CCR & DMA_CCR3_EN); |
22 | #ifdef SPI2_MASTER
|
23 | // Set NSS High
|
24 | GPIO_WriteBit(GPIOA, GPIO_Pin_4, SET); |
25 | #endif
|
26 | // Copy RX buffer
|
27 | for(i=0;i<7;i++) |
28 | {
|
29 | #ifdef SPI2_SLAVE
|
30 | SPI2Buffer[i]=SPI2CommandBuffer[i]; |
31 | #endif
|
32 | SPI2CommandBuffer[i]=SPI2RecBuffer[i]; |
33 | }
|
34 | #ifdef SPI2_MASTER
|
35 | // Set the SPI Bus free
|
36 | SPI2_FREE=1; |
37 | #endif
|
38 | #ifdef SPI2_SLAVE
|
39 | // Set the number of transfers
|
40 | DMA_SetCurrDataCounter(DMA1_Channel2, 7); |
41 | DMA_SetCurrDataCounter(DMA1_Channel3, 7); |
42 | DMA_ClearITPendingBit(DMA1_IT_GL2); // clear again |
43 | DMA_ClearFlag(DMA1_FLAG_GL3); // Clear the global flag |
44 | |
45 | // Start DMA controller again
|
46 | DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE); |
47 | SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx | SPI_I2S_DMAReq_Tx, ENABLE); |
48 | |
49 | // Initiate Transfer
|
50 | DMA_Cmd(DMA1_Channel2, ENABLE); |
51 | DMA_Cmd(DMA1_Channel3, ENABLE); |
52 | #endif
|
53 | }
|
54 | }
|
55 | |
56 | void SPI2_send(void) |
57 | {
|
58 | uint8_t i; |
59 | // Lock SPI Bus
|
60 | SPI2_FREE=0; |
61 | // Write Commands into TX Buffer
|
62 | for(i=0; i<7; i++) |
63 | {
|
64 | SPI2Buffer[i]=CommandBuffer[i]; |
65 | }
|
66 | // Set the number of transfers
|
67 | DMA_SetCurrDataCounter(DMA1_Channel2, 7); |
68 | DMA_SetCurrDataCounter(DMA1_Channel3, 7); |
69 | DMA_ClearITPendingBit(DMA1_IT_GL2); // clear again |
70 | DMA_ClearFlag(DMA1_FLAG_GL3); // Clear the global flag |
71 | |
72 | // Start DMA controller again
|
73 | DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE); |
74 | SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx | SPI_I2S_DMAReq_Tx, ENABLE); |
75 | |
76 | // Pull NSS Low
|
77 | GPIO_WriteBit(GPIOA, GPIO_Pin_4, RESET); |
78 | // Initiate Transfer
|
79 | DMA_Cmd(DMA1_Channel2, ENABLE); |
80 | DMA_Cmd(DMA1_Channel3, ENABLE); |
81 | }
|