Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Кармин Новиелло - Освоение STM32.pdf
Скачиваний:
2740
Добавлен:
23.09.2021
Размер:
47.68 Mб
Скачать

Таймеры

315

Рисунок 8: Как выбрать режим ETR1 в IP tree pane

После выбора источника тактового сигнала можно настроить другие параметры конфигурации в диалоговом окне конфигурации таймера (здесь не показано).

11.3.2. Режимы синхронизации ведущего/ведомого таймеров

Когда таймер работает в режиме ведущего, он может питать другой таймер, сконфигурированный в режиме ведомого, через специальную выходную линию, называемую триггерным выходом (Trigger Output, TRGO)23, подключенную к внутренним выделенным линиям, называемым ITR0, ITR1, ITR2 и ITR3. Ведущий таймер может либо обеспечить источник тактового сигнала (и, следовательно, действовать как предделитель первого порядка – это то, что мы изучали в предыдущем параграфе), либо запустить ведомый таймер.

Линии внутренних триггеров (Internal Trigger, ITR: ITR0, ITR1, ITR2 и ITR3) являются именно внутренними по отношению к микросхеме, и каждая линия подключена между двумя определенными таймерами. Например, в микроконтроллере STM32F030 линия TRGO таймера TIM1 подключена к линии ITR0 таймера TIM2, как показано на рисунке

9.

Рисунок 9: TIM1 может питать таймер TIM2 через линию ITR0

Таймер, сконфигурированный в качестве ведомого, может одновременно выступать в качестве ведущего для другого таймера, что позволяет создавать сложные сети таймеров. Например, на рисунке 10 показано, как таймеры могут быть подключены каскадно, а на рисунке 11 показано, как таймеры могут формировать иерархические структуры, используя комбинации режимов ведомого/ведущего. Обратите внимание, что TIM1, TIM2 и TIM3 внутренне связаны через одну и ту же линию ITR0. Это позволяет синхронизировать несколько таймеров одним и тем же событием (сброс, включение, обновление и т. д.).

23 Некоторые микроконтроллеры STM32, особенно STM32F3, предоставляют две независимые линии запуска, называемые TRGO1 и TRGO2. Этот случай не показан в данной книге.

Таймеры

316

Рисунок 10: Комбинация режимов ведущего/ведомого позволяет конфигурировать таймеры каскадно

Рисунок 11: Комбинация режимов ведущего/ведомого позволяет конфигурировать таймеры в иерархическую структуру

Для конфигурации таймера в режиме ведущего мы используем функцию HAL_TIMEx_Mas-

terConfigSynchronization() и экземпляр структуры TIM_MasterConfigTypeDef, которая

определена следующим образом:

typedef struct {

 

 

 

 

uint32_t

MasterOutputTrigger;

/*

Выбор

триггерного выхода (TRGO)

*/

uint32_t

MasterSlaveMode;

/*

Выбор

режима ведущего/ведомого

*/

} TIM_MasterConfigTypeDef;

MasterOutputTrigger: задает поведение выхода TRGO и может принимать значе-

ние из таблицы 14.

MasterSlaveMode: используется для включения/отключения режима ведущего/ве-

домого таймера. Может принимать значения TIM_MASTERSLAVEMODE_ENABLE или

TIM_MASTERSLAVEMODE_DISABLE.

Таймеры

317

Таблица 14: Доступные источники запуска/тактирования для таймера, работающего в режиме ведомого (автор скопировал название таблицы и забыл исправить его)

Выбор режима ведущего таймера

Описание

 

 

TIM_TRGO_RESET

Сигнал TRGO генерируется, когда установлен бит UG

 

регистра TIMx->EGR. Подробнее об этом в параграфе

 

11.3.3.

TIM_TRGO_ENABLE

Сигнал TRGO генерируется при включении ведущего таймера. Полезен для одновременного запуска нескольких таймеров или для управления временным окном, в котором ведомый таймер включается.

TIM_TRGO_UPDATE

Событие обновления выбрано в качестве триггерного выхода (TRGO). Например, ведущий таймер может затем использоваться в качестве предделителя для ведомого таймера (мы изучили этот режим в параграфе

11.3.1.2).

TIM_TRGO_OC1

TIM_TRGO_OC1REF

Триггерный выход посылает положительный импульс, как только происходит захват или сравнение.

Триггерный выход посылает положительный импульс, как только на канале 1 происходит захват или сравнение.

TIM_TRGO_OC2REF

Триггерный выход посылает положительный импульс, как только на канале 2 происходит захват или сравнение.

TIM_TRGO_OC3REF

Триггерный выход посылает положительный импульс, как только на канале 3 происходит захват или сравнение.

TIM_TRGO_OC4REF

Триггерный выход посылает положительный импульс, как только на канале 4 происходит захват или сравнение.

Давайте рассмотрим пример, который показывает, как сконфигурировать TIM1 и TIM3

вкаскадном режиме, где TIM1 в качестве ведущего для таймера TIM3. TIM1 используется

вкачестве источника тактового сигнала для TIM3 через линию ITR0. Кроме того, TIM1 сконфигурирован так, что он начинает отсчитывать от внешнего события в своей линии TI1FP1, которая в Nucleo-F030 соответствует выводу PA8: TIM1 начинает отсчет, когда вывод PA8 становится высоким, а затем он питает таймер TIM3 через линию ITR0.

Имя файла: src/main-ex5.c

12int main(void) {

13HAL_Init();

14

15Nucleo_BSP_Init();

16MX_TIM1_Init();

17MX_TIM3_Init();

19

HAL_TIM_Base_Start_IT(&htim3);

20

 

21while (1);

22}

23

24 void MX_TIM1_Init(void) {

Таймеры

318

25TIM_ClockConfigTypeDef sClockSourceConfig;

26TIM_MasterConfigTypeDef sMasterConfig;

27TIM_SlaveConfigTypeDef sSlaveConfig;

28

29htim1.Instance = TIM1;

30htim1.Init.Prescaler = 47999;

31htim1.Init.CounterMode = TIM_COUNTERMODE_UP;

32htim1.Init.Period = 249;

33htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

34htim1.Init.RepetitionCounter = 0;

35HAL_TIM_Base_Init(&htim1);

36

37sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;

38HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig);

39

40sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;

41sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;

42sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING;

43sSlaveConfig.TriggerFilter = 15;

44HAL_TIM_SlaveConfigSynchronization(&htim1, &sSlaveConfig);

46sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;

47sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;

48HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);

49}

51void MX_TIM3_Init(void) {

52TIM_SlaveConfigTypeDef sSlaveConfig;

54htim3.Instance = TIM3;

55htim3.Init.Prescaler = 0;

56htim3.Init.CounterMode = TIM_COUNTERMODE_UP;

57htim3.Init.Period = 1;

58htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

59

HAL_TIM_Base_Init(&htim3);

60

 

61sSlaveConfig.SlaveMode = TIM_SLAVEMODE_EXTERNAL1;

62sSlaveConfig.InputTrigger = TIM_TS_ITR0;

63HAL_TIM_SlaveConfigSynchronization(&htim3, &sSlaveConfig);

65HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);

66HAL_NVIC_EnableIRQ(TIM3_IRQn);

67}

68

69void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base) {

70GPIO_InitTypeDef GPIO_InitStruct;

71if(htim_base->Instance==TIM3) {

72__HAL_RCC_TIM3_CLK_ENABLE();

73}

74

Таймеры

319

75if(htim_base->Instance==TIM1) {

76__HAL_RCC_TIM1_CLK_ENABLE();

78GPIO_InitStruct.Pin = GPIO_PIN_8;

79GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

80GPIO_InitStruct.Pull = GPIO_PULLDOWN;

81GPIO_InitStruct.Speed = GPIO_SPEED_LOW;

82GPIO_InitStruct.Alternate = GPIO_AF2_TIM1;

83HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

84}

85}

Строки [29:38] конфигурируют TIM1 для тактирования от внутренней шины APB1. Строки [40:44] конфигурируют TIM1 в режиме ведомого, чтобы он начинал отсчет, когда линия TI1FP1 становится высокой (то есть он запускается). GPIO PA8 сконфигурирован соответственно в строках [78:83] (он сконфигурирован как GPIO_AF2_TIM1). Обратите внимание, что в строке 80 активирован подтягивающий к земле внутренний резистор: это предотвращает случайный запуск таймера плавающим входом. По той же причине TriggerFilter установлен на максимальный уровень в строке 43 (если вы попытаетесь установить его на ноль, то заметите, что довольно легко случайно запустить таймер, даже просто прикоснувшись к проводу гребенки, подключенному к выводу PA8).

Строки [46:48] также конфигурируют TIM1 для работы в режиме ведущего. Таймер будет запускать свою внутреннюю линию (которая подключена к линии ITR0 таймера TIM3) каждый раз, когда генерируется событие обновления. Наконец, строки [61:63] конфигурируют TIM3 в Режиме внешнего тактирования 1, выбирая линию ITR0 в качестве источника тактового сигнала.

Обратите внимание, что для того, чтобы светодиод LD2 мигал каждые 500 мс (2 Гц), период TIM1 устанавливается на 24924, что означает, что частота обновления TIM1 равна 4 Гц. Это необходимо, поскольку, применив уравнение [3], получаем:

Событие обновления =

 

4 Гц

 

 

= 2 Гц = 0,5 с

 

 

 

 

 

(

0 +1 1 +1

)(

0 +1

)

 

)(

 

 

Помните, что поле Period не может быть установлено на ноль.

Для запуска TIM1 необходимо подключить вывод PA8 к источнику +3,3 В. Рисунок 12 показывает, как подключить его на Nucleo-F030.

Наконец, обратите внимание, что мы не вызываем функцию HAL_TIM_Base_Start() для таймера TIM1 (см. процедуру main()), поскольку таймер запускается после события запуска, сгенерированного на канале 1 (то есть мы притягиваем вывод PA8 к источнику

+3,3 В).

24 Понятно, что это значение предделителя относится к микроконтроллеру STM32F030R8, работающему на частоте 48 МГц. Для правильной настройки предделителя вашей Nucleo проверьте примеры книги.