STM32 Timer Start/Stop mit zweitem Timer

Gast #4178353
Lesenswert?

Auf nem STM32F4 ist Timer 2 als PWM-Erzeuger konfiguriert (kein 
Interrupt, Slave-Mode, 2kHz). Timer 4 der als Master im Interrupt läuft 
soll ihn periodisch ein/ausschalten (3Hz).
Die beiden Timer arbeiten für sich alleine wie sie sollen, aber das 
zusammenwirken via "gated mode" schaltet den Slave-Timer nicht ab.

Jemand ne Idee?
1
/**
2
 ******************************************************************************
3
 * @file    timerSync.c
4
 * @author  timertick_t
5
 * @version
6
 * @date    25.06.2015
7
 * @brief   This file contains functions for timer sync example
8
 *
9
 ******************************************************************************
10
 */
11

12
#include "stm32f4xx.h"
13
#include "stm32f4_discovery.h"
14
#include "pwmTimer2.h"  //defines
15
#include "timerSync.h"
16

17
TIM_HandleTypeDef    Tim4Handle;
18

19
void timerSync(void) {
20
  /*
21
   Alignment:
22
   Timer 2 32-bit: PWM beep - PA1 TIM2_CH2
23

24
   Timer 3 16-bit: Resolver -  TI1 + TI2 = TIM3_CH1 + TIM3_CH2
25
   TIM3_CH1: PA6 PC6 PB4
26
   TIM3_CH2: PA7 PC7 PB5
27
   PC7 = MCLK (Audio)
28
   => TIM3_CH1: PC6
29
   => TIM3_CH2: PC7
30

31
   Timer 4 16-bit: IRQ call: LED blink
32
   Timer 5 16-bit:
33

34
   Table 97. TIMx internal trigger connection:
35
   ITR3 (TS = 011)
36
   => Timer 2: Slave
37
   => Timer 4: Master
38
   */
39

40

41
  BSP_LED_Init(LED5);
42
  BSP_LED_Init(LED6);
43
  // some household stuff
44
  if (HAL_Init() != HAL_OK) {
45
    /* Start Conversation Error */
46
    Error_Handler();
47
  }
48

49
  //Step 1:
50
  //Config slave, Timer 2 32-bit: PWM beep - PA1 TIM2_CH2
51
  // frequency 0x20E0 = 9.980kHz, 0xA400 = 2.000kHz
52
  // => Timer 2 32-bit: PWM beep - PA1 TIM2_CH2
53

54
  TIM_HandleTypeDef Tim2Handle;
55

56
  /* First and foremost: Enable TIM2 clock & Port */
57
  RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
58
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
59

60
  GPIO_InitTypeDef GPIO_InitStructure;
61
  GPIO_InitStructure.Pin = GPIO_PIN_1;
62
  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;  //Alternate function ! ! !
63
  GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
64
  GPIO_InitStructure.Pull = GPIO_NOPULL;
65
  GPIO_InitStructure.Alternate = GPIO_AF1_TIM2;
66
  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
67

68
  //Timer settings:
69
  //frequency determined by the value of the TIMx_ARR
70
  //duty cycle determined by the value of the TIMx_CCRx register
71

72
  /* Set TIM2 instance */
73
  Tim2Handle.Instance = TIM2;
74
  Tim2Handle.Init.Prescaler = 0;
75
  Tim2Handle.Init.CounterMode = TIM_COUNTERMODE_UP;
76
  Tim2Handle.Init.Period = FREQUENCY; // 0x20E0 = 9.980kHz, 0xA400 = 2.000kHz (presc = 0)
77
  Tim2Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 4 oder 1: kein Einfluss
78
  Tim2Handle.Init.RepetitionCounter = 0x10000;  // todo necessary?
79
  HAL_TIM_Base_Init(&Tim2Handle);
80

81
  TIM_ClockConfigTypeDef sConfigTIM_ClockConfig;
82
  sConfigTIM_ClockConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
83
  sConfigTIM_ClockConfig.ClockPolarity = TIM_CLOCKPOLARITY_RISING;
84
  sConfigTIM_ClockConfig.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1; // without influence 1, 2, 4, 8x
85
  sConfigTIM_ClockConfig.ClockFilter = 0;
86
  HAL_TIM_ConfigClockSource(&Tim2Handle, &sConfigTIM_ClockConfig);
87

88
  TIM_OC_InitTypeDef sConfigTIM_OC;
89
  sConfigTIM_OC.OCMode = TIM_OCMODE_PWM1;
90
  sConfigTIM_OC.Pulse = (FREQUENCY * 4) / 10; // duty; //--- duty cycle ---
91
  sConfigTIM_OC.OCPolarity = TIM_OCPOLARITY_HIGH;
92
  sConfigTIM_OC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
93
  sConfigTIM_OC.OCFastMode = TIM_OCFAST_ENABLE;
94
  sConfigTIM_OC.OCIdleState = TIM_OCIDLESTATE_RESET;
95
  sConfigTIM_OC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
96
  HAL_TIM_PWM_ConfigChannel(&Tim2Handle, &sConfigTIM_OC, TIM_CHANNEL_2);
97

98

99

100
  TIM_SlaveConfigTypeDef sSlaveConfig;
101

102
  /*!< Slave mode selection This parameter can be a value of @ref TIM_Slave_Mode */
103
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_GATED;
104

105
  /*!< Input Trigger source This parameter can be a value of @ref TIM_Trigger_Selection */
106
  //ITR3 (TS = 011): Timer 2 = Slave, Timer 4 = Master
107
  sSlaveConfig.InputTrigger = TIM_TS_ITR3;
108

109
  /*!< Input Trigger polarity This parameter can be a value of @ref TIM_Trigger_Polarity */
110
  sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING;
111

112
  /*!< Input trigger prescaler  This parameter can be a value of @ref TIM_Trigger_Prescaler */
113
  sSlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1;
114

115
  /*!< Input trigger filter  This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */
116
  sSlaveConfig.TriggerFilter = 0;
117

118

119
  //HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchronization(TIM_HandleTypeDef *htim,
120
  //                                                     TIM_SlaveConfigTypeDef * sSlaveConfig);
121
  HAL_TIM_SlaveConfigSynchronization(&Tim2Handle, &sSlaveConfig);
122

123
  HAL_TIM_PWM_Init(&Tim2Handle);
124

125
  HAL_TIM_PWM_Start(&Tim2Handle, TIM_CHANNEL_2);
126

127

128
  //######################################################################
129
  //Step 2:
130
  //Config master, on/off (blink)
131

132
   uint32_t uwPrescalerValue = (uint32_t) ((SystemCoreClock / 2) / 10000) - 1;
133

134
  /* First and foremost: Enable TIM clock & Port */
135
  // LED: GPIO B8
136
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
137

138
  //Timer 2
139
  RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
140

141
  //GPIO B8, today with open-drain
142
  GPIO_InitStructure.Pin = GPIO_PIN_8;
143
  GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;  // Open drain
144
  GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
145
  GPIO_InitStructure.Pull = GPIO_NOPULL;
146
  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
147
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);  // LED ON!
148
  //HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);  // LED OFF!
149

150
  /* Set TIMx instance */
151
  Tim4Handle.Instance = TIM4;
152
  Tim4Handle.Init.Period = 1000 - 1; //9999 = 0x270F
153
  Tim4Handle.Init.Prescaler = uwPrescalerValue;
154
  Tim4Handle.Init.ClockDivision = 0;
155
  Tim4Handle.Init.CounterMode = TIM_COUNTERMODE_UP;
156
  if (HAL_TIM_Base_Init(&Tim4Handle) != HAL_OK) {
157
    /* Initialization Error */
158
    Error_Handler();
159
  };
160

161
  TIM_MasterConfigTypeDef sTIM_MasterConfigTypeDef;
162
    /*!< Trigger output (TRGO) selection. This parameter can be a value of @ref TIM_Master_Mode_Selection */
163
  sTIM_MasterConfigTypeDef.MasterOutputTrigger = TIM_TRGO_ENABLE;
164

165
  /*!< Master/slave mode selection. This parameter can be a value of @ref TIM_Master_Slave_Mode */
166
  sTIM_MasterConfigTypeDef.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE ;
167
  //HAL_StatusTypeDef HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef* htim, TIM_MasterConfigTypeDef * sMasterConfig);
168
  HAL_TIMEx_MasterConfigSynchronization(&Tim4Handle, &sTIM_MasterConfigTypeDef);
169

170

171
  /*##-2- Start the TIM Base generation in interrupt mode ####################*/
172
  if (HAL_TIM_Base_Start_IT(&Tim4Handle) != HAL_OK) {
173
    /* Starting Error */
174
    Error_Handler();
175
  }
176
  while (0) {  };
177
}
178

179
/**
180
 * @brief  Period elapsed callback in non blocking mode
181
 * @param  htim: TIM handle
182
 * @retval None
183
 */
184
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
185
  if (htim) {  }; //dummy for compiler warning
186
  HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_8);
187
  // BSP_LED_Toggle(LED6);
188
}
189

190
/**
191
 *
192
 * From ... /stm32f4xx_hal_msp.c:
193
 *
194
 * @brief TIM MSP Initialization
195
 *        This function configures the hardware resources used in this example:
196
 *           - Peripheral's clock enable
197
 *           - Peripheral's GPIO Configuration
198
 * @param htim: TIM handle pointer
199
 * @retval None
200
 */
201
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim) {
202
  if (htim) {  }; //dummy
203

204
  /*##-1- Enable peripherals and GPIO Clocks #################################*/
205
  __HAL_RCC_TIM4_CLK_ENABLE();
206
  //TIM4_CLK_ENABLE();
207

208
  /*##-2- Configure the NVIC for TIMx ########################################*/
209
  /* Set Interrupt Group Priority */
210
  HAL_NVIC_SetPriority(TIM4_IRQn, 4, 0);
211

212
  /* Enable the TIMx global Interrupt */
213
  HAL_NVIC_EnableIRQ(TIM4_IRQn);
214
}
215

216
void Error_Handler(void) {
217
  BSP_LED_On(LED5);
218
  while (1) {  }
219
}
220

221
#if NO_CODE_HERE
222
#endif // #if NO_CODE_HERE
#4178975
Lesenswert?

timertick_t schrieb:
> Jemand ne Idee?

Zwei Kleinigkeiten fallen mir auf:
In step2 aktivierst du im RCC Tim2 und nicht Tim4!
Beim Prescaler des Tim4 unterscheidet sich der Wert und dein Kommentar 
um Faktor 10.

Leider arbeite ich nicht mit Bibliotheken und kann daher keine Aussage 
treffen, was da genau passiert. Zu prüfen wäre vor allem, ob die Timer 
laufen. Diese, in der CMSIS sehr explizite Anweißung, vermisse ich hier. 
Kann aber auch sein, dass
1
 HAL_TIM_PWM_Start(&Tim2Handle, TIM_CHANNEL_2);
 das mit übernimmt.
Gast #4179005
Lesenswert?

Autor: Eric (Gast) schrieb:
>Wo ist dein main()?
Das verrate ich nicht.

Oben schrieb ich:
>>Die beiden Timer arbeiten für sich alleine wie sie sollen, aber das
>>zusammenwirken via "gated mode" schaltet den Slave-Timer nicht ab.
Die Interrupt-Routine wird angesprungen, Bit 0 in TIMx_SR sollte also 
kommen:
Bit 0 UIF: Update interrupt flag
This bit is set by hardware on an update event. It is cleared by 
software.
0: No update occurred.
1: Update interrupt pending. This bit is set by hardware when the 
registers are updated.
At overflow or underflow (for TIM2 to TIM5) and if UDIS=0 in the 
TIMx_CR1 register.


>Wie gross ist FREQUENCY --> gibt (FREQUENCY * 4) kein Überlauf?
FREQUENCY = 0xA400, da passiert bei Timer2 als 32-Bit Zähler mit einem 
32-Bit breiten Register nichts böses. Ausserdem funktioniert der Timer 
als Standalone ja wie er soll, wie bereits beschrieben.

 Little Basdart (lil-b)
>In step2 aktivierst du im RCC Tim2 und nicht Tim4!
Die Zusammenhänge wären noch zu prüfen. Überhaupt ist das Verhalten 
seltsam, der Slave reagiert zwar auf entsprechende Schaltbits, aber 
nicht wie eigentlich erwartet.


>Beim Prescaler des Tim4 unterscheidet sich der Wert und dein Kommentar
>um Faktor 10.
Das macht nix, war nur rumgeblödel.
Gast #4179045
Lesenswert?

>Diese, in der CMSIS sehr explizite Anweißung, vermisse ich hier.
Beide vorhanden:
HAL_TIM_PWM_Start(&Tim2Handle, TIM_CHANNEL_2);
und
if (HAL_TIM_Base_Start_IT(&Tim4Handle) != HAL_OK) {...

Interessant aber wäre wirklich die Frage, was genau den TRGO auslöst: 
Ein Update des Timers oder ein gesetztes Interrupt-Bit.
Jedefalls wird das Auto-Reload-Register bedient. in der entsprechenden 
Init-Funktion in stm32f4xx_hal_tim.c fand ich:

  /* Set the Auto-reload value */
  TIMx->ARR = (uint32_t)Structure->Period;

Wie gesagt: Einzeln gehen die Biester. Ich habe mittlerweile auch einige 
Varianten ausprobiert; es ist immer das Zusammenspiel das nicht funzt.
Als ob ein grundsätzlichen Denkfehler vorliegt und der eigentliche 
Fehler wo ganz anders steckt. Dummerweise scheint's für diese 
Konstellation auch keine veröffentlichten Examples im Netz zu geben.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren