Перейти к содержанию

CH32V

  • записей
    8
  • комментариев
    12
  • просмотров
    3 086

Режим одиночного импульса


zhevak

3 045 просмотров

Продолжаю публикацию материалов на тему работы с таймером.

У таймеров, которые встроены в CH32V003, имеется один полезный режим -- режим одиночного импульса (OPM, One Pulse Mode).

Этот режим работы характеризуется тем, что таймер создаёт одиночный кусочек времени, а не генерирует периодический сигнал. Иначе говоря, мы стартуем таймер, он один раз отрабатывает заданное время  и на этом всё заканчивается. Чтобы повторить процедуру, нужно ещё раз стартануть таймер.

В задаче, код которой приведён ниже, таймер отрабатывает промежуток времени, равный 500 мс. По окончании этого промежутка таймер поднимает флаг UIF и возбуждает прерывание.

Кроме этого, у таймера, как по аналогии с предыдущей статьёй, также задействованы два канала захвата/сравнения -- 3-й и 4-й. Они также отрабатывают промежутки времени 75 и 125 мс.

На этот раз управление светодиодами (которые используются для диагностики и отладки) несколько изменилось. Добавился третий светодиод, который индицирует отрабатываемый таймером промежуток времени (500 мс).

 

Код обработчика прерывания выглядит следующим образом:
 

__attribute__((interrupt("WCH-Interrupt-fast")))
void TIM2_IRQHandler(void)
{
  // Отрабатываю период
  if ((TIM2->DMAINTENR & TIM_UIE) && (TIM2->INTFR & TIM_UIF))
  {
    TIM2->INTFR &= ~TIM_UIF;  // Очищаю флаг UIF
    led0_off();               // Гашу светодиод (500 мс)

    ... // Выполняю другую полезную работу, связанную с окончанием полного периода
  }
 
  // Отрабатываю короткий промежуток врмени
  if ((TIM2->DMAINTENR & TIM_CC3IE) && (TIM2->INTFR & TIM_CC3IF))
  {  
    TIM2->INTFR &= ~TIM_CC3IF;  // Очищаю флаг CC3IF
    led2_off();                 // Гашу светодиод (75 мс)

    ... // Выполняю другую полезную работу, связанную с окончанием короткого промежутка времени
  }

  // Отрабатываю длинный промежуток времени
  if ((TIM2->DMAINTENR & TIM_CC4IE) && (TIM2->INTFR & TIM_CC4IF))
  {
    TIM2->INTFR &= ~TIM_CC4IF;  // Очищаю флаг CC4IF
    led1_off();                 // Гашу светодиод (125 мс)

    ... // Выполняю другую полезную работу, связанную с окончанием длинного промежутка времени
  }
}

 

Светодиоды включаются в функции запуска таймера:

void tim2_start(void)
{
  TIM2->CTLR1 |= TIM_CEN;  // Запускаю формирование одиночного импульса
 
  // Включаю все светодиоды
  led0_on();
  led1_on();
  led2_on();
}

 

Функция инициализации таймера (по сравнению с примером из предыдущей статьи) тоже изменилась.
 

void tim2_init(void)
{
  RCC->APB1PCENR |= RCC_TIM2EN;  // Включаю тактирование модуля таймера
 
  TIM2->CTLR1  = TIM_OPM;    // Режим одиночного импульса
  TIM2->PSC    = 24000 - 1;  // Таймер будет считать со скоростью 1 кГц
  TIM2->ATRLR  = 500;        // Период 500 мс
  TIM2->CH3CVR = 25;         // Короткий импульс 25 мс
  TIM2->CH4CVR = 125;        // Длинный импульс 125 мс
  TIM2->INTFR  = 0;          // Сбрасываю все флаги

  // Разрешаю прерывания от 3-го и 4-го каналов, а также по окончанию счёта таймера
  TIM2->DMAINTENR |= (TIM_CC4IE | TIM_CC3IE | TIM_UIE);

  NVIC_EnableIRQ(TIM2_IRQn);  // Разрешаю в системе прерывание от таймера TIM2
}

Как видите, режим одиночного импульса задаётся с помощью установки флага OPM в управляющем регистре CTLR1.

Теперь функция main() должна выглядеть как-то так:
 

int main(void)
{
  uint32_t flag = 0;
 
  system_init();
  leds_init();
  tim2_init();  // Настраиваю таймер TIM2 на генерацию одиночных импульсов

  __enable_irq();

  while (true)
  {
    if (system_1s() == 1)
    { // Сюда мы попадаем один раз в секунду
      if (flag == 1)
      {
        flag = 0;
        led4_off();
      }
      else
      {
        flag = 1;
        led4_on();
        tim2_start();  // Запускаю таймер
      }
    }
  }
}


В начале функции main() происходит инициализация таймера на работу в режиме одиночных импульсов. В главном цикле программы периодически вызывается функция system_1s(), которая возвращает признак истечения односекундного интервала времени. Эта функция в этой статье не описана. Секундные интервалы времени для этой функции вырабатываются системным таймером SysTick. Согласно этим интервалам меняется значение переменной flag и через каждые две секунду происходит запуск таймера TIM2.

Вообще это не принципиально по какому критерию запускать таймер TIM2. Можно, например, по нажатию кнопки, а интервалы формировать с целью подавления дребезга.

 

 

 

Изменено пользователем zhevak

3 Комментария


Рекомендуемые комментарии

Я не знаю. Я не знаток этой экосистемы.

Я, конечно, иногда использую платы Arduino в своих проектах, но использую только как аппаратную часть, которая имеет уже готовые к применению компоненты -- источник питания, USB-UART - интерфейс для связи с компом, ну и сам процессор с кварцем. Это всё, что мне обычно надо от Ардуино. Я не пользую ни среду разработки, ни тем более их библиотеки. И поэтому, что они там делают, я понятия не имею.

Ссылка на комментарий

Смысл у Ticker класса в том что-бы вызвать заданную функцию через заданное время. Например после нажатия кнопки включить светодиод и выключить его с помощью Ticker через пять секунд.

Я думаю при помощи  SysTick можно такое сделать, а у таймера  мало времени получится т.к 16-бит. Что это за SysTick,как оно работает?

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы публикуете как гость. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Добавить комментарий...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...

×
×
  • Создать...