Forum: Mikrocontroller und Digitale Elektronik STM32F4 PWM + DMA geht nicht


von Alex (Gast)


Lesenswert?

Hallo,

ich versuche seit gestern auf dem STM32F4 Discovery eine PWM laufen zu 
lassen die per DMA mit verschiedenen duty cycles gefüttert wird. Ich 
will damit WS2812 LED's ansteuern.

Leider krieg ichs irgendwie nicht hin, es wird kein einziger Wert in das 
CC Register geschrieben und ich finde einfach meinen Fehler nicht.

Der Code:
1
#include <stm32f4xx.h>
2
#include "main.h"
3
4
5
6
uint16_t timerValues[48];
7
8
int main(void)
9
{
10
11
12
13
    create_testpattern(); //fill timerValues[]
14
15
    init_DMA();
16
    init_TIM();
17
18
    userbutton_init();
19
20
    GPIO_SetBits(GPIOD, GPIO_Pin_13);
21
    while(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)); //wait for user button
22
    GPIO_ResetBits(GPIOD, GPIO_Pin_13);
23
24
    TIM_Cmd(TIM3, ENABLE);
25
    DMA_Cmd(DMA1_Stream7, ENABLE);
26
    while(!DMA_GetCmdStatus(DMA1_Stream7)); //wait till stream is enabled
27
    TIM_DMACmd(TIM3, TIM_DMA_Update, ENABLE);
28
29
30
31
32
33
34
35
36
    while(1);
37
38
39
}
40
41
void DMA1_Stream7_IRQHandler(void) {
42
43
  DMA_ClearITPendingBit(DMA1_Stream7, DMA_IT_TCIF1);
44
  GPIO_SetBits(GPIOD, GPIO_Pin_13);
45
  DMA_Cmd(DMA1_Stream7, DISABLE);
46
47
}
48
49
void init_DMA(void){
50
51
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
52
53
  DMA_InitTypeDef DMA_InitStruct;
54
55
  DMA_InitStruct.DMA_BufferSize       = 48;
56
  DMA_InitStruct.DMA_Channel         = DMA_Channel_5;
57
  DMA_InitStruct.DMA_DIR           = DMA_DIR_MemoryToPeripheral;
58
  DMA_InitStruct.DMA_FIFOMode       = DMA_FIFOMode_Disable;
59
  DMA_InitStruct.DMA_FIFOThreshold     = DMA_FIFOThreshold_HalfFull;
60
  DMA_InitStruct.DMA_Memory0BaseAddr     = (uint32_t)&timerValues[0];
61
  DMA_InitStruct.DMA_MemoryBurst       = DMA_MemoryBurst_Single;
62
  DMA_InitStruct.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;
63
  DMA_InitStruct.DMA_MemoryInc       = DMA_MemoryInc_Enable;
64
  DMA_InitStruct.DMA_Mode         = DMA_Mode_Normal;
65
  DMA_InitStruct.DMA_PeripheralBaseAddr   = (uint32_t)&TIM3->CCR3 ;
66
  DMA_InitStruct.DMA_PeripheralDataSize   = DMA_PeripheralDataSize_HalfWord;
67
  DMA_InitStruct.DMA_PeripheralInc     = DMA_PeripheralInc_Disable;
68
  DMA_InitStruct.DMA_Priority       = DMA_Priority_Medium;
69
70
  DMA_Init(DMA1_Stream7, &DMA_InitStruct);
71
72
  DMA_ITConfig(DMA1_Stream7, DMA_IT_TC, ENABLE);
73
74
75
}
76
77
78
void init_TIM(void){
79
80
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
81
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB , ENABLE);
82
83
  TIM_DeInit(TIM3);
84
85
  GPIO_InitTypeDef GPIO_InitStruct;
86
87
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
88
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
89
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
90
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
91
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
92
  GPIO_Init(GPIOB, &GPIO_InitStruct);
93
94
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_TIM3);
95
96
97
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;
98
99
  TIM_TimeBaseStruct.TIM_Prescaler = 0;
100
  TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
101
  TIM_TimeBaseStruct.TIM_Period = 103;
102
  TIM_TimeBaseStruct.TIM_ClockDivision = 0;
103
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStruct);
104
105
  TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
106
107
  TIM_OCInitTypeDef TIM_OCInitStruct;
108
109
  TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
110
  TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
111
  TIM_OCInitStruct.TIM_Pulse = 95;
112
  TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
113
  TIM_OCInitStruct.TIM_OCIdleState = TIM_OCIdleState_Reset;
114
  TIM_OCInitStruct.TIM_OutputNState = TIM_OutputState_Disable;
115
  TIM_OCInitStruct.TIM_OCNPolarity = TIM_OCPolarity_High;
116
  TIM_OCInitStruct.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
117
  TIM_OC3Init(TIM3, &TIM_OCInitStruct);
118
119
120
  /* --- Interrupt DMA --- */
121
122
  NVIC_InitTypeDef NVIC_InitStructure;
123
124
  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream7_IRQn;
125
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
126
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
127
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
128
129
  NVIC_Init(&NVIC_InitStructure);
130
131
132
  TIM_DMACmd(TIM3, TIM_DMA_Update, DISABLE);
133
134
135
}

Ich beobachte ab dem Tasterdruck mit meinem Logic Sniffer. Das 
PWM-Signal hat hier immer den während der Timerinitialisierung 
eingestellten duty cycle (CCR3 = 95).

Ich hoffe mir kann jemand helfen

Gruß,
Alex

von benwilliam (Gast)


Lesenswert?

ich weis jetzt nicht wo bei dir der fehler ist
aber ich mache das gleiche evtl. hilft dir mein code:

https://github.com/benwilliam/equinox_clock/blob/master/WS2811/WS2811.c

von MarcusM (Gast)


Lesenswert?

Schau doch mal hier ;)

http://mikrocontroller.bplaced.net/wordpress/?page_id=980

Das wird dir sicher weiterhelfen^^
Und da gibts so ziemlich alles was dein Herz begehrt, was den 
STM32F4-Discovery angeht ;)
Gruß

von Alex (Gast)


Lesenswert?

Alles klar, danke erstmal :-)

ich werd mich da mal durchwursteln

von MarcusM (Gast)


Lesenswert?

sry falscher Link..
Hier der richtige:

http://mikrocontroller.bplaced.net/wordpress/?page_id=1462

aber denke das hast du selbst auch schon bemerkt ;)

von Alex (Gast)


Lesenswert?

Hab mein Problem nun gelöst.

Der Fehler lag einmal am Auswählen des falschen streams, für 
TIM3_DMA_Update wäre das stream 2.
Zum Anderen lag der Fehler an der standard periph lib version 1.0.0, 
welche statt Channel_5 immer den Channel 7 configuriert hat. Nach 
"updaten" der Lib funktioniert das aber nun auch richtig.

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.