Страница 1 из 2

Таймер в микроконтроллере AVR

СообщениеДобавлено: 19 фев 2012, 15:28
VVZ
Работа выполняется с таймером T0 микроконтроллера ATtiny2313 (D1), используя несколько изменённую схему второго задания. По ходу работы исследуются режимы работы таймера, его регистров, выхода и прерываний. Схема для работы :

Изображение

R1-10 - 1 кОм; R11 - 10 кОм.

К выводам PORTВ подключёна светодиодная шкала (VD1), на которую постоянно выводится состояние счётного регистра TCNT0 таймера (см. код программы). Крайние светодиоды шкалы показывают состояние выхода таймера OC0B (вывод PD5) и состояние вывода PD6, который является индикатором работы в прерывании. Для тактирования таймера к входу T0 (вывод PD4) подключается тактовый генератор. Возможно, индикацию выводов OC0B (PD5) и PD6 будет удобней (для наглядности) выполнять не через светодиоды шкалы, а через отдельные светодиоды.

Например, режим работы таймера Normal, прерывание по сравнению.

Код: выделить все
//ATtiny2313
//f_cpu=8000000

#include <avr/io.h>
#include <avr/interrupt.h>         

SIGNAL(SIG_OUTPUT_COMPARE0B)
{
TCNT0 = 0;
PORTD ^= 0b01000000; //инверсия на PD6
}

int main(void)               
{
// порты ввода/вывода
   PORTA  =  0b11111111;   
   DDRA   =  0b00000000;

// PD6 - выход на светодиод для индикации прерывания; D5 - выход OC0B; PD4 - вход T0
   PORTD  =  0b10011111;
   DDRD   =  0b01100000;
   
   PORTB  =  0b00000000;
   DDRB   =  0b11111111; // PB0-PB7 - аноды индикатора
   
//таймер T0
   TCCR0A = 0b00010000; // Normal; состояние вывода OC0B меняется на противоположное
   TCCR0B = 0b00000111; //подключение вывода T0, счёт по нарастающему фронту   
   TIMSK  = 0b00000100; //прерывание по сравнению OCR0B
   OCR0B  = 8;
 
   sei();
   
   while (1) {
   PORTB = TCNT0;     
   };
}

Таймер в микроконтроллере AVR

СообщениеДобавлено: 21 фев 2012, 21:47
EgorovAD MEPhI
-||-

Пример 2. Normal. Overflow.

СообщениеДобавлено: 22 фев 2012, 22:28
EgorovAD MEPhI
Пример 2. Normal. Overflow.

Режим работы таймера - Normal. Прерывание по переполнению.

В обработчике сигнала необходимо сбросить значение счетного регистра таймера до выбранного значения.
А.В. Евстифеев, стр 241.

Код: выделить все
//мк ATtiny2313


#include <avr/io.h>
#include <avr/interrupt.h>

//Режим Normal, прерывание по переполнению

#define TCNT TCNT0 = 256 - 15  //Число тактов до прерывания     

SIGNAL(SIG_OVERFLOW0) //прерывание по переполнению
{
   TCNT; //сброс счетчик
   PORTD ^= 0b01000000;
}

int main(void)
{
   PORTA = 0b11111111;
   DDRA  = 0b00000000;
   
// PD6 - выход на светодиод для индикации прерывания; D5 - выход OC0B; PD4 - вход T0
        PORTB = 0b00000000;
        DDRB  = 0b11111111;
   
        PORTD = 0b10011111;
        DDRD  = 0b01100000; //D5 - выход OCR0B
   
   //Режим Normal
   TCCR0A = 0;
   TCCR0B = 0x07;      //источник тактового сигнала
   TIMSK  = 0b00000010; //прерывание по переполнению
   TCNT;
   
   sei();
   
   while(1)
   {
      PORTB = TCNT0; //вывод счетчика таймера на индикатор
   }
}

Пример 3. CTC.

СообщениеДобавлено: 22 фев 2012, 22:28
EgorovAD MEPhI
Пример 3. CTC.

Режим работы таймера - СТС(сброс при совпадении).

Максимальное значение счетного регистра таймера определяется регистром сравнения OCR0A.
А.В. Евстифеев, стр 242.

Код: выделить все
//мк ATtiny2313

#include <avr/io.h>
#include <avr/interrupt.h>

//Режим СТС(сброс при совпадении)
//Состояние выхода меняется на противоположенное


int main(void)
{
   PORTA = 0b11111111;
   DDRA  = 0b00000000;
   
   PORTB = 0b00000000;
   DDRB  = 0b11111111;
   
    PORTD = 0b10011111;
    DDRD  = 0b01100000; //D5 - выход OCR0B
   
   //Режим СТС   
   TCCR0A = 0b00010010;
   TCCR0B = 0x07;

   
   OCR0A  = 20; //Задаем максимум счетчика таймера
   
   while(1)
   {
      PORTB = TCNT0;
   }
}

Пример 4. СТС. Overflow.

СообщениеДобавлено: 22 фев 2012, 22:29
EgorovAD MEPhI
Пример 4. СТС. Overflow.

Режим работы таймера - СТС. Прерывание по переполнению.

Прерывание по переполнению в режиме СТС генерируется только, если регистра сравнения(OCR0A) равен 255(0xFF).
А.В. Евстифеев, стр 242.

Код: выделить все
//мк ATtiny2313

#include <avr/io.h>
#include <avr/interrupt.h>

//Режим СТС(сброс при совпадении), прерывание по переполнению
//Состояние выхода меняется на противоположенное

SIGNAL(SIG_OVERFLOW0) //прерывание по переполнению
{
   PORTD ^= 0b01000000;
}

int main(void)
{
   PORTA = 0b11111111;
   DDRA  = 0b00000000;
   
   PORTB = 0b00000000;
   DDRB  = 0b11111111;
   
    PORTD = 0b10011111;
    DDRD  = 0b01100000; //D5 - выход OCR0B

   //Режим СТС
   TCCR0A = 0b00010010;
   TCCR0B = 0x07;

   TIMSK  = 0b00000010;
   
   OCR0A  = 0xFF; //Для прерывания по переполнению только 0xFF
   
   sei();
   
   while(1)
   {
      PORTB = TCNT0;
   }
}

Пример 5. CTC. Compare.

СообщениеДобавлено: 22 фев 2012, 22:29
EgorovAD MEPhI
Пример 5. CTC. Compare.

Режим работы таймера - СТС. Прерывание по сравнению.

Прерывание по сравнению в режиме СТС генерируется при равенстве счетного регистра таймера регистру сравнения OCR0A.
А.В. Евстифеев, стр 242.

Код: выделить все
//мк ATtiny2313

#include <avr/io.h>
#include <avr/interrupt.h>

//Режим СТС(сброс при совпадении), прерывание по сравнению.
//Состояние выхода меняется на противоположенное


SIGNAL (SIG_OUTPUT_COMPARE0A) //прерывание по сравнению c OCR0A
{
   PORTD ^= 0b01000000;
}

SIGNAL (SIG_OUTPUT_COMPARE0B) //прерывание по сравнению с OCR0B
{
   
}

int main(void)
{
   PORTA = 0b11111111;
   DDRA  = 0b00000000;
   
   PORTB = 0b00000000;
   DDRB  = 0b11111111;
   
    PORTD = 0b10011111;
    DDRD  = 0b01100000; //D5 - выход OCR0B
   
   //Режим СТС   
   TCCR0A = 0b00010010;
   TCCR0B = 0x07;
   
   TIMSK  = 0b00000101;

   OCR0A  = 20; //Для прерывания по сравнению любое значение
   //OCR0B  = 10;
   

   sei();
   
   while(1)
   {
      PORTB = TCNT0;
   }
}

Пример 6. Phase Correct PWM.

СообщениеДобавлено: 22 фев 2012, 22:30
EgorovAD MEPhI
Пример 6. Phase Correct PWM.

Режим работы таймера - (ШИМ)Phase Correct PWM.

Счетный регистр таймера инкрементирует свое значение до значения OCR0A(или 0xFF - в зависимости от WGM02). Затем дикрементирует до минимума(0x00). Затем опять меняется направление счета.
Значение OCR0B определяет "скважность" сигнала т.е. отношения полезного сигнала к периоду.
А.В. Евстифеев, стр 245.

Код: выделить все
//мк ATtiny2313

#include <avr/io.h>
#include <avr/interrupt.h>

//Режим ШИМ (Phase Correct PWM)

int main(void)
{
   PORTA = 0b11111111;
   DDRA  = 0b00000000;
   
   PORTB = 0b00000000;
   DDRB  = 0b11111111;
   
    PORTD = 0b10011111;
    DDRD  = 0b01100000; //D5 - выход OCR0B
   
   //Режим ШИМ (Phase Correct PWM)
   TCCR0A = 0b00110001; //7,6 и 5,4 биты отвечают за выходы OC0A и OC0B
   //01 влияет только на OC0A
   //10 неинвертированный ШИМ сигнал
   //11 инвертированный ШИМ сигнал
   
   //TCCR0B = 0b00000111;//Максимальное значение счетчика = 0xFF
   TCCR0B = 0b00001111; //Максимально значение счетчика = OCR0A

   OCR0A  = 40; //Задаем максимальное значение
   OCR0B = 10;  //Изменение значения OCR0B определяет "скважность"
   //Т.е. отношения полезного сигнала к периоду
   
   sei();
   while(1)
   {
      PORTB = TCNT0;
   }
}

Пример 7. Phase Correct PWM. Устойчивые состояния.

СообщениеДобавлено: 22 фев 2012, 22:30
EgorovAD MEPhI
Пример 7. Phase Correct PWM. Устойчивые состояния.

Режим работы таймера - (ШИМ)Phase Correct PWM.

Если в регистр сравнения записать максимальное или минимальное(0x00) значение, то при совпадении значения счетчика таймера и содержания регистра сравнения, выход переключится в одно из устойчивых состояний. В соответствии с таблицей 7.16(стр. 247)
А.В. Евстифеев, стр 247.

Код: выделить все
//мк ATtiny2313

#include <avr/io.h>
#include <avr/interrupt.h>

//Режим ШИМ (Phase Correct PWM)

int main(void)
{
   PORTA = 0b11111111;
   DDRA  = 0b00000000;
   
   PORTB = 0b00000000;
   DDRB  = 0b11111111;
   
    PORTD = 0b10011111;
    DDRD  = 0b01100000; //D5 - выход OCR0B
   
   //Режим ШИМ (Phase Correct PWM)
   TCCR0A = 0b00110001;
   //TCCR0B = 0b00000111;//Максимальное значение счетчика = 0xFF
   TCCR0B = 0b00001111; //Максимально значение счетчика = OCR0A

   OCR0A  = 40; //Задаем максимальное значение
   OCR0B = 0;  //Если задать 0 или максимум в зависимости от TCCROA
   //(COMOx0:COMOx1) выход переходит в одно из устойчивых состояний
   
   sei();
   while(1)
   {
      PORTB = TCNT0;
   }
}

Пример 8. Phase Correct PWM. Overflow.

СообщениеДобавлено: 22 фев 2012, 22:31
EgorovAD MEPhI
Пример 8. Phase Correct PWM. Overflow.

Режим работы таймера - ШИМ(Phase Correct PWM). Прерывание по переполнению.

Прерывание генерируется когда счетный регистр таймера достигает нуля.
А.В. Евстифеев, стр 245.

Код: выделить все
//мк ATtiny2313

#include <avr/io.h>
#include <avr/interrupt.h>

//Режим ШИМ (Phase Correct PWM), прерывание по переполнению

SIGNAL(SIG_OVERFLOW0) //прерывание по переполнению, только при достижении 0
{
   PORTD ^= 0b01000000;
}

int main(void)
{
   PORTA = 0b11111111;
   DDRA  = 0b00000000;
   
   PORTB = 0b00000000;
   DDRB  = 0b11111111;
   
    PORTD = 0b10011111;
    DDRD  = 0b01100000; //D5 - выход OCR0B
   
   //Режим ШИМ (Phase Correct PWM)
   TCCR0A = 0b00110001;
   //TCCR0B = 0b00000111;
   TCCR0B = 0b00001111;
   
   OCR0A  = 40;
   OCR0B = 20; 
   
   TIMSK = 0b00000010;
   
   sei();
   
   while(1)
   {
      PORTB = TCNT0;
   }
}

Пример 9. Phase Correct PWM. Compare.

СообщениеДобавлено: 22 фев 2012, 22:31
EgorovAD MEPhI
Пример 9. Phase Correct PWM. Compare.

Режим работы таймера - ШИМ(Phase Correct PWM). Прерывание по сравнению.

Прерывание генерируется когда содержание счетного регистра таймера становится равно содержанию регистра сравнения.
А.В. Евстифеев, стр 245.

Код: выделить все
//мк ATtiny2313

#include <avr/io.h>
#include <avr/interrupt.h>

//Режим ШИМ (Phase Correct PWM), прерывание по сравнению

SIGNAL (SIG_OUTPUT_COMPARE0B)

{
   PORTD ^= 0b01000000;
}

SIGNAL (SIG_OUTPUT_COMPARE0A)
{
}

int main(void)
{
   PORTA = 0b11111111;
   DDRA  = 0b00000000;
   
   PORTB = 0b00000000;
   DDRB  = 0b11111111;
   
    PORTD = 0b10011111;
    DDRD  = 0b01100000; //D5 - выход OCR0B
   
   //Режим ШИМ (Phase Correct PWM)
   TCCR0A = 0b00110001;
   //TCCR0B = 0b00000111;
   TCCR0B = 0b00001111;
   
   OCR0A = 80;
   OCR0B = 40; 
   
   TIMSK = 0b00000101;
   
   sei();
   
   while(1)
   {
      PORTB = TCNT0;
   }
}