Robotcraft and retrofit
Главная | Interrupt TC1 | Регистрация | Вход
Суббота
28.12.2024
18:38
Приветствую Вас Гость | RSS


Описание работы таймера/счётчика 1.
Прерывания от TC1

 


 

Таймер/счётчик 1 (TC1) представляет из себя 16-битный модуль, содержащий 10 8-битных регистров. Эти регистры фактически являются набором из 5 16-битных регистров. Счёт происходит в регистрах TCNT1H (Timer counter 1 High byte) и TCNT1L (Low byte), вместе составляющих 16-битный регистр TCNT1. ВНИМАНИЕ! Если использовать прямое чтение 8-битных регистров TCNT1H и TCNT1L, то нельзя быть уверенным, что эти регистры прочитались одновременно. Может произойти следующая ситуация: Счётчик содержал значение $01FF, Вы считали TCNT1H (содержащий значение 01 в какую-то переменную). За это время произошёл счётный импульс, и содержимое TCNT1L стало равно $00, а в TCNT1H записалось значение $02. Теперь Вы читаете значение TCNT1L в другую переменную, получаете в этой переменной значение $00 (ведь таймер-счётчик уже произвёл счёт). 16-битное значение этих переменных получилось $0100, но на момент считывания старшего байта содержимое счётчика было $01FF, и младший байт у Вас должен был прочитаться как FF. Для предотвращения такой ситуации служит временный регистр, содержащийся в блоке таймера-счётчика. Этот регистр прозрачный, т.е. действует автоматически. При считывании значения регистра TCNT1L в переменную, содержимое TCNT1H попадает в этот регистр. Затем при чтении старшего байта в переменную, считывается значение временного регистра. Временный регистр абсолютно прозрачен для пользователя, но для его корректной работы необходимо соблюдать такую последовательность действий:
Для 16-битной операции записи, старший байт должен быть записан первым. Младший - вторым.
Для операции 16-битного чтения, младший байт должен быть прочитан первым, а содержимое старшего байта считывается вторым.
Регистр TCCR1A служит для задания режимов работы таймера/счётчика 1:

Биты COM1A1,COM1A0, COM1B1 и COM1B0 - контролируют поведение выводов OC1A и OC1B.
Биты FOC1A, FOC1B, WGM11 и WGM10 служат для задания работы ТС1 как широтно-импульсного модулятора.
Скорость счёта ТС1 можно установить в регистре TCCR1B:

Где биты ICNC1, ICES1, WGM13 и WGM12 также служат для PWM, а CS12, CS11 и CS10 настраивают скорость счёта следующим образом:

В случае, если в эти биты записаны значения 000, ТС0 остановлен. Если записано 001, то тактовая частота процессора подаётся через схему делителя без изменений, и на каждый такт процессора ТС1 увеличивает значение в регистре TCNT1. Соответственно, если в CSxx Записано 101, то увеличение значения в TCNT1 происходит на каждый 1024-ый такт процессора.

16-битные регистры OCR1A и OCR1Bслужат для задания значения, при достижении которого в режиме счёта, ТС1 генерирует соответствующие прерывания.

Обработка прерываний от TC1

ТС1 при переполнении значения TCNT1 посылает процессору сигнал Timer/Counter 1 Overflow. Также процессору посылается сигнал Timer/Counter 1 A или B Compare Match при совпадении значений в регистрах TCNT1 и OCR1A и OCR1B соответственно. Реакция процессора на эти сигналы (вызов соответствующих прерываний) зависит от значения регистров TIMSK и флага I в Status регистре процессора.
Для задания реакции на события TC1 в регистре TIMSK служат четыре бита:

Бит 2 - TOIE1 - Когда этот бит установлен в 1 и разрешены прерывания, процессор реагирует на сигнал переполнения ТС1 и вызывает прерывание по вектору $010 (OVF1addr).
Бит 3 - OCIE1B - Когда этот бит установлен в 1 и разрешены прерывания, процессор реагирует вызовом прерывания по вектору $00E (OC1Baddr) на событие совпадения счёта с константой в регистре OCR1B. Бит 4 - OCIE1A - Когда этот бит установлен в 1 и разрешены прерывания, процессор реагирует вызовом прерывания по вектору $00C (OC1Aaddr) на событие совпадения счёта с константой в регистре OCR1A. Бит 5 - TICIE1 - Если установлен этот бит и разрешены прерывания, разрешено прерывание захвата ТС1, расположенного по вектору $00A (ICP1addr).

 

 

http://sotvorimvmeste.ru/viewtopic.php?f=38&t=78

Работа выполняется с таймером 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;     
   };
}
 

Пример 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.

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

Максимальное значение счетного регистра таймера определяется регистром сравнения 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.

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

Прерывание по переполнению в режиме СТС генерируется только, если регистра сравнения(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.

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

Прерывание по сравнению в режиме СТС генерируется при равенстве счетного регистра таймера регистру сравнения 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.

Режим работы таймера - (ШИМ)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. Устойчивые состояния.

Режим работы таймера - (ШИМ)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.

Режим работы таймера - ШИМ(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.

Режим работы таймера - ШИМ(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;
   }
}

 

 

Пример 10. Fast PWM. Compare/Overflow.

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

В этом режиме инкреметирования счетного регистра идет до OCR0A (или 0xFF - в зависимости от WGM02). Затем происходит сброс до минимума(0x00). Затем инкрементация повторяется.
Прерывание по сравнению генерируется при достижении счетчиком значения OCR0B, по переполнению - при достижении максимального значения. Так же присутствуют устойчивые состояния.
А.В. Евстифеев, стр 243.
 

 
//мк ATtiny2313

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

//Быстрый ШИМ (Fast PWM)

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

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
   
   //Быстрый ШИМ (Fast PWM)
   TCCR0A = 0b00110011; //7,6 и 5,4 биты отвечают за выходы OC0A и OC0B
   //01 влияет только на OC0A
   //10 неинвертированный ШИМ сигнал
   //11 инвертированный ШИМ сигнал
   
   //TCCR0B = 0b00000111;
   TCCR0B = 0b00001111;
   
   OCR0A = 80; //Прерывание по переполнению при достижении OCR0A
   OCR0B = 40; 
   
   //TIMSK = 0b00000010;//Переполнение
   //TIMSK = 0b00000101;//Сравнение
   
   sei();
   
   while(1)
   {
      PORTB = TCNT0;
   }
}
Copyright MyCorp © 2024
Бесплатный конструктор сайтов - uCoz