Автор Тема: Как правильно организовать прерывания от таймера?  (Прочитано 10165 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн lgedmitry

  • Старожил
  • *****
  • Сообщений: 4621
  • Репутация: 30
  • Сергей, Рыбинск
  • Поблагодарили: +701
Задача такая: нуна построить преобразователь напряжение-частота. Для этих целей выбрана атмега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

  • Старожил
  • *****
  • Сообщений: 798
  • Репутация: 13
  • Андрей
  • Поблагодарили: +18
Изменять счетный регистр в прерывании - не очень хорошая идея, хотя бы потому, что, в общем, его значение неопределено в момент входа в прерывание, а потому тайминги не будут точно выдержаны. Да и на установку значения нужно время. Период будет больше заданного, плюс джиттер.

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

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

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

Оффлайн blindman

  • Старожил
  • *****
  • Сообщений: 798
  • Репутация: 13
  • Андрей
  • Поблагодарили: +18
Я этим компилятором не пользуюсь, так, видел где-то код, мог и напутать

Оффлайн lgedmitry

  • Старожил
  • *****
  • Сообщений: 4621
  • Репутация: 30
  • Сергей, Рыбинск
  • Поблагодарили: +701
Я этим компилятором не пользуюсь, так, видел где-то код, мог и напутать
А что, он плохой? Я если честно, не разбирался, который лучше. Просто качнул первый нагугленный.

Оффлайн xar

  • Старожил
  • *****
  • Сообщений: 5224
  • Репутация: 16
  • Ренат
  • Поблагодарили: +271
lgedmitry, он как минимум платный. а Андрей вроде еще и на линухе сидит ко всему прочему

Оффлайн blindman

  • Старожил
  • *****
  • Сообщений: 798
  • Репутация: 13
  • Андрей
  • Поблагодарили: +18
Нет, не плохой. Это у меня свои заморочки

и добавил...
Андрей вроде еще и на линухе сидит ко всему прочему
Линукс [ˈlɪnʊks] https://www.kernel.org/pub/linux/kernel/SillySounds/english.au

А сижу я большую часть времени на табурете  :laugh:
« Последнее редактирование: 07 Февраля 2014, 17:10:06 от blindman »

 

Похожие темы

  Тема / Автор Ответов Последний ответ
33 Ответов
45945 Просмотров
Последний ответ 21 Октября 2010, 20:05:35
от AudioKiller
55 Ответов
45414 Просмотров
Последний ответ 23 Апреля 2011, 17:40:25
от yurkov
26 Ответов
20878 Просмотров
Последний ответ 18 Февраля 2014, 14:43:51
от Leonew
2 Ответов
8156 Просмотров
Последний ответ 26 Декабря 2013, 00:17:23
от debian
7 Ответов
7013 Просмотров
Последний ответ 10 Июля 2014, 07:49:02
от technic