Суббота, 23.09.2017, 19:23
RC - Мастерская
Главная | Каталог статей | Регистрация | Вход
Меню
Статистика
Главная » Статьи » Инструкции » Микроконтроллеры

Таймеры и прерывания микроконтроллеров atmega48/88/168/328/2560
Таймеры и прерывания микроконтроллеров atmega48/88/168/328/2560

  Таймеры. При программировании микроконтроллеров AVR это один из самых востребованных ресурсов. Они позволяют вести отсчет времени в тактах микроконтроллера и генерировать прерывания через заданные промежутки времени. В микроконтроллерах atmega48/88/168/328 имеется три таймера. Таймеры 0 и 2 - восьми битные. Верхней границей их счета является 255. На следующем такте происходит так называемое переполнение и таймер начинает отсчет с нуля. Таймер 1 - 16-ти битный. Его переполнение происходит соответственно при превышении счета 65535. При переполнении каждый таймер может генерировать соответствующее прерывание по переполнению.
  Так же каждый из таймеров обладает двумя компараторами. На каждом такте они сверяют текущее значение таймера с заданным в соответствующем регистре и при совпадении могут генерировать каждый свое прерывание. Текущее значение каждого таймера можно получить в соответствующем регистре TCNTx, где x - номер таймера.
  Так же для каждого из таймеров доступен режим CTC - сброс при совпадении. В этом режиме при совпадении значения с одним из компараторов счет таймера автоматически сбрасывается в ноль.
  Таймеры могут вести счет как на частоте работы микроконтроллера (CLK), так и с пред делителем. Значение пред делителя для каждого таймера выставляется свое.
  Микроконтроллеры atmega2560 имеют в своем составе еще дополнительно три 16-ти разрядных таймера.
  Так же стоит отметить, что таймер 0 используется микроконтроллером для внутренних нужд. Поэтому его перестройка не желательна.
  Для себя я сделал удобную "шпаргалку"-заготовку по управлению таймерами микроконтроллера:
Код
//----------------------------------------------------------------------------- Timer0 -------------------------------------------------------------------
void Timer0_init()
{
  TCCR0A = 0;
  TCCR0B = 0;
  TCCR0A |= (1<<WGM01);                   // Режим CTC (сброс по совпадению)
  TCCR0B |= (1<<CS00);                      // Тактирование от CLK.
                                                           // Если нужен предделитель :
  // TCCR0B = (1<<CS01);                   // CLK/8
  // TCCR0B = (1<<CS00)|(1<<CS01); // CLK/64
  // TCCR0B = (1<<CS02);                   // CLK/256
  // TCCR0B = (1<<CS00)|(1<<CS02); // CLK/1024

                                                          // Верхняя граница счета. Диапазон от 0 до 255.
  OCR0A = 123;                                   // Частота прерываний A будет = Fclk/(N*(1+OCR0A))  
  OCR0B = 123;                                   // Частота прерываний B будет = Fclk/(N*(1+OCR0B))  
                                                          // где N - коэф. предделителя (1, 8, 64, 256 или 1024)
  TIMSK0 |= (1<<OCIE0A);                  // Разрешить прерывание по совпадению A
  TIMSK0 |= (1<<OCIE0B);                  // Разрешить прерывание по совпадению B
  TIMSK0 |= (1<<TOIE0);                    // Разрешить прерывание по переполнению
}

ISR (TIMER0_COMPA_vect)
{
  // Обработчик прерывания таймера 0 по совпадению A
}

ISR (TIMER0_COMPB_vect)
{
  // Обработчик прерывания таймера 0 по совпадению B
}

ISR (TIMER0_OVF_vect)
{
  // Обработчик прерывания таймера 0 по переполнению
}
//----------------------------------------------------------------------------- Timer1 -------------------------------------------------------------------
void Timer1_init()
{
  TCCR1B = 0;
  TCCR1A = 0;
  TCCR1B |= (1<<WGM12);                    // Режим CTC (сброс по совпадению)
  TCCR1B |= (1<<CS10);                       // Тактирование от CLK.
                                                            // Если нужен предделитель :
  // TCCR1B |= (1<<CS11);                   // CLK/8
  // TCCR1B |= (1<<CS10)|(1<<CS11); // CLK/64
  // TCCR1B |= (1<<CS12);                   // CLK/256
  // TCCR1B |= (1<<CS10)|(1<<CS12); // CLK/1024

                                                            // Верхняя граница счета. Диапазон от 0 до 65535.
  OCR1A = 2678;                                   // Частота прерываний A будет = Fclk/(N*(1+OCR1A))  
  OCR1B = 2678;                                   // Частота прерываний A будет = Fclk/(N*(1+OCR1B))  
                                                            // где N - коэф. предделителя (1, 8, 64, 256 или 1024)
  TIMSK1 |= (1<<OCIE1A);                    // Разрешить прерывание по совпадению A
  TIMSK1 |= (1<<OCIE1B);                    // Разрешить прерывание по совпадению B
  TIMSK1 |= (1<<TOIE1);                      // Разрешить прерывание по переполнению
}

ISR (TIMER1_COMPA_vect)
{
  // Обработчик прерывания таймера 1 по совпадению A
}

ISR (TIMER1_COMPB_vect)
{
  // Обработчик прерывания таймера 1 по совпадению B
}

ISR (TIMER1_OVF_vect)
{
  // Обработчик прерывания таймера 1 по переполнению
}

//----------------------------------------------------------------------------- Timer2 -------------------------------------------------------------------
void Timer2_init()
{
  TCCR2A = 0;
  TCCR2B = 0;
  TCCR2A |= (1<<WGM21);                                    // Режим CTC (сброс по совпадению)
  TCCR2B |= (1<<CS20);                                       // Тактирование от CLK.
                                                                            // Если нужен предделитель :
  // TCCR2B = (1<<CS21);                                     // CLK/8
  // TCCR2B = (1<<CS20)|(1<<CS21);                   // CLK/32
  // TCCR2B = (1<<CS22);                                     // CLK/64
  // TCCR2B = (1<<CS20)|(1<<CS22);                   // CLK/128
  // TCCR2B = (1<<CS21)|(1<<CS22);                   // CLK/256
  // TCCR2B = (1<<CS20)|(1<<CS21)|(1<<CS22); // CLK/1024

                                                                            // Верхняя граница счета. Диапазон от 0 до 255.
  OCR2A = 249;                                                     // Частота прерываний A будет = Fclk/(N*(1+OCR2A))  
  OCR2B = 249;                                                     // Частота прерываний B будет = Fclk/(N*(1+OCR2B))
                                                                            // где N - коэф. предделителя (1, 8, 32, 64, 128, 256 или 1024)
  TIMSK2 |= (1<<OCIE2A);                                    // Разрешить прерывание по совпадению A
  TIMSK2 |= (1<<OCIE2B);                                    // Разрешить прерывание по совпадению B
  TIMSK2 |= (1<<TOIE2);                                      // Разрешить прерывание по переполнению
}

ISR (TIMER2_COMPA_vect)
{
  // Обработчик прерывания таймера 2 по совпадению A
}

ISR (TIMER2_COMPB_vect)
{
  // Обработчик прерывания таймера 2 по совпадению B
}

ISR (TIMER2_OVF_vect)
{
  // Обработчик прерывания таймера 2 по переполнению
}
//----------------------------------------------------------------------------- Timer3 -------------------------------------------------------------------
void Timer3_init()
{
  TCCR3A = 0;
  TCCR3B = 0;
  TCCR3B |= (1<<WGM32);                    // Режим CTC (сброс по совпадению)
  TCCR3B |= (1<<CS30);                       // Тактирование от CLK.
                                                            // Если нужен предделитель :
  // TCCR3B |= (1<<CS31);                   // CLK/8
  // TCCR3B |= (1<<CS30)|(1<<CS31); // CLK/64
  // TCCR3B |= (1<<CS32);                   // CLK/256
  // TCCR3B |= (1<<CS30)|(1<<CS32); // CLK/1024

                                                           // Верхняя граница счета. Диапазон от 0 до 65535.
  OCR3A = 2678;                                  // Частота прерываний A будет = Fclk/(N*(1+OCR3A))  
  OCR3B = 2678;                                  // Частота прерываний B будет = Fclk/(N*(1+OCR3B))  
                                                          // где N - коэф. предделителя (1, 8, 64, 256 или 1024)
  TIMSK3 |= (1<<OCIE3A);                  // Разрешить прерывание по совпадению A
  TIMSK3 |= (1<<OCIE3B);                  // Разрешить прерывание по совпадению B
  TIMSK3 |= (1<<TOIE3);                    // Разрешить прерывание по переполнению
}

ISR (TIMER3_COMPA_vect)
{
  // Обработчик прерывания таймера 3 по совпадению A
}

ISR (TIMER3_COMPB_vect)
{
  // Обработчик прерывания таймера 3 по совпадению B
}

ISR (TIMER3_OVF_vect)
{
  // Обработчик прерывания таймера 3 по переполнению
}
//----------------------------------------------------------------------------- Timer4 -------------------------------------------------------------------
void Timer4_init()
{
  TCCR4B = 0;
  TCCR4A = 0;
  TCCR4B |= (1<<WGM42);                    // Режим CTC (сброс по совпадению)
  TCCR4B |= (1<<CS40);                       // Тактирование от CLK.
                                                            // Если нужен предделитель :
  // TCCR4B |= (1<<CS41);                   // CLK/8
  // TCCR4B |= (1<<CS40)|(1<<CS41); // CLK/64
  // TCCR4B |= (1<<CS42);                   // CLK/256
  // TCCR4B |= (1<<CS40)|(1<<CS42); // CLK/1024

                                                            // Верхняя граница счета. Диапазон от 0 до 65535.
  OCR4A = 2678;                                   // Частота прерываний A будет = Fclk/(N*(1+OCR4A))  
  OCR4B = 2678;                                   // Частота прерываний B будет = Fclk/(N*(1+OCR4B))  
                                                            // где N - коэф. предделителя (1, 8, 64, 256 или 1024)
  TIMSK4 |= (1<<OCIE4A);                    // Разрешить прерывание по совпадению A
  TIMSK4 |= (1<<OCIE4B);                    // Разрешить прерывание по совпадению B
  TIMSK4 |= (1<<TOIE4);                      // Разрешить прерывание по переполнению
}

ISR (TIMER4_COMPA_vect)
{
  // Обработчик прерывания таймера 4 по совпадению A
}

ISR (TIMER4_COMPB_vect)
{
  // Обработчик прерывания таймера 4 по совпадению B
}

ISR (TIMER4_OVF_vect)
{
  // Обработчик прерывания таймера 4 по переполнению
}
//----------------------------------------------------------------------------- Timer5 -------------------------------------------------------------------
void Timer5_init()
{
  TCCR5B = 0;
  TCCR5A = 0;
  TCCR5B |= (1<<WGM52);                    // Режим CTC (сброс по совпадению)
  TCCR5B |= (1<<CS50);                       // Тактирование от CLK.
                                                            // Если нужен предделитель :
  // TCCR5B |= (1<<CS51);                   // CLK/8
  // TCCR5B |= (1<<CS50)|(1<<CS51); // CLK/64
  // TCCR5B |= (1<<CS52);                   // CLK/256
  // TCCR5B |= (1<<CS50)|(1<<CS52); // CLK/1024

                                                           // Верхняя граница счета. Диапазон от 0 до 65535.
  OCR5A = 15624;                                // Частота прерываний A будет = Fclk/(N*(1+OCR5A))  
  OCR5B = 15624;                                // Частота прерываний B будет = Fclk/(N*(1+OCR5B))
                                                           // где N - коэф. предделителя (1, 8, 64, 256 или 1024)
  TIMSK5 |= (1<<OCIE5A);                   // Разрешить прерывание по совпадению A
  TIMSK5 |= (1<<OCIE5B);                   // Разрешить прерывание по совпадению B
  TIMSK5 |= (1<<TOIE5);                     // Разрешить прерывание по переполнению
}

ISR (TIMER5_COMPA_vect)
{
  // Обработчик прерывания таймера 5 по совпадению A
}

ISR (TIMER5_COMPB_vect)
{
  // Обработчик прерывания таймера 5 по совпадению B
}

ISR (TIMER5_OVF_vect)
{
  // Обработчик прерывания таймера 5 по переполнению
}

  Из этого кода удобно взять функцию по настройке интересующего таймера, закоментировать/раскоментировать нужные строки для получения необходимых настроек и написать свой код в обработчиках прерываний.
Категория: Микроконтроллеры | Добавил: Mactep (16.12.2013)
Просмотров: 5184 | Теги: таймеры, Arduino | Рейтинг: 5.0/2
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Поиск