Forum: Mikrocontroller und Digitale Elektronik STM32 DMA neustarten


von Holger K. (holgerkraehe)


Lesenswert?

Guten Tag

Ich versuche den DMA bei einem STM32 welcher als SPI fungiert, während 
der SPI Übertragung neuzustarten.

Das sieht wie folgt aus:

CS ------|____________________|--------
SCK       |||| |||| |||| ||||
DMA         |-----------------

Ein SCK Grüppchen |||| entspricht 8 Clocks bzw. einem Byte
Ich triggere intern auf die 5te Flanke des ersten Bytes und möchte ab da 
für die folgenden Bytes den DMA parat haben, so dass dieser die nächsten 
Bytes sendet.

Dazu habe ich folgenden Code getestet:
1
 void DMA_Config(void)
2
 {
3
   DMA_InitTypeDef  DMA_InitStructure;
4
5
   DMA_DeInit(DMA1_Channel5);
6
   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI2->DR;   //0x4000380C;
7
   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&dataSendA[0];
8
   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
9
   DMA_InitStructure.DMA_BufferSize = 3;
10
   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
11
   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
12
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
13
   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
14
   DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
15
   DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
16
   DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
17
   DMA_Init(DMA1_Channel5, &DMA_InitStructure);
18
19
   //DMA_ITConfig(DMA1_Channel5,DMA_IT_TC,ENABLE);
20
21
   DMA_Cmd(DMA1_Channel5, DISABLE);
22
23
24
   //DMA_ITConfig(DMA1_Channel5,DMA_IT_TC,ENABLE);
25
   SPI_I2S_DMACmd(SPI2,SPI_I2S_DMAReq_Tx,ENABLE);
26
 }
27
28
29
30
31
32
.....
33
//Neustarten:
34
35
  //DMA Deaktivieren
36
  DMA1_Channel5->CCR &= (uint16_t)(~DMA_CCR1_EN);
37
38
  //Adresse
39
  DMA1_Channel5->CMAR = (uint32_t)&dataSendA[0];
40
41
        //DMA Counter auf 3 Bytes
42
  DMA1_Channel5->CNDTR = 3;
43
44
        //SPI TX DMA Kanal aktivieren
45
  SPI2->CR2 |= SPI_I2S_DMAReq_Tx;
46
47
  //DMA Aktivieren
48
  DMA1_Channel5->CCR |= DMA_CCR1_EN;

Leider funktioniert dies nicht wie gewünscht.
Das erste Byte ist willkürlich. das zweite stimmt dann das dritte ist 0.

Hat jemand eine Idee?

von Reginald L. (Firma: HEGRO GmbH) (reggie)


Lesenswert?

Vergiss nicht ungelesene Bytes aus dem spi auszulesen, sonst wird sofort 
der dma bei der nächsten Aktivierung getriggert.
Such mal nach meinen Beiträgen zu spi und dma, da hatte ich ein 
ähnliches Problem.

: Bearbeitet durch User
von Holger K. (holgerkraehe)


Angehängte Dateien:

Lesenswert?

Reginald L. schrieb:
> Vergiss nicht ungelesene Bytes aus dem spi auszulesen

Hab ich...


Hier ist die vollständige routine:
1
void TIM1_CC_IRQHandler(void)
2
{
3
4
  uint8_t cmd;
5
  TIM1->SR = (uint16_t)~TIM_IT_CC1;
6
  //cmd = SPI2->DR;
7
8
  //DMA Deaktivieren
9
  DMA1_Channel5->CCR &= (uint16_t)(~DMA_CCR1_EN);
10
11
  //Adresse
12
  DMA1_Channel5->CMAR = (uint32_t)&dataSendA[0];
13
  DMA1_Channel5->CNDTR = 3;
14
15
  SPI2->CR2 |= SPI_I2S_DMAReq_Tx;
16
17
  //delay(2);
18
19
  //DMA Aktivieren
20
  DMA1_Channel5->CCR |= DMA_CCR1_EN;
21
22
  GPIOC->ODR = 0xFF;
23
  GPIOC->ODR = 0x00;
24
}


Im Anhang das Bild.
Es zeigt, dass ich 0x81, 0x75, 0x27 und 0x03 empfange.
Mein Buffer ist jedoch:
1
uint8_t  dataSendA[10] = {0x75, 0x33, 0x81, 0x01, 0x77, 0x14, 0x41, 0x63, 0x20, 0xAA};

Eine Merkwürdigkeit ist noch, dass wenn ich das Programm mehrmals 
hintereinander flashe, sich der DMA unterschiedlich verhält.
Manchmal sendet der SPI Slave nur 0x00 und dies immer, dann wieder 
0x81,0x75,0x27,0x03

: Bearbeitet durch User
von Reginald L. (Firma: HEGRO GmbH) (reggie)


Lesenswert?

Holger K. schrieb:
> GPIOC->ODR = 0xFF;
>   GPIOC->ODR = 0x00;
Guck doch nochmal über deinen Code drüber, vllt übersiehst du was ;)

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.