XMEGA - таймер/счетчик.

Posted by Reason89 | Posted in , ,


     XMEGA содержит несколько 16-битных таймеров-счетчиков с четырьмя каналами захвата/сравнения в первом и двумя каналами захвата/сравнения во втором, в зависимости отмодификации. Каждый из каналов помимо основного регистра счета, имеет буферный регистр, откуда удобно считывать данные на случай если в процессе считывания значения в основном регистре все время обновляются.
    Таймер-счетчик может быть в двух исполнениях: таймер-счетчик 0, который содержит четыре CCx-канала, и таймер-счетчик 1 с двумя CCx-каналами. Таким образом, упоминаемые далее регистры и биты регистров CCx-каналов 3 и 4 имеются только у таймера-счетчика 0. Блок AWeX доступен только у таймера-счетчика 0, а блок Hi-Res имеется у всех таймеров-счетчиков.
    Таймеры-счетчики в XMEGA содержат полный набор функций, позволяют реализовать генерацию: прямоугольных импульсов, широтно-импульсную модуляцию с одно- и двунаправленным счетом и частотных импульсов. Входной 32-битный захват имеет возможности шумоподавления, захвата частоты и длительности импульсов. Таймеры имеют возможности генерации событий/прерываний по переполнению, по совпадению или захвату и по ошибке. Также имеет возможность использовать поддержку DMA.
    Для осуществления более сложных и специализированных генераторов импульсов предусмотрена возможность совместной работы таймеров-счетчиков с блоками расширения разрешающей способности (Hi-Res) с возможностью увеличения разрешающей способности на 2 бита (в 4 раза) и расширения возможностей генерации импульсов (AWeX) включающих в себя: 4 блока генерации мертвого времени (DT) с отдельными настройками для включения и отключения сигнала, событие контролирующие защиту от повреждения, одноканальная работа с несколькими выходами и образцовый генератор.
    Таймер-счетчик состоит из основного счетчика и нескольких каналов сравнения или захвата (CCx-каналов). Основной счетчик может использоваться для счета импульсов синхронизации или событий. Предусмотрена возможность задания направления и периода счета. CCx-каналы могут использоваться для реализации функций управления по условию совпадения счетчика с заданным значением, для генерации импульсов (частота или ШИМ) или для измерения параметров импульсного сигнала.
    Функции захвата и сравнения нельзя выполнять одновременно, т.е. таймер-счетчик не может одновременно выполнять и генерацию, и захват импульсов. Когда CCx-канал используется для выполнения операций сравнения, его называют каналом сравнения. Если же CCx-канал используется для захвата, то его называют каналом захвата.
     Удобная система прерываний, которые гененрируются  отдельно по каждому каналу в с следующих случаях:  переполнение таймера, ошибка таймер, захват или сравнения.


Не большой пример по работе с таймером счетчиком по переполнению

 
 //Переменные
volatile int timer_blink = 500; // Начальное значение переменной
//Инициализация
void initialization(void)
{ 
 cli(); // Запрещаем прерывания
 //Настройка таймера (TimerC0 в 1Khz)
 TCC0.CTRLA = TC_CLKSEL_DIV1024_gc; // Presacler 1024
 TCC0.CTRLB = 0x00; // Выбираем режим: Normal
 TCC0.PER = 32; // Верхнее значение счетчика 1000 Hz 
 TCC0.CNT = 0x00; // Сбрасываем счетчик
 TCC0.INTCTRLA = 0b00000011; // Даем высокий уровень для прерываний
 //Определение всех 
 PMIC.CTRL |= PMIC_HILVLEN_bm |PMIC_MEDLVLEN_bm|PMIC_LOLVLEN_bm; 
 sei(); // Активируем прерывания
}
//Прерывания по переполнению  TimerC0 в 1Khz 
ISR(TCC0_OVF_vect) 
{
// По прерыванию уменьшаем значение переменной на 1
 timer_blink--; if (timer_blink <0 br="" timer_blink="0;}">}
int main (void) 
{ 
 initialization();
 while(1) 
 { 
 if (timer_blink <= 0) 
 { 
 // Сюда вставляем инструкцию, которую необходимо выполнить по достижению переменной 0
 timer_blink=500; // Затем вновь возвращаем переменной начальное значение.
 }
 } 
}

    В следующей программе настраиваются три таймер счетчика на захват. Запускаются и останавливаются таймера по внешним прерываниям. При переполнении таймера на определенные выводы для индикации подается короткий сигнал. т.е. вы можете сравнить значения поступающие по разным каналам на микроконтроллер, за один промежуток времени.

 
void StartTimers(void) // Запускаем режим захвата по трем каналам таймера
{
    TCC0.CTRLA = TC_CLKSEL_EVCH0_gc; // Выбираем источником тактов нулевой канал порта
    TCD0.CTRLA = TC_CLKSEL_EVCH1_gc;                
    TCE0.CTRLA = TC_CLKSEL_EVCH2_gc;                    
    TCC0.CTRLB = 0x00;               // Выбрали режим: Normal
    TCD0.CTRLB = 0x00;                                
    TCE0.CTRLB = 0x00;                                
    TCC0.INTCTRLA = 0x01;            // Разрешаем прерывания низкого уровня по переполнению
    TCD0.INTCTRLA = 0x01;            // 0x01 - низкий уровень; 0x02 - средний; 0x03- высокий уровень...
    TCE0.INTCTRLA = 0x01;                            
}
void StopTimers(void)  // Останавливаем работу таймеров
{
    TCC0.CTRLA = TC_CLKSEL_OFF_gc;
    TCD0.CTRLA = TC_CLKSEL_OFF_gc;
    TCE0.CTRLA = TC_CLKSEL_OFF_gc;
}
ISR(PORTD_INT0_vect) // Обработка команды на начало Счета
{
    TCC0.CCA = 0;    // Обнуляем регистры захвата                    
    TCD0.CCA = 0;                                
    TCE0.CCA = 0;        
    StartTimers();   // Запускаем таймеры
}
ISR(PORTE_INT0_vect)  // Обработка команды по Сбросу
{
    StopTimers();     // Останавливаем таймеры
}
ISR(TCC0_OVF_vect)   // Обработка прерывания по переполнению таймера
{
    PORTC.OUTSET =0x04;
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");
    PORTC.OUTCLR =0x04;    
}
ISR(TCD0_OVF_vect)  // Обработка прерывания по переполнению таймера
{
    PORTC.OUTSET =0x04;
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");
    PORTC.OUTCLR =0x04;    
}
ISR(TCE0_OVF_vect) // Обработка прерывания по переполнению таймера
{
    PORTC.OUTSET =0x04;
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");
    PORTC.OUTCLR =0x04;
}
int main(void)
{
    // Настройка работы от внешнего кварца в 4МГц
    cli();                // Отключение прерываний
    OSC.XOSCCTRL = 0x4B;  // 2-9 МГц  без режима сбережения и со стабильной частотой во время запуска (01001011)
    OSC.CTRL = 0x08;      // Разрешение работы внешнего генератора
    while((OSC.STATUS & 0x08) == 0);  // Ожидание сигнала о включении внешнего генератора
    
    // Настройка портов
    PORTC.DIR = 0x1C;     // PC0 - T/C-X; PC2, PC3, PC4 - Для индикации переполнения таймера 
    PORTD.DIR = 0x00;     // PD0 - T/C-Y; PD1 - Прерывание на начало Счета 
    PORTE.DIR = 0x00;     // PE0 - T/C-Y; PE1 - Прерывание на Сброс счетчиков  
    //Разрешаем внешнии прерывания
    // Установка маски прерываний на PIN1
    PORTD.INT0MASK = 0x02;
    PORTE.INT0MASK = 0x02;
    // Установка чувствительности по заднему фронту
    PORTD.PIN1CTRL = PORT_OPC_WIREDORPULL_gc | PORT_ISC_FALLING_gc;
    PORTE.PIN1CTRL = PORT_OPC_WIREDORPULL_gc | PORT_ISC_FALLING_gc;
    PORTD.PIN3CTRL = PORT_OPC_PULLDOWN_gc | PORT_ISC_FALLING_gc;
    PORTD.PIN5CTRL = PORT_OPC_PULLDOWN_gc | PORT_ISC_FALLING_gc;
    EVSYS.CH0MUX = EVSYS_CHMUX_PORTD_PIN3_gc;
    EVSYS.CH1MUX = EVSYS_CHMUX_PORTD_PIN4_gc;
    EVSYS.CH2MUX = EVSYS_CHMUX_PORTD_PIN5_gc;
    TCC0.CTRLD = TC_EVACT_CAPT_gc | TC_EVSEL_CH0_gc;
    TCD0.CTRLD = TC_EVACT_CAPT_gc | TC_EVSEL_CH1_gc;
    TCE0.CTRLD = TC_EVACT_CAPT_gc | TC_EVSEL_CH2_gc;
     // Настройка высокого уровня прерываний
    PORTD.INTCTRL = PORT_INT0LVL_HI_gc;
    PORTE.INTCTRL = PORT_INT0LVL_HI_gc;
// Разрешаем все уровни прерываний    
PMIC.CTRL|=PMIC_HILVLEN_bm|PMIC_MEDLVLEN_bm|PMIC_LOLVLEN_bm;     
    sei(); // Включение прерываний
    while(1)
        {
        // Код программы
        }

    Так же Xmega стандартно позволяет  считать на таймере счетчике количество тактов,  с делителем от 2 до 1024. В данном случае необходимости использовать систему событий не возникает:

void StartTimer()

{
    TCC0.PER = 16384; 
    TCC0.INTCTRLA = 0x03;
    TCC0.CTRLA = TC_CLKSEL_DIV1024_gc;
}


ISR(TCC0_OVF_vect)                                                    
{
    // Подпрограмма обработки данных по переполнению
}
В регистр PER заносится значение до которого будет считать таймер счетчик.
В регистре CTRLA разрешаем работу таймера счетчик с частотой поделенной на 1024.
По достижению 16384, таймер счетчик сгенерирует прерывание высокого уровня и уйдет на его обработку.
 Документация AVR по работе с таймерами.
Материал к документации



Comments (0)

Отправить комментарий