Forum: Mikrocontroller und Digitale Elektronik Cortex F4 Timer Input Capture + DMA


von progger0815 (Gast)


Lesenswert?

Hallo,

ich habe versucht anhand von den Examples von Coocox, die ich auch hier 
im Forum gefunden habe, mit dem STM32F4Discovery Timer Input Capture mit 
DMA zu realisieren.

Leider bekomm ich das ganze nicht zum laufen.
Bitte um Hilfe.
1
void Timer_DMA_INIT_EXAMPLE(void)
2
{
3
    GPIO_InitTypeDef GPIO_InitStructure;
4
5
    /* TIM4 clock enable */
6
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
7
8
    /* GPIOB clock enable */
9
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
10
    
11
    /* TIM4 chennel2 configuration : PB.07 */
12
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_7;
13
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
14
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
15
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
16
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP ;
17
    GPIO_Init(GPIOB, &GPIO_InitStructure);
18
    
19
    /* Connect TIM pin to AF2 */
20
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_TIM4);
21
22
23
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
24
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_BothEdge;
25
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
26
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
27
    TIM_ICInitStructure.TIM_ICFilter = 0x0;
28
    
29
      
30
   TIM_ICInit(TIM4, &TIM_ICInitStructure);
31
   
32
   TIM_UpdateRequestConfig(TIM4,TIM_UpdateSource_Regular);
33
34
    
35
    // DMA Konfiguration
36
37
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
38
    DMA_InitTypeDef DMA_InitStruct;
39
    DMA_StructInit(&DMA_InitStruct);
40
    DMA_InitStruct.DMA_Channel = DMA_Channel_2;
41
    DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)TIM_DMABase_CCR2;
42
    DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)&buffer;
43
    DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralToMemory;
44
    DMA_InitStruct.DMA_BufferSize = 11;
45
    DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
46
    DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
47
    DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
48
    DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
49
    DMA_InitStruct.DMA_Mode = DMA_Mode_Circular; // DMA_Mode_Circular wenn man dauernd senden will;
50
    DMA_InitStruct.DMA_Priority = DMA_Priority_High;
51
    DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;
52
    DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
53
    DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;
54
    DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
55
    DMA_Init(DMA1_Stream3, &DMA_InitStruct);
56
    DMA_Cmd(DMA1_Stream3, ENABLE);
57
    
58
    TIM_DMAConfig(TIM4, TIM_DMABase_CCR2, TIM_DMABurstLength_1Transfer); 
59
     
60
    TIM_DMACmd(TIM4, TIM_DMA_Trigger , ENABLE);
61
       
62
    TIM_SelectCCDMA(TIM4, ENABLE);
63
}

von Raffael T. (Gast)


Lesenswert?

Das interessiert mich auch.
Ich kämpfe auch gerade mit den Cortex F4 Timern.
@ progger0815: hast du schon eine Lösung?

von Nils P. (ert)


Lesenswert?

huhu,

was ist das Ziel?

PWM-Verhältnis einlesen? Schaut euch mal die Befehle an:

TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);

/* Select the TIM3 Input Trigger: TI1FP1 */
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);

/* Select the slave Mode: Reset Mode */
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
TIM_SelectMasterSlaveMode(TIM3,TIM_MasterSlaveMode_Enable);  // 21 MHz

TIM_PrescalerConfig(TIM3, 3, TIM_PSCReloadMode_Immediate);

/* TIM enable counter */
TIM_Cmd(TIM3, ENABLE);

G Ert

von Raffael T. (Gast)


Lesenswert?

Danke für die Antwort Nils!

Ich habe den Timer mittlerweile zum Laufen gebracht (hab das Sample von 
Progger verwendet)
Gibt auch schön Interrupts aber der DMA-Request funktioniert nicht.
Ich habe auch schon das 1400 Seiten Manual von ARM durchforstet, kann 
aber nichts finden, warum DMA hier nicht funktioniert. Anscheinend 
übersehe ich da was Entscheidendes.

Ich will nicht PWM einlesen, sondern die Zeit zwischen mehreren 
Umschaltvorgängen des übergeordenten Systems wissen. Das Ganze ist zur 
Fehleranalyse gedacht. DMA brauch ich aus Ressourcengründen.

von Dr. Sommer (Gast)


Lesenswert?

Die Cortex M4(F) haben keine Timer, nur einen Systick. Ihr meint die 
STM32F4-Timer. Daher bringt das Manual von ARM auch nichts, sondern eher 
das STM32F4 Reference Manual von ST.

von progger0815 (Gast)


Lesenswert?

Ich hänge leider noch immer beim DMA fest.
Per Interrupt lässt sich der Timerwert auslesen, nur mit DMA 
funktioniert es nicht.
Kann es sein, dass Interrupt und DMA Request nicht gleichzeitig 
funktionieren?

von Torsten C. (torsten_c) Benutzerseite


Lesenswert?

Raffael T. schrieb:
> Ich kämpfe auch gerade mit den Cortex F4 Timern.
> @ progger0815: hast du schon eine Lösung?

Nun sind wir bereits zu dritt. Mein Problem: Ich muss ca. 60ms lang alle 
Interrupts ausschalten, um eine Kette mit bis zu 2000 WS2812-LEDs in 
einem exakten und Jitter-freien Timing mit Daten-Bits zu versorgen.

Andererseits muss ich auch in dieser Zeit die Flanken eines 
ALPS-Encoders (Dreh-Drück-Knopf) auslesen. Dort kommen bei schnellen 
Drehungen ca. alle 8ms Flankenwechsel. Ich würde also ca. 7 
Flankenwechsel verlieren.

Vielleicht gibt es 2 verschiedene Möglichkeiten:

1. Der DMA-Controller schiebt die Daten-Bits Jitter-frei auf einen
   GPIO-Pin oder

2. Der DMA-Controller schiebt nach jedem Flankenwechsel vom
   ALPS-Encoder die Input-Capture-Werte in den FIFO oder noch
   besser ins RAM.

Lösung 2 wäre m.E. das, was progger0815 auch möchte.

Ich blicke nach Lektüre der Datenblätter ohne Programm-Beispiel auch 
noch nicht ganz durch.

Hat das schon mal jemand hinbekommen, oder inzwischen ein 
Programm-Beispiel gefunden?

von Torsten C. (torsten_c) Benutzerseite


Lesenswert?

Dr. Sommer schrieb:
> Daher bringt das Manual von ARM auch nichts, sondern eher
> das STM32F4 Reference Manual von ST.

... und das UM0427.

PS: Das scheint aber alles nicht so einfach zu sein, hier gab's auch 
noch keine Antwort:

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/DispForm.aspx?ID=32344

von Uwe B. (Firma: TU Darmstadt) (uwebonnes)


Lesenswert?

Torsten C. schrieb:
> Andererseits muss ich auch in dieser Zeit die Flanken eines
> ALPS-Encoders (Dreh-Drück-Knopf) auslesen. Dort kommen bei schnellen
> Drehungen ca. alle 8ms Flankenwechsel. Ich würde also ca. 7
> Flankenwechsel verlieren.

Manche STM32 Timer, z.B. TIM1/8, kennen eine Quadratur Encoder Mode. 
Dann werden die Flanken auch bei abgeschalteten Interrupt erkannt..

von Torsten C. (torsten_c) Benutzerseite


Angehängte Dateien:

Lesenswert?

Uwe Bonnes schrieb:
> Manche STM32 Timer, z.B. TIM1/8, kennen eine Quadratur Encoder Mode.
> Dann werden die Flanken auch bei abgeschalteten Interrupt erkannt..

Danke für den Tipp. :-) Dann kann ich zwar keine SW-Entprellung machen, 
aber da nur jeder zweite Counter-Stand genutzt wird, sollte das gehen.

Ich will nicht länger auf alternative Lösungen warten und habe für 
schnelle Drehungen zur Sicherheit eine Entprellung mit 2 Widerständen 
und einem Kondensator bestückt. Ich bin heute nur noch nicht zum 
ausprobieren gekommen.

Aber die Ursprungsfrage von progger0815 ist leider noch nicht 
beantwortet. Mich interessiert trotzdem, wie's gehen würde.

Und um den Prozessor nicht mit zu blockieren, will ich auch
Möglichkeit 1 ^^ weiter verfolgen.

von Uwe B. (Firma: TU Darmstadt) (uwebonnes)


Lesenswert?

Erstens haben die Timer auch noch Filteroptionen. Schau Dir die erstmal 
an, bevor Du extern Filters. Aus ausserdem macht Prellen nichts, solange 
das Prellen nicht bis zur naechsten Taktflanke des anderen Kanal dauert.

von Torsten C. (torsten_c) Benutzerseite


Lesenswert?

Uwe Bonnes schrieb:
> Schau Dir die erstmal an, bevor Du extern Filterst.

Wieder ein guter Tipp, danke. In dem Teil ist noch einiges verborgen, 
was ich noch nicht entdeckt habe.

Uwe Bonnes schrieb:
> solange das Prellen nicht bis zur naechsten Taktflanke
> des anderen Kanal dauert

Das kann bei schnellen Drehungen leider passieren. Aber wenn die Flanken 
immer erst übernommen werden, wenn die Signale mehrere Takte stabil 
sind, werden ja vielleicht beide Flanken verzögert und dann würde ja 
trotzdem korrekt gezählt werden.

Mit 'nem größeren Drehknopf (Foto) kommt man auch nicht mehr so leicht 
auf sooo hohe Frequenzen, als wenn man direkt an der Welle dreht.

Aber ich glaube, nun haben wir - ohne es zu wollen - langsam diesen 
Thread für ein anderes Thema gekapert.

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.