Разное и полезное > Микроконтроллеры и их программирование
Как правильно организовать прерывания от таймера?
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 ---Я этим компилятором не пользуюсь, так, видел где-то код, мог и напутать
--- Конец цитаты ---
А что, он плохой? Я если честно, не разбирался, который лучше. Просто качнул первый нагугленный.
Навигация
Перейти к полной версии