Forum: Mikrocontroller und Digitale Elektronik STM32 Timer Start/Stop mit zweitem Timer


von timertick_t (Gast)


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

: Wiederhergestellt durch Admin
von Eric (Gast)


Lesenswert?

Wo ist dein main()?
Wie gross ist FREQUENCY --> gibt (FREQUENCY * 4) kein Überlauf?
Was macht die while(0) am Ende von timerSync()?

: Wiederhergestellt durch Admin
von Little B. (lil-b)


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.

: Wiederhergestellt durch Admin
von timertick_t (Gast)


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.

: Wiederhergestellt durch Admin
von timertick_t (Gast)


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.

: Wiederhergestellt durch Admin
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.