STM MATLAB Simulator
Loading...
Searching...
No Matches
stm32f4xx_matlab_tim.c
Go to the documentation of this file.
1/**
2**************************************************************************
3* @file stm32f4xx_matlab_tim.c
4* @brief Исходный код симулятора таймеров.
5**************************************************************************
6@details
7Данный файл содержит функции для симуляции таймеров STM32F407xx.
8**************************************************************************/
10
11
12
13struct SlaveChannels Slave_Channels; ///< структура для связи и синхронизации таймеров
14
15
16//----------------------TIMER BASE FUNCTIONS-----------------------//
17/**
18 * @brief Симуляция таймера на один такт симуляции.
19 * @param TIMx – таймер, каналы которого надо записать.
20 * @param TIMS – структура таймера для симуляции.
21 * @details Это базовая функция для симуляции таймера: она вызывается каждый шаг симуляции
22 * и вызывает все другие функции, необходимые для симуляции:
23 * - Overflow_Check()
24 * - Slave_Mode_Check_Source()
25 * - TIMx_Count()
26 * - Channels_Simulation()
27 */
28void TIM_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
29{
30 Overflow_Check(TIMx, TIMS);
31
32
33
34 // Выбор режима работы таймера
35 switch (TIMx->SMCR & TIM_SMCR_SMS) // TIMER MODE
36 {
37 // обычный счет
38 case(TIM_SLAVEMODE_DISABLE):// NORMAL MODE counting
39 TIMx_Count(TIMx, TIMS);
40 Channels_Simulation(TIMx, TIMS); // CaptureCompare and PWM channels simulation
41 break;
42
43
44 // включение слейв таймера по ивенту
45 case(TIM_SLAVEMODE_TRIGGER): // SLAVE MODE: TRIGGER MODE
46 Slave_Mode_Check_Source(TIMx, TIMS);
47 TIMx_Count(TIMx, TIMS);
48 Channels_Simulation(TIMx, TIMS); // CaptureCompare and PWM channels simulation
49 break;
50 }
51
52}
53/**
54 * @brief Симуляция счетчика таймера на один такт симуляции.
55 * @param TIMx – таймер, каналы которого надо записать.
56 * @param TIMS – структура таймера для симуляции.
57 * @details Данная функция проверяет направление таймера и увеличивает или уменьшает
58 * значение счетчика на то число, на которое оно бы увеличилось за шаг симуляции.
59 * @note Для счетчика используется double формат, т.к. кол-во счетов за шаг симуляции
60 может быть дробным. После в конце функции double счетчик записывает с округлением
61 в регистр таймера CNT.
62 */
63void TIMx_Count(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS)
64{
65 if ((TIMx->CR1 & TIM_CR1_DIR) && TIMx->CR1) // up COUNTER and COUNTER ENABLE
66 TIMS->tx_cnt -= TIMS->tx_step / TIMx->PSC;
67 else if (((TIMx->CR1 & TIM_CR1_DIR) == 0) && TIMx->CR1) // down COUNTER and COUNTER ENABLE
68 TIMS->tx_cnt += TIMS->tx_step / TIMx->PSC;
69 TIMx->CNT = (uint32_t)TIMS->tx_cnt;
70}
71
72/**
73 * @brief Проверка на переполнение и дальнейшая его обработка.
74 * @param TIMx – таймер, каналы которого надо записать.
75 * @param TIMS – структура таймера для симуляции.
76 * @details Данная функция проверяет когда таймер переполниться и если надо,
77 вызывает соответствующее прерывание:
78 - call_IRQHandller()
79 */
80void Overflow_Check(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS)
81{
82 // Переполнение таймера: сброс таймера и вызов прерывания
83 if ((TIMx->CR1 & TIM_CR1_UDIS) == 0) // UPDATE enable
84 {
85 if ((TIMx->CR1 & TIM_CR1_ARPE) == 0) TIMS->RELOAD = TIMx->ARR; // PRELOAD disable - update ARR every itteration
86 if (TIMS->tx_cnt > TIMS->RELOAD || TIMS->tx_cnt < 0) // OVERFLOW
87 {
88 TIMS->RELOAD = TIMx->ARR; // RELOAD ARR
89
90 if (TIMS->tx_cnt > TIMx->ARR) // reset COUNTER
91 TIMS->tx_cnt = 0;
92 else if (TIMS->tx_cnt < 0)
93 TIMS->tx_cnt = TIMx->ARR;
94
95 if(TIMx->DIER & TIM_DIER_UIE) // if update interrupt enable
96 call_IRQHandller(TIMx); // call HANDLER
97 }
98 }
99}
100//-----------------------------------------------------------------//
101
102
103
104//----------------------------CHANNELS-----------------------------//
105/**
106 * @brief Симуляция каналов таймера.
107 * @param TIMx – таймер, каналы которого надо записать.
108 * @param TIMS – структура таймера для симуляции.
109 * @details Данная функция симулирует работу всех каналов таймера.
110 * Она вызывает функции:
111 * - CC_PWM_Ch1_Simulation()
112 * - CC_PWM_Ch2_Simulation()
113 * - CC_PWM_Ch3_Simulation()
114 * - CC_PWM_Ch4_Simulation()
115 * - Write_OC_to_GPIO()
116 * - Write_OC_to_TRGO()
117 */
118void Channels_Simulation(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS)
119{
120 CC_PWM_Ch1_Simulation(TIMx, TIMS);
121 CC_PWM_Ch2_Simulation(TIMx, TIMS);
122 CC_PWM_Ch3_Simulation(TIMx, TIMS);
123 CC_PWM_Ch4_Simulation(TIMx, TIMS);
124
125 Write_OC_to_GPIO(TIMx, TIMS);
126
127 Write_OC_to_TRGO(TIMx, TIMS);
128}
129//-----------------CAPTURE COPMARE & PWM FUNCTIONS------------------//
130/**
131 * @brief Выбор режима первого канала и его симуляция.
132 * @param TIMx – таймер, каналы которого надо записать.
133 * @param TIMS – структура таймера для симуляции.
134 * @details Данная функция по регистрам таймера проверяет как настроен
135 первый канал и соответствующе симулирует его работу.
136 */
137void CC_PWM_Ch1_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
138{ // определяет режим канала
139switch (TIMx->CCMR1 & TIM_CCMR1_OC1M)
140{
141 case (TIM_OCMODE_ACTIVE): // ACTIVE mode
142 if (abs(TIMx->CNT - TIMx->CCR1) < 2*TIMS->tx_step)
143 TIMS->Channels.OC1REF = 1;
144 break;
145
146 case (TIM_OCMODE_INACTIVE): // INACTIVE mode
147 if (abs(TIMx->CNT - TIMx->CCR1) < 2*TIMS->tx_step)
148 TIMS->Channels.OC1REF = 0;
149 break;
150
151 case (TIM_OCMODE_TOGGLE): // TOOGLE mode
152 if (abs(TIMx->CNT - TIMx->CCR1) < 2*TIMS->tx_step)
153 TIMS->Channels.OC1REF = ~TIMS->Channels.OC1REF;
154 break;
155
156 case (TIM_OCMODE_PWM1): // PWM MODE 1 mode
157 if (TIMx->CNT < TIMx->CCR1)
158 TIMS->Channels.OC1REF = 1;
159 else
160 TIMS->Channels.OC1REF = 0;
161 break;
162
163 case (TIM_OCMODE_PWM2): // PWM MODE 2 mode
164 if (TIMx->CNT < TIMx->CCR1)
165 TIMS->Channels.OC1REF = 0;
166 else
167 TIMS->Channels.OC1REF = 1;
168 break;
169
170 case (TIM_OCMODE_FORCED_ACTIVE): // FORCED ACTIVE mode
171 TIMS->Channels.OC1REF = 1; break;
172
173 case (TIM_OCMODE_FORCED_INACTIVE): // FORCED INACTIVE mode
174 TIMS->Channels.OC1REF = 0; break;
175
176}
177}
178/**
179 * @brief Выбор режима второго канала и его симуляция.
180 * @param TIMx – таймер, каналы которого надо записать.
181 * @param TIMS – структура таймера для симуляции.
182 * @details Данная функция по регистрам таймера проверяет как настроен
183 второй канал и соответствующе симулирует его работу.
184 */
185void CC_PWM_Ch2_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
186{ // определяет режим канала
187switch (TIMx->CCMR1 & TIM_CCMR1_OC2M)
188{
189 case ((TIM_OCMODE_ACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // ACTIVE mode
190 if (abs(TIMx->CNT - TIMx->CCR2) < 2*TIMS->tx_step)
191 TIMS->Channels.OC2REF = 1;
192 break;
193
194 case ((TIM_OCMODE_INACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // INACTIVE mode
195 if (abs(TIMx->CNT - TIMx->CCR2) < 2*TIMS->tx_step)
196 TIMS->Channels.OC2REF = 0;
197 break;
198
199 case ((TIM_OCMODE_TOGGLE) << (TIM_OCMODE_SECOND_SHIFT)): // Toogle mode
200 if (abs(TIMx->CNT - TIMx->CCR2) < 2*TIMS->tx_step)
201 TIMS->Channels.OC2REF = ~TIMS->Channels.OC2REF;
202 break;
203
204 case ((TIM_OCMODE_PWM1) << (TIM_OCMODE_SECOND_SHIFT)): // PWM mode 1 mode
205 if (TIMx->CNT < TIMx->CCR2)
206 TIMS->Channels.OC2REF = 1;
207 else
208 TIMS->Channels.OC2REF = 0;
209 break;
210
211 case ((TIM_OCMODE_PWM2) << (TIM_OCMODE_SECOND_SHIFT)): // PWM mode 2 mode
212 if (TIMx->CNT < TIMx->CCR2)
213 TIMS->Channels.OC2REF = 0;
214 else
215 TIMS->Channels.OC2REF = 1;
216 break;
217
218 case ((TIM_OCMODE_FORCED_ACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // FORCED ACTIVE mode
219 TIMS->Channels.OC2REF = 1; break;
220
221 case ((TIM_OCMODE_FORCED_INACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // FORCED INACTIVE mode
222 TIMS->Channels.OC2REF = 0; break;
223
224}
225}
226/**
227 * @brief Выбор режима третьего канала и его симуляция.
228 * @param TIMx – таймер, каналы которого надо записать.
229 * @param TIMS – структура таймера для симуляции.
230 * @details Данная функция по регистрам таймера проверяет как настроен
231 третий канал и соответствующе симулирует его работу.
232 */
233void CC_PWM_Ch3_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
234{ // определяет режим канала
235switch (TIMx->CCMR2 & TIM_CCMR1_OC1M)
236{
237 case (TIM_OCMODE_ACTIVE): // ACTIVE mode
238 if (abs(TIMx->CNT - TIMx->CCR3) < 2*TIMS->tx_step)
239 TIMS->Channels.OC3REF = 1;
240 break;
241
242 case (TIM_OCMODE_INACTIVE): // INACTIVE mode
243 if (abs(TIMx->CNT - TIMx->CCR3) < 2*TIMS->tx_step)
244 TIMS->Channels.OC3REF = 0;
245 break;
246
247 case (TIM_OCMODE_TOGGLE): // Toogle mode
248 if (abs(TIMx->CNT - TIMx->CCR3) < 2*TIMS->tx_step)
249 TIMS->Channels.OC3REF = ~TIMS->Channels.OC3REF;
250 break;
251
252 case (TIM_OCMODE_PWM1): // PWM mode 1 mode
253 if (TIMx->CNT < TIMx->CCR3)
254 TIMS->Channels.OC3REF = 1;
255 else
256 TIMS->Channels.OC3REF = 0;
257 break;
258
259 case (TIM_OCMODE_PWM2): // PWM mode 2 mode
260 if (TIMx->CNT < TIMx->CCR3)
261 TIMS->Channels.OC3REF = 0;
262 else
263 TIMS->Channels.OC3REF = 1;
264 break;
265
266 case (TIM_OCMODE_FORCED_ACTIVE): // FORCED ACTIVE mode
267 TIMS->Channels.OC3REF = 1; break;
268
269 case (TIM_OCMODE_FORCED_INACTIVE): // FORCED INACTIVE mode
270 TIMS->Channels.OC3REF = 0; break;
271
272}
273}
274/**
275 * @brief Выбор режима четвертого канала и его симуляция.
276 * @param TIMx – таймер, каналы которого надо записать.
277 * @param TIMS – структура таймера для симуляции.
278 * @details Данная функция по регистрам таймера проверяет как настроен
279 четвертый канал и соответствующе симулирует его работу.
280 */
281void CC_PWM_Ch4_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
282{ // определяет режим канала
283switch (TIMx->CCMR2 & TIM_CCMR1_OC2M)
284{
285 case ((TIM_OCMODE_ACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // ACTIVE mode
286 if (abs(TIMx->CNT - TIMx->CCR4) < 2*TIMS->tx_step)
287 TIMS->Channels.OC4REF = 1;
288 break;
289
290 case ((TIM_OCMODE_INACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // INACTIVE mode
291 if (abs(TIMx->CNT - TIMx->CCR4) < 2*TIMS->tx_step)
292 TIMS->Channels.OC4REF = 0;
293 break;
294
295 case ((TIM_OCMODE_TOGGLE) << (TIM_OCMODE_SECOND_SHIFT)): // Toogle mode
296 if (abs(TIMx->CNT - TIMx->CCR4) < 2*TIMS->tx_step)
297 TIMS->Channels.OC4REF = ~TIMS->Channels.OC4REF;
298 break;
299
300 case ((TIM_OCMODE_PWM1) << (TIM_OCMODE_SECOND_SHIFT)): // PWM mode 1 mode
301 if (TIMx->CNT < TIMx->CCR4)
302 TIMS->Channels.OC4REF = 1;
303 else
304 TIMS->Channels.OC4REF = 0;
305 break;
306
307 case ((TIM_OCMODE_PWM2) << (TIM_OCMODE_SECOND_SHIFT)): // PWM mode 2 mode
308 if (TIMx->CNT < TIMx->CCR4)
309 TIMS->Channels.OC4REF = 0;
310 else
311 TIMS->Channels.OC4REF = 1;
312 break;
313
314 case ((TIM_OCMODE_FORCED_ACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // FORCED ACTIVE mode
315 TIMS->Channels.OC4REF = 1; break;
316
317 case ((TIM_OCMODE_FORCED_INACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // FORCED INACTIVE mode
318 TIMS->Channels.OC4REF = 0; break;
319
320}
321}
322
323/**
324 * @brief Запись каналов таймера в порты GPIO.
325 * @param TIMx – таймер, каналы которого надо записать.
326 * @param TIMS – структура того же таймера для симуляции.
327 * @details Данная функция записывает каналы OC в порты GPIO, определенные в TIMS.
328 * Запись происходит только если пин настроен на альтернативную функцию.
329 */
330void Write_OC_to_GPIO(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
331{
332 // write gpio pin if need
333 if (Check_OC1_GPIO_Output(TIMS)) // check OC OUTPUT 4 enable (GPIO AF MODE)
334 {
335 uint32_t temp2 = ~(uint32_t)(1 << (TIMS->Channels.OC1_PIN_SHIFT));
336 if (TIMx->CCER & TIM_CCER_CC1P) // POLARITY check
337 { // low POLARITY
338 if (TIMS->Channels.OC1REF)
339 TIMS->Channels.OC1_GPIOx->ODR &= ~(uint32_t)(1 << (TIMS->Channels.OC1_PIN_SHIFT));
340 else
341 TIMS->Channels.OC1_GPIOx->ODR |= 1 << (TIMS->Channels.OC1_PIN_SHIFT);
342 }
343 else
344 { // high POLARITY
345 if (TIMS->Channels.OC1REF)
346 TIMS->Channels.OC1_GPIOx->ODR |= 1 << (TIMS->Channels.OC1_PIN_SHIFT);
347 else
348 TIMS->Channels.OC1_GPIOx->ODR &= ~(uint32_t)(1 << (TIMS->Channels.OC1_PIN_SHIFT));
349 }
350 }
351 if (Check_OC2_GPIO_Output(TIMS)) // check OC OUTPUT 4 enable (GPIO AF MODE)
352 {
353 if (TIMx->CCER & TIM_CCER_CC2P) // POLARITY check
354 { // low POLARITY
355 if (TIMS->Channels.OC2REF)
356 TIMS->Channels.OC2_GPIOx->ODR &= ~(uint32_t)(1 << (TIMS->Channels.OC2_PIN_SHIFT));
357 else
358 TIMS->Channels.OC2_GPIOx->ODR |= 1 << (TIMS->Channels.OC2_PIN_SHIFT);
359 }
360 else
361 { // high POLARITY
362 if (TIMS->Channels.OC2REF)
363 TIMS->Channels.OC2_GPIOx->ODR |= 1 << (TIMS->Channels.OC2_PIN_SHIFT);
364 else
365 TIMS->Channels.OC2_GPIOx->ODR &= ~(uint32_t)(1 << (TIMS->Channels.OC2_PIN_SHIFT));
366 }
367 }
368 if (Check_OC3_GPIO_Output(TIMS)) // check OC OUTPUT 4 enable (GPIO AF MODE)
369 {
370 if (TIMx->CCER & TIM_CCER_CC3P) // POLARITY check
371 { // low POLARITY
372 if (TIMS->Channels.OC3REF)
373 TIMS->Channels.OC3_GPIOx->ODR &= ~(uint32_t)(1 << (TIMS->Channels.OC3_PIN_SHIFT));
374 else
375 TIMS->Channels.OC3_GPIOx->ODR |= 1 << (TIMS->Channels.OC3_PIN_SHIFT);
376 }
377 else
378 { // high POLARITY
379 if (TIMS->Channels.OC3REF)
380 TIMS->Channels.OC3_GPIOx->ODR |= 1 << (TIMS->Channels.OC3_PIN_SHIFT);
381 else
382 TIMS->Channels.OC3_GPIOx->ODR &= ~(uint32_t)(1 << (TIMS->Channels.OC3_PIN_SHIFT));
383 }
384 }
385 if (Check_OC4_GPIO_Output(TIMS)) // check OC CHANNEL 4 enable (GPIO AF MODE)
386 {
387 if (TIMx->CCER & TIM_CCER_CC4P) // POLARITY check
388 { // low POLARITY
389 if (TIMS->Channels.OC4REF)
390 TIMS->Channels.OC4_GPIOx->ODR &= ~(uint32_t)(1 << (TIMS->Channels.OC4_PIN_SHIFT));
391 else
392 TIMS->Channels.OC4_GPIOx->ODR |= (1) << (TIMS->Channels.OC4_PIN_SHIFT);
393 }
394 else
395 { // high POLARITY
396 if (TIMS->Channels.OC4REF)
397 TIMS->Channels.OC4_GPIOx->ODR |= (1) << (TIMS->Channels.OC4_PIN_SHIFT);
398 else
399 TIMS->Channels.OC4_GPIOx->ODR &= ~(uint32_t)(1 << (TIMS->Channels.OC4_PIN_SHIFT));
400 }
401 }
402}
403/** Запись результата compare в глабальную структуру с TRIGGER OUTPUT */
404/**
405 * @brief Запись каналов таймера в глабальную структуру с TRIGGER OUTPUT.
406 * @param TIMx – таймер, каналы которого надо записать.
407 * @param TIMS – структура того же таймера для симуляции.
408 * @details Данная функция считывает каналы OC и записывает их в внешний канал триггера TRGO.
409 */
410void Write_OC_to_TRGO(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS)
411{
412 // write trigger output from OCxREF pin if need
413 unsigned temp_trgo;
414 if ((TIMx->CR2 & TIM_CR2_MMS) == (0b100 << TIM_CR2_MMS_Pos))
415 {
416 temp_trgo = TIMS->Channels.OC1REF;
417 }
418 else if ((TIMx->CR2 & TIM_CR2_MMS) == (0b101 << TIM_CR2_MMS_Pos))
419 {
420 temp_trgo = TIMS->Channels.OC2REF;
421 }
422 else if ((TIMx->CR2 & TIM_CR2_MMS) == (0b110 << TIM_CR2_MMS_Pos))
423 {
424 temp_trgo = TIMS->Channels.OC3REF;
425 }
426 else if ((TIMx->CR2 & TIM_CR2_MMS) == (0b111 << TIM_CR2_MMS_Pos))
427 {
428 temp_trgo = TIMS->Channels.OC4REF;
429 }
430 // select TIMx TRGO
431 if (TIMx == TIM1)
432 Slave_Channels.TIM1_TRGO = temp_trgo;
433 else if (TIMx == TIM2)
434 Slave_Channels.TIM2_TRGO = temp_trgo;
435 else if (TIMx == TIM3)
436 Slave_Channels.TIM3_TRGO = temp_trgo;
437 else if (TIMx == TIM4)
438 Slave_Channels.TIM4_TRGO = temp_trgo;
439 else if (TIMx == TIM5)
440 Slave_Channels.TIM5_TRGO = temp_trgo;
441 else if (TIMx == TIM6)
442 Slave_Channels.TIM6_TRGO = temp_trgo;
443 else if (TIMx == TIM7)
444 Slave_Channels.TIM7_TRGO = temp_trgo;
445 else if (TIMx == TIM8)
446 Slave_Channels.TIM8_TRGO = temp_trgo;
447 temp_trgo = 0;
448}
449//------------------------------------------------------------------//
450
451
452
453
454//--------------------MISC (temporary) FUNCTIONS--------------------//
455/** Определение источника для запуска таймера в SLAVE MODE */
456/**
457 * @brief Определение источника для запуска таймера в SLAVE MODE.
458 * @param TIMx – таймер, который надо включить.
459 * @param TIMx – таймер, прерываний которого надо вызвать.
460 * @details Данная функция проверяет какой триггер выбран для запуска таймера,
461 * после записывает значение канала триггера в бит включения таймера.
462 * Таким образом, при лог.1 в канале триггера - таймер включиться.
463 */
464void Slave_Mode_Check_Source(TIM_TypeDef* TIMx)
465{
466 if (TIMx == TIM2)
467 {
468 if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR0)
469 TIMx->CR1 |= (Slave_Channels.TIM1_TRGO << TIM_CR1_CEN_Pos);
470 else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR1)
471 TIMx->CR1 |= (Slave_Channels.TIM1_TRGO << TIM_CR1_CEN_Pos);
472 else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR2)
473 TIMx->CR1 |= (Slave_Channels.TIM1_TRGO << TIM_CR1_CEN_Pos);
474 else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR3)
475 TIMx->CR1 |= (Slave_Channels.TIM8_TRGO << TIM_CR1_CEN_Pos);
476 }
477 else if (TIMx == TIM3)
478 {
479 if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR0)
480 TIMx->CR1 |= (Slave_Channels.TIM8_TRGO << TIM_CR1_CEN_Pos);
481 else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR1)
482 TIMx->CR1 |= (Slave_Channels.TIM2_TRGO << TIM_CR1_CEN_Pos);
483 else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR2)
484 TIMx->CR1 |= (Slave_Channels.TIM2_TRGO << TIM_CR1_CEN_Pos);
485 else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR3)
486 TIMx->CR1 |= (Slave_Channels.TIM3_TRGO << TIM_CR1_CEN_Pos);
487 }
488 else if (TIMx == TIM4)
489 {
490 if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR0)
491 TIMx->CR1 |= (Slave_Channels.TIM3_TRGO << TIM_CR1_CEN_Pos);
492 else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR1)
493 TIMx->CR1 |= (Slave_Channels.TIM5_TRGO << TIM_CR1_CEN_Pos);
494 else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR2)
495 TIMx->CR1 |= (Slave_Channels.TIM3_TRGO << TIM_CR1_CEN_Pos);
496 else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR3)
497 TIMx->CR1 |= (Slave_Channels.TIM4_TRGO << TIM_CR1_CEN_Pos);
498 }
499 else if (TIMx == TIM5)
500 {
501 if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR0)
502 TIMx->CR1 |= (Slave_Channels.TIM4_TRGO << TIM_CR1_CEN_Pos);
503 else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR1)
504 TIMx->CR1 |= (Slave_Channels.TIM4_TRGO << TIM_CR1_CEN_Pos);
505 else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR2)
506 TIMx->CR1 |= (Slave_Channels.TIM7_TRGO << TIM_CR1_CEN_Pos);
507 else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR3)
508 TIMx->CR1 |= (Slave_Channels.TIM7_TRGO << TIM_CR1_CEN_Pos);
509 }
510}
511//------------------------------------------------------------------//
512
513
514//------------------------SIMULINK FUNCTIONS------------------------//
515/** Симулирование выбранных через дефайн таймеров */
516/**
517 * @brief Симуляция выбранных таймеров.
518 * @details Таймеры для симуляции выбираются через дефайны в stm32f4xx_matlab_conf.h.
519 Функция вызывается на каждом шаге симуляции.
520 */
522{
523#ifdef USE_TIM1
524 TIM_Simulation(TIM1, &tim1s);
525#endif
526#ifdef USE_TIM2
527 TIM_Simulation(TIM2, &tim2s);
528#endif
529#ifdef USE_TIM3
530 TIM_Simulation(TIM3, &tim3s);
531#endif
532#ifdef USE_TIM4
533 TIM_Simulation(TIM4, &tim4s);
534#endif
535#ifdef USE_TIM5
536 TIM_Simulation(TIM5, &tim5s);
537#endif
538#ifdef USE_TIM6
539 TIM_Simulation(TIM6, &tim6s);
540#endif
541#ifdef USE_TIM7
542 TIM_Simulation(TIM7, &tim7s);
543#endif
544#ifdef USE_TIM8
545 TIM_Simulation(TIM8, &tim8s);
546#endif
547#ifdef USE_TIM9
548 TIM_Simulation(TIM9, &tim9s);
549#endif
550#ifdef USE_TIM10
551 TIM_Simulation(TIM10, &tim10s);
552#endif
553#ifdef USE_TIM11
554 TIM_Simulation(TIM11, &tim11s);
555#endif
556#ifdef USE_TIM12
557 TIM_Simulation(TIM12, &tim12s);
558#endif
559#ifdef USE_TIM13
560 TIM_Simulation(TIM13, &tim13s);
561#endif
562#ifdef USE_TIM14
563 TIM_Simulation(TIM14, &tim14s);
564#endif
565}
566/**
567 * @brief Деинициализирование выбранных таймеров.
568 * @details Таймеры для деинициализизации выбираются через дефайны в stm32f4xx_matlab_conf.h.
569 Функция вызывается в конце симуляции.
570 */
572{
573#ifdef USE_TIM1
574 memset(&tim1s, 0, sizeof(tim1s));
575#endif
576#ifdef USE_TIM2
577 memset(&tim2s, 0, sizeof(tim2s));
578#endif
579#ifdef USE_TIM3
580 memset(&tim3s, 0, sizeof(tim3s));
581#endif
582#ifdef USE_TIM4
583 memset(&tim4s, 0, sizeof(tim4s));
584#endif
585#ifdef USE_TIM5
586 memset(&tim5s, 0, sizeof(tim5s));
587#endif
588#ifdef USE_TIM6
589 memset(&tim6s, 0, sizeof(tim6s));
590#endif
591#ifdef USE_TIM7
592 memset(&tim7s, 0, sizeof(tim7s));
593#endif
594#ifdef USE_TIM8
595 memset(&tim8s, 0, sizeof(tim8s));
596#endif
597#ifdef USE_TIM9
598 memset(&tim9s, 0, sizeof(tim9s));
599#endif
600#ifdef USE_TIM10
601 memset(&tim10s, 0, sizeof(tim10s));
602#endif
603#ifdef USE_TIM11
604 memset(&tim11s, 0, sizeof(tim11s));
605#endif
606#ifdef USE_TIM12
607 memset(&tim12s, 0, sizeof(tim12s));
608#endif
609#ifdef USE_TIM13
610 memset(&tim13s, 0, sizeof(tim13s));
611#endif
612#ifdef USE_TIM14
613 memset(&tim14s, 0, sizeof(tim14s));
614#endif
615}
616//------------------------------------------------------------------//
617
618//------------------TIM'S HANDLERS (BETA) FUNCTIONS-----------------//
619// Определение обработчиков, которые не используются
620// Т.к. в MSVC нет понятия weak function, необходимо объявить все колбеки
621// И если какой-то колбек не используется, его надо определить
622#ifndef USE_TIM1_UP_TIM10_HANDLER
624#endif
625#ifndef USE_TIM2_HANDLER
626void TIM2_IRQHandler(void) {}
627#endif
628#ifndef USE_TIM3_HANDLER
629void TIM3_IRQHandler(void) {}
630#endif
631#ifndef USE_TIM4_HANDLER
632void TIM4_IRQHandler(void) {}
633#endif
634#ifndef USE_TIM5_HANDLER
635void TIM5_IRQHandler(void) {}
636#endif
637#ifndef USE_TIM6_HANDLER
639#endif
640#ifndef USE_TIM7_HANDLER
641void TIM7_IRQHandler(void) {}
642#endif
643#ifndef USE_TIM8_UP_TIM13_HANDLER
645#endif
646#ifndef USE_TIM1_BRK_TIM9_HANDLER
648#endif
649#ifndef USE_TIM1_TRG_COM_TIM11_HANDLER
651#endif
652#ifndef USE_TIM8_BRK_TIM12_HANDLER
654#endif
655#ifndef USE_TIM8_TRG_COM_TIM14_HANDLER
657#endif
658
659/**
660 * @brief Вызов прерывания таймера TIMx.
661 * @param TIMx – таймер, прерываний которого надо вызвать.
662 * @details Данная функция симулирует аппаратный вызов прерывания
663 таймера по какому-либо событию.
664 */
665void call_IRQHandller(TIM_TypeDef* TIMx)
666{ // calling HANDLER
667 if ((TIMx == TIM1) || (TIMx == TIM10))
669 else if (TIMx == TIM2)
671 else if (TIMx == TIM3)
673 else if (TIMx == TIM4)
675 else if (TIMx == TIM5)
677 else if (TIMx == TIM6)
679 else if (TIMx == TIM7)
681 else if ((TIMx == TIM8) || (TIMx == TIM13))
683 else if ((TIMx == TIM1) || (TIMx == TIM9))
685 else if ((TIMx == TIM1) || (TIMx == TIM11))
687 else if ((TIMx == TIM8) || (TIMx == TIM12))
689 else if ((TIMx == TIM8) || (TIMx == TIM14))
691}
692//------------------------------------------------------------------//
void Overflow_Check(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
Проверка на переполнение и дальнейшая его обработка.
#define Check_OC3_GPIO_Output(_tims_)
Дефайн для проверки выводить ли канал 3 на GPIO (настроен ли GPIO на альтернативную функцию)
void Write_OC_to_GPIO(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
Запись каналов таймера в порты GPIO.
void Simulate_TIMs(void)
Симуляция выбранных таймеров.
void TIM_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
Симуляция таймера на один такт симуляции.
void Write_OC_to_TRGO(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
Запись каналов таймера в глабальную структуру с TRIGGER OUTPUT.
void TIM_SIM_DEINIT(void)
Деинициализирование выбранных таймеров.
void TIMx_Count(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
Симуляция счетчика таймера на один такт симуляции.
void CC_PWM_Ch1_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
Выбор режима первого канала и его симуляция.
void Slave_Mode_Check_Source(TIM_TypeDef *TIMx)
Определение источника для запуска таймера в SLAVE MODE.
void Channels_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
Симуляция каналов таймера.
#define Check_OC1_GPIO_Output(_tims_)
Дефайн для проверки выводить ли канал 1 на GPIO (настроен ли GPIO на альтернативную функцию)
void CC_PWM_Ch3_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
Выбор режима третьего канала и его симуляция.
void call_IRQHandller(TIM_TypeDef *TIMx)
Вызов прерывания таймера TIMx.
#define Check_OC2_GPIO_Output(_tims_)
Дефайн для проверки выводить ли канал 2 на GPIO (настроен ли GPIO на альтернативную функцию)
void CC_PWM_Ch4_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
Выбор режима четвертого канала и его симуляция.
#define Check_OC4_GPIO_Output(_tims_)
Дефайн для проверки выводить ли канал 4 на GPIO (настроен ли GPIO на альтернативную функцию)
#define TIM_OCMODE_SECOND_SHIFT
Дефайн для сдвига между первой и второй половиной CCMRx регистров
void CC_PWM_Ch2_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
Выбор режима второго канала и его симуляция.
struct TIM_Sim tim1s
struct TIM_Sim tim4s
struct TIM_Sim tim12s
struct TIM_Sim tim3s
struct TIM_Sim tim7s
void TIM6_DAC_IRQHandler(void)
void TIM1_TRG_COM_TIM11_IRQHandler(void)
void TIM8_BRK_TIM12_IRQHandler(void)
void TIM2_IRQHandler(void)
void TIM1_BRK_TIM9_IRQHandler(void)
void TIM8_TRG_COM_TIM14_IRQHandler(void)
void TIM5_IRQHandler(void)
struct SlaveChannels Slave_Channels
структура для связи и синхронизации таймеров
void TIM4_IRQHandler(void)
void TIM8_UP_TIM13_IRQHandler(void)
void TIM7_IRQHandler(void)
void TIM3_IRQHandler(void)
void TIM1_UP_TIM10_IRQHandler(void)
Заголовочный файл для симулятора таймеров.
GPIO_TypeDef * OC2_GPIOx
Порт второго канала
unsigned OC4REF
Четвертый канал
uint32_t OC1_PIN_SHIFT
Пин первого канала
GPIO_TypeDef * OC1_GPIOx
Порт первого канала
GPIO_TypeDef * OC3_GPIOx
Порт третьего канала
GPIO_TypeDef * OC4_GPIOx
Порт четвертого канала
unsigned OC2REF
Второй канал
uint32_t OC4_PIN_SHIFT
Пин четвертого канала
unsigned OC1REF
Первый канал
unsigned OC3REF
Третьий канал
uint32_t OC3_PIN_SHIFT
Пин третьего канала
uint32_t OC2_PIN_SHIFT
Пин второго канала
Структура для управления Слейв Таймерами
unsigned TIM1_TRGO
Синган синхронизации таймера 1.
unsigned TIM6_TRGO
Синган синхронизации таймера 6.
unsigned TIM8_TRGO
Синган синхронизации таймера 8
unsigned TIM2_TRGO
Синган синхронизации таймера 2.
unsigned TIM7_TRGO
Синган синхронизации таймера 7.
unsigned TIM5_TRGO
Синган синхронизации таймера 5.
unsigned TIM3_TRGO
Синган синхронизации таймера 3.
unsigned TIM4_TRGO
Синган синхронизации таймера 4.
Структура для моделирования таймера
int RELOAD
Буфер для периода таймера (для реализации функции PRELOAD)
double tx_cnt
Счетчик таймера (double, т.к. кол-во тактов за шаг симуляции может быть дробным)
struct Channels_Sim Channels
Структура для симуляции каналов
double tx_step
Шаг счета за один шаг симуляции (double, т.к. кол-во тактов за шаг симуляции может быть дробным)