Forum: Mikrocontroller und Digitale Elektronik STM32 Timer synchronisieren


von Traubensaft .. (increasingcurrant)


Angehängte Dateien:

Lesenswert?

Hi,

ich möchte bei einem STM32F446RE Timer 1 und Timer 8 synchron laufen 
lassen. Als Trigger nehme ich dazu Timer 2.

Folgendes Setup:
Master: TIM2
- MSM bit gesetzt
- TRGO = Enable Bit (CNT_EN)

Slaves: TIM1, TIM8
- Salve Mode: Reset Mode
- Trigger Source: ITR1

Meine CubeMX-Konfiguration und die Auszüge aus AN4013 und dem Reference 
Manual, auf denen basierend ich meine Konfig erstellt habe sind im 
Anhang.

Ich nutze folgenden Code:
1
HAL_TIM_Base_Start(&htim2);
2
HAL_TIM_PWM_Start(&htim8, CH_LVL_1);
3
HAL_TIM_PWM_Start(&htim1, CH_LVL_2);

Die Idee dahinter: TIM2 generiert durch sein Enable-Bit das TRGO, das an 
ITR1 von TIM1 und TIM8 gelesen wird. Dadurch werden deren Enable-Bits 
zeitgleich gesetzt. HAL_TIM_PWM_Start(...) startet nur die Ausgabe der 
jeweiligen Kanäle; der Timer läuft bereits.

Leider sind die PWMs um 900 ns verschoben, das Counter-Enable-Bit wird 
also in Software gesetzt.

Was habe ich übersehen?
Vielen Dank für eure Tipps,

Traubensaft

von pegel (Gast)


Lesenswert?

Sehr sparsam dein Quelltext.

Hast Du dir die genannten Beispiele in der pdf angesehen?

Da findet sich so etwas wie: HAL_TIM_SlaveConfigSynchronization

von Traubensaft .. (increasingcurrant)


Angehängte Dateien:

Lesenswert?

Falls das missverständlich war: das PDF habe ich selbst erstellt; das 
sind nicht irgendwelche "Beispiele". Sie enthält die relevanten Auszüge 
der Herstellerdokumentation, sowie die Einstellungen die ich daraus für 
mein Projekt abgeleitet habe.

Anbei de Inhalt der tim.c-Datei, die CubeMX aus meinen Einstellungen 
generiert. In den Anhang packe ich die (ungetestete) main.c des 
Beispiels von ST aus dem Verzeichnis
1
\Repository\STM32Cube_FW_F4_V1.21.0\Projects\STM32446E_EVAL\Examples\TIM\TIM_ParallelSynchro\Src

1
/* Includes ------------------------------------------------------------------*/
2
#include "tim.h"
3
4
#include "gpio.h"
5
6
/* USER CODE BEGIN 0 */
7
8
/* USER CODE END 0 */
9
10
TIM_HandleTypeDef htim1;
11
TIM_HandleTypeDef htim2;
12
TIM_HandleTypeDef htim8;
13
14
/* TIM1 init function */
15
void MX_TIM1_Init(void)
16
{
17
  TIM_ClockConfigTypeDef sClockSourceConfig;
18
  TIM_SlaveConfigTypeDef sSlaveConfig;
19
  TIM_MasterConfigTypeDef sMasterConfig;
20
  TIM_OC_InitTypeDef sConfigOC;
21
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;
22
23
  htim1.Instance = TIM1;
24
  htim1.Init.Prescaler = 0;
25
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
26
  htim1.Init.Period = 1199;
27
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
28
  htim1.Init.RepetitionCounter = 0;
29
  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
30
  {
31
    _Error_Handler(__FILE__, __LINE__);
32
  }
33
34
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
35
  if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
36
  {
37
    _Error_Handler(__FILE__, __LINE__);
38
  }
39
40
  if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
41
  {
42
    _Error_Handler(__FILE__, __LINE__);
43
  }
44
45
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;
46
  sSlaveConfig.InputTrigger = TIM_TS_ITR1;
47
  if (HAL_TIM_SlaveConfigSynchronization(&htim1, &sSlaveConfig) != HAL_OK)
48
  {
49
    _Error_Handler(__FILE__, __LINE__);
50
  }
51
52
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
53
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
54
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
55
  {
56
    _Error_Handler(__FILE__, __LINE__);
57
  }
58
59
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
60
  sConfigOC.Pulse = 600;
61
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
62
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
63
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
64
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
65
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
66
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
67
  {
68
    _Error_Handler(__FILE__, __LINE__);
69
  }
70
71
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
72
  {
73
    _Error_Handler(__FILE__, __LINE__);
74
  }
75
76
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
77
  {
78
    _Error_Handler(__FILE__, __LINE__);
79
  }
80
81
  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
82
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
83
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
84
  sBreakDeadTimeConfig.DeadTime = 0;
85
  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
86
  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
87
  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
88
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
89
  {
90
    _Error_Handler(__FILE__, __LINE__);
91
  }
92
93
  HAL_TIM_MspPostInit(&htim1);
94
95
}
96
/* TIM2 init function */
97
void MX_TIM2_Init(void)
98
{
99
  TIM_ClockConfigTypeDef sClockSourceConfig;
100
  TIM_MasterConfigTypeDef sMasterConfig;
101
102
  htim2.Instance = TIM2;
103
  htim2.Init.Prescaler = 0;
104
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
105
  htim2.Init.Period = 0;
106
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
107
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
108
  {
109
    _Error_Handler(__FILE__, __LINE__);
110
  }
111
112
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
113
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
114
  {
115
    _Error_Handler(__FILE__, __LINE__);
116
  }
117
118
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_ENABLE;
119
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
120
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
121
  {
122
    _Error_Handler(__FILE__, __LINE__);
123
  }
124
125
}
126
/* TIM8 init function */
127
void MX_TIM8_Init(void)
128
{
129
  TIM_ClockConfigTypeDef sClockSourceConfig;
130
  TIM_SlaveConfigTypeDef sSlaveConfig;
131
  TIM_MasterConfigTypeDef sMasterConfig;
132
  TIM_OC_InitTypeDef sConfigOC;
133
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;
134
135
  htim8.Instance = TIM8;
136
  htim8.Init.Prescaler = 0;
137
  htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
138
  htim8.Init.Period = 1199;
139
  htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
140
  htim8.Init.RepetitionCounter = 0;
141
  if (HAL_TIM_Base_Init(&htim8) != HAL_OK)
142
  {
143
    _Error_Handler(__FILE__, __LINE__);
144
  }
145
146
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
147
  if (HAL_TIM_ConfigClockSource(&htim8, &sClockSourceConfig) != HAL_OK)
148
  {
149
    _Error_Handler(__FILE__, __LINE__);
150
  }
151
152
  if (HAL_TIM_PWM_Init(&htim8) != HAL_OK)
153
  {
154
    _Error_Handler(__FILE__, __LINE__);
155
  }
156
157
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;
158
  sSlaveConfig.InputTrigger = TIM_TS_ITR1;
159
  if (HAL_TIM_SlaveConfigSynchronization(&htim8, &sSlaveConfig) != HAL_OK)
160
  {
161
    _Error_Handler(__FILE__, __LINE__);
162
  }
163
164
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
165
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
166
  if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig) != HAL_OK)
167
  {
168
    _Error_Handler(__FILE__, __LINE__);
169
  }
170
171
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
172
  sConfigOC.Pulse = 600;
173
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
174
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
175
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
176
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
177
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
178
  if (HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
179
  {
180
    _Error_Handler(__FILE__, __LINE__);
181
  }
182
183
  if (HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
184
  {
185
    _Error_Handler(__FILE__, __LINE__);
186
  }
187
188
  sConfigOC.Pulse = 0;
189
  if (HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
190
  {
191
    _Error_Handler(__FILE__, __LINE__);
192
  }
193
194
  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
195
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
196
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
197
  sBreakDeadTimeConfig.DeadTime = 0;
198
  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
199
  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
200
  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
201
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim8, &sBreakDeadTimeConfig) != HAL_OK)
202
  {
203
    _Error_Handler(__FILE__, __LINE__);
204
  }
205
206
  HAL_TIM_MspPostInit(&htim8);
207
208
}
209
210
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
211
{
212
213
  GPIO_InitTypeDef GPIO_InitStruct;
214
  if(tim_baseHandle->Instance==TIM1)
215
  {
216
    /* USER CODE BEGIN TIM1_MspInit 0 */
217
218
    /* USER CODE END TIM1_MspInit 0 */
219
    /* TIM1 clock enable */
220
    __HAL_RCC_TIM1_CLK_ENABLE();
221
222
    /**TIM1 GPIO Configuration    
223
    PA8     ------> TIM1_CH1 
224
     */
225
    GPIO_InitStruct.Pin = TIM1_CH1_Pin;
226
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
227
    GPIO_InitStruct.Pull = GPIO_PULLDOWN;
228
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
229
    GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
230
    HAL_GPIO_Init(TIM1_CH1_GPIO_Port, &GPIO_InitStruct);
231
232
    /* USER CODE BEGIN TIM1_MspInit 1 */
233
234
    /* USER CODE END TIM1_MspInit 1 */
235
  }
236
  else if(tim_baseHandle->Instance==TIM2)
237
  {
238
    /* USER CODE BEGIN TIM2_MspInit 0 */
239
240
    /* USER CODE END TIM2_MspInit 0 */
241
    /* TIM2 clock enable */
242
    __HAL_RCC_TIM2_CLK_ENABLE();
243
    /* USER CODE BEGIN TIM2_MspInit 1 */
244
245
    /* USER CODE END TIM2_MspInit 1 */
246
  }
247
  else if(tim_baseHandle->Instance==TIM8)
248
  {
249
    /* USER CODE BEGIN TIM8_MspInit 0 */
250
251
    /* USER CODE END TIM8_MspInit 0 */
252
    /* TIM8 clock enable */
253
    __HAL_RCC_TIM8_CLK_ENABLE();
254
255
    /**TIM8 GPIO Configuration    
256
    PC6     ------> TIM8_CH1 
257
     */
258
    GPIO_InitStruct.Pin = TIM8_CH1_Pin;
259
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
260
    GPIO_InitStruct.Pull = GPIO_PULLDOWN;
261
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
262
    GPIO_InitStruct.Alternate = GPIO_AF3_TIM8;
263
    HAL_GPIO_Init(TIM8_CH1_GPIO_Port, &GPIO_InitStruct);
264
265
    /* USER CODE BEGIN TIM8_MspInit 1 */
266
267
    /* USER CODE END TIM8_MspInit 1 */
268
  }
269
}
270
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
271
{
272
273
  GPIO_InitTypeDef GPIO_InitStruct;
274
  if(timHandle->Instance==TIM1)
275
  {
276
    /* USER CODE BEGIN TIM1_MspPostInit 0 */
277
278
    /* USER CODE END TIM1_MspPostInit 0 */
279
    /**TIM1 GPIO Configuration    
280
    PA9     ------> TIM1_CH2
281
    PA10     ------> TIM1_CH3
282
    PA11     ------> TIM1_CH4 
283
     */
284
    GPIO_InitStruct.Pin = TIM1_CH2_PWM_LVL4_Pin|TIM1_CH3_PWM_LVL5_Pin|TIM1_CH4_PWM_LVL2_Pin;
285
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
286
    GPIO_InitStruct.Pull = GPIO_NOPULL;
287
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
288
    GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
289
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
290
291
    /* USER CODE BEGIN TIM1_MspPostInit 1 */
292
293
    /* USER CODE END TIM1_MspPostInit 1 */
294
  }
295
  else if(timHandle->Instance==TIM8)
296
  {
297
    /* USER CODE BEGIN TIM8_MspPostInit 0 */
298
299
    /* USER CODE END TIM8_MspPostInit 0 */
300
301
    /**TIM8 GPIO Configuration    
302
    PC7     ------> TIM8_CH2
303
    PC8     ------> TIM8_CH3
304
    PC9     ------> TIM8_CH4 
305
     */
306
    GPIO_InitStruct.Pin = TIM8_CH2_PWM_LVL3_Pin|TIM8_CH3_PWM_LVL1_Pin|TIM8_CH4_reserved_Pin;
307
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
308
    GPIO_InitStruct.Pull = GPIO_NOPULL;
309
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
310
    GPIO_InitStruct.Alternate = GPIO_AF3_TIM8;
311
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
312
313
    /* USER CODE BEGIN TIM8_MspPostInit 1 */
314
315
    /* USER CODE END TIM8_MspPostInit 1 */
316
  }
317
318
}
319
320
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
321
{
322
323
  if(tim_baseHandle->Instance==TIM1)
324
  {
325
    /* USER CODE BEGIN TIM1_MspDeInit 0 */
326
327
    /* USER CODE END TIM1_MspDeInit 0 */
328
    /* Peripheral clock disable */
329
    __HAL_RCC_TIM1_CLK_DISABLE();
330
331
    /**TIM1 GPIO Configuration    
332
    PA8     ------> TIM1_CH1
333
    PA9     ------> TIM1_CH2
334
    PA10     ------> TIM1_CH3
335
    PA11     ------> TIM1_CH4 
336
     */
337
    HAL_GPIO_DeInit(GPIOA, TIM1_CH1_Pin|TIM1_CH2_PWM_LVL4_Pin|TIM1_CH3_PWM_LVL5_Pin|TIM1_CH4_PWM_LVL2_Pin);
338
339
    /* USER CODE BEGIN TIM1_MspDeInit 1 */
340
341
    /* USER CODE END TIM1_MspDeInit 1 */
342
  }
343
  else if(tim_baseHandle->Instance==TIM2)
344
  {
345
    /* USER CODE BEGIN TIM2_MspDeInit 0 */
346
347
    /* USER CODE END TIM2_MspDeInit 0 */
348
    /* Peripheral clock disable */
349
    __HAL_RCC_TIM2_CLK_DISABLE();
350
    /* USER CODE BEGIN TIM2_MspDeInit 1 */
351
352
    /* USER CODE END TIM2_MspDeInit 1 */
353
  }
354
  else if(tim_baseHandle->Instance==TIM8)
355
  {
356
    /* USER CODE BEGIN TIM8_MspDeInit 0 */
357
358
    /* USER CODE END TIM8_MspDeInit 0 */
359
    /* Peripheral clock disable */
360
    __HAL_RCC_TIM8_CLK_DISABLE();
361
362
    /**TIM8 GPIO Configuration    
363
    PC6     ------> TIM8_CH1
364
    PC7     ------> TIM8_CH2
365
    PC8     ------> TIM8_CH3
366
    PC9     ------> TIM8_CH4 
367
     */
368
    HAL_GPIO_DeInit(GPIOC, TIM8_CH1_Pin|TIM8_CH2_PWM_LVL3_Pin|TIM8_CH3_PWM_LVL1_Pin|TIM8_CH4_reserved_Pin);
369
370
    /* USER CODE BEGIN TIM8_MspDeInit 1 */
371
372
    /* USER CODE END TIM8_MspDeInit 1 */
373
  }
374
} 
375
376
/* USER CODE BEGIN 1 */
377
378
/* USER CODE END 1 */
379
380
/**
381
 * @}
382
 */
383
384
/**
385
 * @}
386
 */
387
388
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

von pegel (Gast)


Lesenswert?

Mangels F446 habe ich angefangen alles auf einen F401 zu portieren.
Man muss ja erst einmal wissen, wie die Signale am Ende aussehen sollen.

Im Hinterkopf natürlich die eigentliche Frage und ob nicht noch eine 
andere Lösung möglich wäre.

Mit anderen Worten, das wurde mir zu viel Aufwand.

Vielleicht versucht sich noch einer daran, der einen F446 da hat.

von Traubensaft .. (increasingcurrant)


Lesenswert?

Wahnsinn was du dir für eine Mühe machst, vielen Dank!

Nun hat sich das Problem erledigt. In der Slave Configuration habe ich 
den falschen slave mode verwendet. Wenn man den "Trigger mode" anstelle 
des "Reset mode" wählt klappt es wie gewünscht.

: Bearbeitet durch User
von pegel (Gast)


Lesenswert?

Ich habe so etwas geahnt! ;)

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.