В предыдущей части урока мы познакомились с оконным сторожевым таймером, как организован WWDG в контроллере STM32, познакомились со схемой урока, создали и настроили проект.
И у нас второй светодиод, только начав светиться, сразу потухал и процесс начинался сначала. Потому что мы не перезагружаем вовремя наш оконный сторожевой таймер. Давайте теперь посчитаем, в какое приблизительно время, или, точнее, в какой интервал времени мы должны уложиться с перезагрузкой нашего WWDG.
В принципе, здесь не надо ни каких сложных формул, предоставленных нам даташитом на контроллер. Мы и так всё посчитаем.
Сначала посчитаем, сколько времени нам требуется на один тик счётчика оконного сторожевого таймера. Для этого мы частоту 4 мегагерца разделим на 4096 и на 8. 4096 — это величина постоянная, а 8 — это наш предделитель. После деления мы на результат поделим единицу. После всех этих действий мы получим 8,192 милисекунды. Вот это и есть период одного тика. Мы помним что счётчик считает в обратную сторону от числа, которое мы в него занесли. А занесли мы в него 127. Поэтому сначала посчитаем, сколько тиков ему надо будет посчитать до первой границы, которую мы сделали равной 90. Получим 37. Умножаем 37 на 8,192 и получим результат, примерно равный 303,1 милисекунды. То есть мы знаем что в интервале от запуска WWDG до 303,1 милисекунды мы не должны его перезагружать. Теперь узнаем интервал от начала счёта до известной величины 0x3F или в десятичном выражении 63. Для этого мы 63 вычтем из 127 и получим значение 64. Вот столько тиков пройдёт у нас до перезагрузки системы. Посчитаем теперь этот интервал, умножив 64 на 8,192, и получим число примерно 524,3 милисекунды.
Теперь мы знаем, что мы должны перезагрузить наш оконный сторожевой таймер в интервале времени между 303,1 и 524,3 милисекунд. Так как таймер 2 у нас настроен на 400 милисекунд, то перезагружать нам его надо в каждый тик и мы как раз уложимся в нужном интервале.
Но здесь будет некоторая загвоздка. В первом кейсе нам его перезагружать не надо, так как он сработает сразу после старта WWDG, так как наш таймер 2 стартует сразу же после оконного сторожевого таймера. Можно, конечно между их стартами включить обычную задержку в 400 милисекунд, но мы так делать не будем, как то не эстетично. Пока мы никак делать не будем а всего лишь перезагрузим WWDG в каждом кейсе кроме нулевого
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
case 1: WWDG_Refresh(); LED1_OFF(); LED2_ON(); break; case 2: WWDG_Refresh(); LED2_OFF(); LED3_ON(); break; case 3: WWDG_Refresh(); LED3_OFF(); LED4_ON(); break; case 4: WWDG_Refresh(); LED4_OFF(); LED5_ON(); break; case 5: WWDG_Refresh(); LED5_OFF(); LED6_ON(); break; case 6: WWDG_Refresh(); LED6_OFF(); LED7_ON(); break; case 7: WWDG_Refresh(); LED7_OFF(); LED8_ON(); break; case 8: WWDG_Refresh(); LED8_OFF(); LED9_ON(); break; case 9: WWDG_Refresh(); |
Соберём код и прошьём контроллер.
У нас будут светодиоды бежать от первого до последнего, и, казалось бы, всё работает. Но работает не всё. Здесь я не смогу показать то, что у нас, когда начинается каждый следующий цикл, то первый светодиод будет гореть немного дольше остальных. Всё это происходит потому, что здесь имеет место перезагрузка системы, так как мы в нулевом кейсе не перезагружаем счётчик. Поэтому в этом кейсе мы сделаем проверку на флаг первого цикла, и если он у нас не в нуле, то перезагрузим оконный сторожевой таймер, а если в нуле, то установим его в единицу
1 2 3 |
case 0: if(fl_no_tirst) WWDG_Refresh(); else fl_no_tirst=1; |
Если мы теперь соберём код и прошьём контроллер, то у нас цикл пойдёт правильно.
Ну и теперь. как и в случае с независимым сторожевым таймером, в обработчике прерываний от кнопки «сломаем» наш таймер 2, то есть остановим его. Для этого мы всего лишь раскомментируем код остановки таймера, а остальной код работы с регистрами удалим
HAL_TIM_Base_Stop_IT(&htim2);
IWDG->KR = 0x00005555U;
//IWDG->PR = IWDG_PR_PR_2; // IWDG_PRESCALER_64
IWDG->RLR = 1150;
Соберём код, прошьём контроллер и в момент работы программы нажмём кратковременно нашу кнопку
Контроллер почти сразу перезагрузится, так как таймер 2 остановится, а сторожевой таймер перестанет обновляться. Вот это и будет эмуляция реакции сторожевого таймера на зависание.
Теперь поиграем со скоростью работы таймера 2 и заставим его работать с периодом между тиками не равными 400, а с такими чтобы они были либо меньше интервала до верхней границы счёта, либо больше интервала до нижней границы счёта.
В обработчике прерываний от кнопки закомментируем остановку таймера, а изменим число сравнения
1 2 |
//HAL_TIM_Base_Stop_IT(&htim2); TIM2->ARR = 1099; |
Интервал между тиками таймера 2 теперь будет составлять 1 / (8000000/2000/1100) = 0,275. А это меньше чем интервал счёта до верхней границы и получится такая ситуация, что WWDG будет перезагружаться слишком рано, что по условию его работы недопустимо и у нас будет перезагружаться наша программа.
Соберём код, прошьём контроллер и при нажатии на кнопку мы будем получать аналогичный результат.
Попробуем установить другое число в регистр сравнения таймера 2
1 2 |
//TIM2->ARR = 1099; TIM2->ARR = 2199; |
В этом случае мы получим следующий период тиков: 1 / (8000000/2000/2200) = 0,55. Это значение периода больше интервала до окончания счёта счётчика обратного отсчёта сторожевого таймера (0,524). Хоть и не на много, но все равно сработает.
Проверим это, собрав код и прошив контроллер. И при нажатии на кнопку система также будет перезагружаться.
Чтобы убедиться окончательно в правильности наших расчётов занесём в регистр сравнения таймера 2 следующее число по нажатию кнопки
1 2 |
//TIM2->ARR = 2199; TIM2->ARR = 1799; |
В этом случае мы получим следующий период тиков таймера 2: 1 / (8000000/2000/1800) = 0,45. Это значение больше чем мы установили в Cube MX, но всё же входит в интервал между 0,303 и 0,524. Поэтому при нажатии кнопки у нас будет просто происходить некоторое небольшое замедление мигания наших светодиодов, но система у нас перезагружаться не будет.
Соберём код, прошьём контроллер. После кратковременного нажатия на кнопку таймер 2 считает чуть медленнее, но тем не менее контроллер не перезагружается. К сожалению, я не могу в рамках статьи это показать, так что милости прошу на просмотр видеоурока, ссылка на который внизу страницы.
Таким образом, в данном уроке мы познакомились с оконным сторожевым таймером (WWDG), поняли, как он работает и закрепили свои знания на практике.
Всем спасибо за внимание!
Предыдущая часть Программирование МК STM32 Следующий урок
Отладочную плату STM32F103C8T6 можно приобрести здесь STM32F103C8T6
Программатор недорогой можно купить здесь ST-Link V2
Смотреть ВИДЕОУРОК (нажмите на картинку)
Добавить комментарий