Forum: Mikrocontroller und Digitale Elektronik STM32F429 DMA und ADC


von muhh (Gast)


Lesenswert?

Hallo Leute,

ich bin im Moment dabei den DMA Controller des STM32F429 zu 
programmieren. Leider funktioniert da gar nichts... Ich habe versucht 
den DMA DataCounter (SxNDTR) zu setzen und ihn dirket danach auszulesen. 
Leider funktioniert das nicht, ich erhalte immer den Wert 0. Hier der 
Code dafür (die Initialisierung habe ich jetzt mal weggelassen).
1
DMA_SetCurDataCounter(DMA2_Stream0,10);
2
uint16_t asd = DMA_GetCurrDataCounter(DMA2_Stream0);
3
4
DMA_Cmd(DMA2_Stream0, ENABLE);

Woran kann das liegen? Ich schreibe doch nur einen Wert in ein 
Register...

Viele Grüße

von Gerald G. (gerald_g)


Lesenswert?

Füge mal ein

asm volatile ("nop"::);
Dazwischen ein

: Bearbeitet durch User
von muhh (Gast)


Lesenswert?

Hallo,

ich habe das probiert und den Breakpoint auf die Zeile gelegt, aber es 
passiert leider nichts.

von m.n. (Gast)


Lesenswert?

muhh schrieb:
> Ich habe versucht
> den DMA DataCounter (SxNDTR) zu setzen und ihn dirket danach auszulesen.
> Leider funktioniert das nicht, ich erhalte immer den Wert 0.

Es funktioniert, wie es soll :-)
Das Register kann man nur lesen, wenn der DMA-Kanal aktiv ist. Das ist 
der 'wunderbare' STM32!

von muhh (Gast)


Lesenswert?

Leider funktioniert auch das nicht.

Ich habe den den Stream0 (Channel0) aktiviert mit DMA_Cmd(DMA2_Stream0, 
ENABLE), leider funktioniert das auslesen des Counter Wertes dann immer 
noch nicht...

von BastiDerBastler (Gast)


Lesenswert?

Wenn er aktiv ist, oder wenn er aktiviert ist?
Letzteres wäre ja nun das Muster, das man überall in dem Teil hat. Wenn 
ein Gerät abgeschaltet ist, dann hört es eben auch nicht am AHB mit...

von BastiDerBastler (Gast)


Lesenswert?

Hast Du im RCC_AHB1ENR den DMA-Controller selber angeschaltet?

von muhh (Gast)


Lesenswert?

Folgenden Code habe ich verwendet, vielleicht habe ich euch einfach auch 
nur missverstanden und es deswegen falsch gemacht.
1
DMA_Cmd(DMA2_Stream0, DISABLE);
2
DMA2_Stream0->NDTR = 10;
3
DMA_Cmd(DMA2_Stream0, ENABLE);
4
asd = DMA_GetCurrDataCounter(DMA2_Stream0);
5
asm volatile ("nop"::);

Bei dem As. Befehl habe ich einen Breakpoint gesetzt um zu schauen, 
welcher Wert in asd steht, leider immer noch 0. Ich benutze ganz am 
Anfang die Funktion DMA_DeInit(DMA_Stream0), aber eigentlich werden da 
alle Werte nur auf 0 gesetzt... Ich weiß echt nicht woran das liegt, ich 
bekomme den DMA einfach nicht zum laufen, selbst diese einfachen 
Sachen...

von m.n. (Gast)


Lesenswert?

muhh schrieb:
> ich bin im Moment dabei den DMA Controller des STM32F429 zu
> programmieren. Leider funktioniert da gar nichts...

Was ich Dir weiter oben andeuten wollte: der DMA-Controller ist eine 
Krücke. Nimm das "Referece Manual" RM0090 und lies zwischen den Zeilen 
genau nach, was alles nicht geht.
Dann such Dir ein Beispielprogramm, was in etwa die von Dir gewünschte 
Funktion erfüllt und passe es an.

Wenn Du einen richtigen DMAC brauchst, dann nimm einen RX62/RX63 von 
Renesas.

von W. M. (muhh)


Lesenswert?

BastiDerBastler schrieb:
> Hast Du im RCC_AHB1ENR den DMA-Controller selber angeschaltet?

-.- Ich hatte anstelle von
1
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
 geschrieben:
1
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

Manchmal ist echt der Wurm drin... Dankeschön für die Tipps, ich bin 
froh das ich das jetzt geklärt habe, der DMA läuft jetzt mit dem ADC :)

von Clemens M. (panko)


Lesenswert?

Hätte es auch vorher, du hast ja zweimal das Selbe geschrieben ;-)

von W. M. (muhh)


Lesenswert?

Clemens M. schrieb:
> Hätte es auch vorher, du hast ja zweimal das Selbe geschrieben ;-)

Oh man ey, Copy Paste Fehler :D

Vorher:
1
RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_DMA2, ENABLE);

Nachher:
1
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

Ich habe doch noch ein kleines Problem mit dem ADC und dem DMA. Ich 
möchte erstmal 2 Channel im Scan Mode wandeln und diese Werte via DMA in 
ein Array mit 2 Feldern schreiben. Leider funktioniert das nicht so wie 
ich möchte. Die erste Gruppen-Wandlung wird in das Array geschrieben, 
die Werte ändern sich aber nie wieder.

Hier die Konfiguration:
1
/** Enable peripheral clocks */
2
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);  // 90 MHz ADC1 Clk
3
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
4
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
5
6
  ADC_DeInit();
7
  ADC_StructInit(&ADC_InitStructure);
8
9
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
10
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
11
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
12
  ADC_InitStructure.ADC_NbrOfConversion = 2;
13
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
14
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;
15
16
  ADC_Init(ADC1, &ADC_InitStructure);
17
  ADC_Cmd(ADC1, ENABLE);
18
  ADC_DMACmd(ADC1, ENABLE);
19
20
  /**
21
   * Configure Regular Channel Group
22
   * Tconv = Sampling Time + 12 cycles
23
   */
24
  ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_15Cycles);    // => Tconv = (15 + 12) cycles = 1.2us
25
  ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_15Cycles);
26
27
  ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
28
29
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
30
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
31
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
32
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
33
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
34
  GPIO_Init(GPIOC, &GPIO_InitStructure);
35
36
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
37
  NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQn;
38
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
39
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
40
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
41
  NVIC_Init(&NVIC_InitStructure);
42
  NVIC_EnableIRQ(ADC_IRQn);
43
44
45
  /*************************************************
46
   * DMA Configuration
47
   ************************************************/
48
49
  DMA_StructInit(&DMA_InitStructure);
50
  DMA_DeInit(DMA2_Stream0);
51
52
  DMA_InitStructure.DMA_BufferSize = 2;
53
  DMA_InitStructure.DMA_Channel = DMA_Channel_0;
54
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
55
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) &PedalConvValue[0];
56
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;      // Don't Care
57
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
58
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
59
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
60
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
61
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
62
  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
63
64
  DMA_Init(DMA2_Stream0, &DMA_InitStructure);
65
66
  GPIO_ToggleBits(GPIOG, GPIO_Pin_13);
67
  GPIO_ToggleBits(GPIOG, GPIO_Pin_14);
68
  DMA_Cmd(DMA2_Stream0, ENABLE);

Auf Knopfdruck wird eine Wandlung gestartet. Das ADC Interrupt wird nach 
einer ScanConversion ausgelöst. Hier die ISR:
1
void ADC_IRQHandler(void)
2
{
3
  NVIC_ClearPendingIRQ(ADC_IRQn);
4
  ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
5
6
  uint_fast16_t DMACounterValue = DMA_GetCurrDataCounter(DMA2_Stream0);
7
8
  uint16_t PedalValue = ADC_GetConversionValue(ADC1);
9
  uint16_t asdasd[4] = {PedalConvValue[0],PedalConvValue[1],PedalConvValue[2],PedalConvValue[3]};
10
11
  ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
12
13
  uint32_t adc_cr = ADC1->CR2 & 0x00000200;           // Wird das DDS Bit gesetzt?
14
  GPIO_ToggleBits(GPIOG, GPIO_Pin_13);
15
}

Wenn ich die die DMA_BufferSize auf 4 setze, dann funktioniert das ganze 
einwandfrei, er füllt immer zwei Felder mit Daten und nach zwei 
ScanConversions fängt er von vorne an.

von Christoph E. (qfnr)


Lesenswert?

m.n. schrieb:
> muhh schrieb:
>> Ich habe versucht
>> den DMA DataCounter (SxNDTR) zu setzen und ihn dirket danach auszulesen.
>> Leider funktioniert das nicht, ich erhalte immer den Wert 0.
>
> Es funktioniert, wie es soll :-)
> Das Register kann man nur lesen, wenn der DMA-Kanal aktiv ist. Das ist
> der 'wunderbare' STM32!

Das stimmt meines wissens nach nicht. das DMA-SxNDTR Register kann, wenn 
der Stream aus ist sowohl geschrieben als auch gelesen werden. Ist der 
Stream jedoch an kann er gelesen aber nicht beschrieben werden.

Gruß
Christopher

von BastiDerBastler (Gast)


Lesenswert?

So wär' das doch schneller aufgefallen? :)

stm::rcc::enable< stm::rcc::dma1, stm::rcc::dma2 >();

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.