СОВРЕМЕННАЯ ЭЛЕКТРОНИКА №9/2014

ЭЛЕМЕНТЫ И КОМПОНЕНТЫ 28 WWW.SOEL.RU СОВРЕМЕННАЯ ЭЛЕКТРОНИКА ◆ № 9 2014 Рассмотрим назначение регистров управления и состояния таймера на конкретных примерах программ. П РИМЕРЫ ПРОГРАММ Для запуска таймера необходи- мо выполнить несколько операций, таких как подача тактирования на тай- мер и инициализация его регистров. Рассмотрим эти операции на основе примеров программ для работы с тай- мерами. Довольно часто в процессе програм- мирования возникает задача реализа- ции временных задержек. Для реше- ния данной задачи необходима функ- ция формирования задержки. Пример такой функции на основе базово- го таймера TIM7 для STM32 приведён в листинге 1. Эта функция может формировать задержки в микросекундах или мил- лисекундах в зависимости от парамет- ра «t». Длительность задержки задаётся параметром «n». В данной программе задействован режим одного прохода таймера TIM7, при котором счётный регистр CNT выполняет счёт до значения переполне- ния, записанного в регистре ARR. Когда эти значения сравняются, таймер оста- новится. Факт остановки таймера ожи- дается в цикле while, путём проверки бита CEN статусного регистра CR1. Включение тактирования таймеров производится однократно в главном модуле программы при их инициали- зации. Базовые таймеры подключены к шине APB1, поэтому подача такто- вых импульсов выглядит следующим образом: RCC->APB1ENR |= RCC_APB1ENR_ TIM6EN; // Включить тактирование на TIM6 RCC->APB1ENR |= RCC_APB1ENR_ TIM7EN; // Включить тактирование на TIM7 Описанный выше программный спо- соб формирования задержки имеет существенный недостаток, связанный с тем, что процессор вынужден зани- маться опросом флага на протяжении всего времени задержки и поэтому не имеет возможности в это время выпол- нять другие задачи. Устранить такой недостаток можно с помощьюиспользо- вания режима прерываний от таймера. Функции обработки прерывания для базовых таймеров обычно выгля- дят следующим образом: Листинг 2 // Подключение библиотек #include <stm32f10x.h> #include <stm32f10x_gpio.h> #include <stm32f10x_rcc.h> #include <stm32f10x_tim.h> #include <misc.h> // Назначение выводов для светодиодных индикаторов enum { LED1 = GPIO_Pin_8, LED2 = GPIO_Pin_9 }; // Функция инициализации портов управления светодиодными индикаторами void init_leds() { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); GPIO_InitTypeDef gpio; GPIO_StructInit(&gpio); gpio.GPIO_Mode = GPIO_Mode_Out_PP; gpio.GPIO_Pin = LED1 | LED2; GPIO_Init(GPIOC, &gpio); } // Функция инициализации таймера TIM6 void init_timer_TIM6() { // Включить тактирование таймера RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); TIM_TimeBaseInitTypeDef base_timer; TIM_TimeBaseStructInit(&base_timer); // Задать делитель равным 23999 base_timer.TIM_Prescaler = 24000 - 1; // Задать период равным 500 мс base_timer.TIM_Period = 500; TIM_TimeBaseInit(TIM6, &base_timer); // Разрешить прерывание по переполнению счётчика таймера TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE); // Включить таймер TIM_Cmd(TIM6, ENABLE); // Разрешить обработку прерывания по переполнению счётчика таймера NVIC_EnableIRQ(TIM6_DAC_IRQn); } // Функция обработки прерывания таймера void TIM6_DAC_IRQHandler() { // Если произошло прерывание по переполнению счётчика таймера TIM6 if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) { // Обнулить бит обрабатываемого прерывания TIM_ClearITPendingBit(TIM6, TIM_IT_Update); // Инвертировать состояние светодиодных индикаторов GPIO_Write(GPIOC, GPIO_ReadOutputData(GPIOC) ^ (LED1 | LED2)); } } // Главный модуль программы int main() { init_leds(); GPIO_SetBits(GPIOC, LED1); GPIO_ResetBits(GPIOC, LED2); init_timer_TIM6(); while (1) { // Место для других команд } }

RkJQdWJsaXNoZXIy MTQ4NjUy