Разное и полезное > Микроконтроллеры и их программирование

Как правильно организовать прерывания от таймера?

(1/2) > >>

lgedmitry:
Задача такая: нуна построить преобразователь напряжение-частота. Для этих целей выбрана атмега8, как самый маленький АВР контроллер со встроенным АЦП.
вот этот вот кусок кода собсна и разруливает ситуацию, ибо находится в основном крутящемся теле программы:

--- Код: ---adc_data=read_adc();              //это обращение к подпрограмме чтения из ацп восьмибитного значения
    if (adc_data)                         //если пора ехать
        {adc_data2=25000/adc_data;
        TCCR0=0x00;                   //отключаем таймер засыпания
        TCCR1B=0x0B;                 //включаем таймер преобразования
        suspend=0;
        power=0;
        adc_h=(adc_data2>>8);         //вот эти две переменные и поедут в таймер для определения его коэффициента пересчёта.
        adc_l=(adc_data2&0x00FF);
--- Конец кода ---
а вот это, собсна, и есть программа, исполняющаяся в прерывании таймера1, выдающего на-гора на выход ОС1А частоту, прпорциональную входному напряжению АЦП:

--- Код: ---interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
// Place your code here
// Place your code here
TCNT1H=0x00;
TCNT1L=0x00;
OCR1AH=adc_h;
OCR1AL=adc_l;
if (dir) position++;
else position--;
if (position>ocrr)
{dir=0;
}
if (position<ocrl)
{dir=1;
}
}
--- Конец кода ---
Вродь как всё тут работает, но есть такое мнение, что менять значения TCNT1H и TCNT1L, находясь в прерывании - это не очень хороший метод.
Нет ли у товарищей каких идей, как сделать код более кошерным? ;-[

blindman:
Изменять счетный регистр в прерывании - не очень хорошая идея, хотя бы потому, что, в общем, его значение неопределено в момент входа в прерывание, а потому тайминги не будут точно выдержаны. Да и на установку значения нужно время. Период будет больше заданного, плюс джиттер.

Я бы сделал так:


--- Код: ---interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
    OCR1A += adc_data2;
    if (dir) position++;
    else position--;

    if (position>ocrr)  {
        dir=0;
    }

    if (position<ocrl) {
        dir=1;
    }
}
--- Конец кода ---

То есть устанавливаем следующее срабатывание прерывания ровно через adc_data2 тактов после текущего, независимо от того, сколько времени ушло на вход в прерывание

ну и adc_data2 надо защитить (это разделяемый ресурс, и он двухбайтный, а значит доступ к нему - не атомарная операция)


--- Код: ---#cli
adc_data2=25000/adc_data;
#sei
--- Конец кода ---

Вроде так в CVAVR выглядят инструкции запрещения и разрешения прерываний?

lgedmitry:
Прикольно, Андрей :v: . Спасибо, тему просёк. Красотища то какая!
Зы такой синтаксис кли и сеи не пробовал компиллятору скармливать. Но сам он, когда начальную рыбу под программу готовит, то пишет так: #asm("cli"). Вроде так... У меня сейчас компа перед глазами нету.

blindman:
Я этим компилятором не пользуюсь, так, видел где-то код, мог и напутать

lgedmitry:

--- Цитата: blindman от 07 Февраля 2014, 16:39:59 ---Я этим компилятором не пользуюсь, так, видел где-то код, мог и напутать

--- Конец цитаты ---
А что, он плохой? Я если честно, не разбирался, который лучше. Просто качнул первый нагугленный.

Навигация

[0] Главная страница сообщений

[#] Следующая страница

Перейти к полной версии