roboforum.ru

Технический форум по робототехнике.

Прошу помощи - одновременное исп. трех таймеров на Atmega8

Прошу помощи - одновременное исп. трех таймеров на Atmega8

Alex_Sor » 30 сен 2011, 00:21

:crazy:
...неделю бьюсь с проблемой.

дано:
1) контроллер который на выходе выдает стабилизированный(задается кнопками) ток и напряжение, с БП от 220в на uc38XX в высоковльтной части, и во вторичке - атмега8 , которая управляет всем - БП управляется через оптопару, чем сильнее светит светодиод в оптопаре - тем меньше напряжения выдает БП.

2) атмега8 контролирует выходной ток и напряжение контроллера, смотрит есть-ли нагрузка, если ее нет то отключает выход контроллера но внутри контроллера сама питается от БП так что должна на нем поддерживать некий коридор напряжения ХХ.
атмега8 стабилизирует ток-напряжение через выдачу из себя с порта ШИМ - через RC цепочку - постоянка на оптопару в обратную связь в БП.

3) прошлая прога контроллера была на асме - но код утерян и человека нет кто проектировал... я пишу на С в CVAVR - мне так привычней, да и прога там не сложная.

4) советы вида "переделать плату" или сменить контроллер - не принимаются.

5) для управления контроллером принял решение распараллелить три процесса по трем таймерам :
- таймер0 : прерывается по переполнению примерно 5000 раз в сек., проверяет ток и напряжение с АЦП, делает простые операции с ними и выдает результат в OCR2 таймера2.
- таймер1 : 16 бит - он отрабатывает цикл в 0.5сек - внутри его прерывания по переполнению программа с выдачей на ЖКИ 2х8 данных, + простейший логический аппарат управления, читающий два АЦП по опросу. АЦП сконфигурированы не работать по прерыванию - только по команде read_adc(n); Проверил - 0.5 сек хватает с головой на всё что я внутри прерывания по переполнению таймера1 делаю. Тактовая атмеги8 - 16мегагерц, должно с головой хватить.
- таймер2 : 8 бит, использую как ШИМ но без вывода на его ногу - т.е. по прерыванию по переполнению пишу в нем всего одну команду - PORTB.0=1; и выход. По прерыванию по сравнению - OCR2 - в нем пишу PORTB.0=0; и выхожу.


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

проблема еще в том, что БП стартует не моментально - т.е. есть пара сек после включения в 220В за которые стартанет uc38xx и потом атмега8 должна подхватить управление БП.

В общем - что я не делал, какие режимы не применял - все вместе не работает...

Прогу не могу привести - извините.
Буду благодарен за кусочек очень простого кода где все три таймера работают так как мне надо - я уже поломал всю голову и переписывал прогу раз 20...
по осциллографу получается совсем не то что рисуют в учебниках на красивых картинок на ноге атмеги8 ...
игрался запретом прерываний, игрался разнесением счетчиков таймеров чтобы не в один момент все три переполнялись - все бестолку...

Памагите !!! :)

контроллер рабочий - аппаратную часть всю проверил - прошивка прошлой прогой - полет нормальный, ШИМит и бардака нет с сигналами на выходе.

и в конце дебильный вопрос который возник при чтении кучи примеров программ разных авторов:
- в самом прерывании по переполнении - например таймера0 - надо-ли в первой строке писать TCCNT0=число ? Я так понял что если общий коэфф. пересчета мне не нужно менять - то достаточно в начале main процедуры проинитить все три таймера, и больше их не трогать - т.е. для шима я просто в регистр OCR2 ложу нужное число и получаю изменение скважности - и в прерывании по сравнению - просто меняю ногу порта с 1 на 0. Или надо каждый раз при входе в прогу по прерыв.по переполнению опять устанавливать "до куда считаем"?

P.S. опыт в программировании на С у меня достаточный - мне бы понять почему примеры в отдельности работают а все вместе - один большой глюк...
в инете все любят таймер1 использовать а варианта с тремя таймерами одновременно я не нашел ни одного...

Re: Прошу помощи - одновременное исп. трех таймеров на Atmeg

Michael_K » 30 сен 2011, 02:01

Как вы отлаживаете код?

Re: Прошу помощи - одновременное исп. трех таймеров на Atmeg

HarryStar » 30 сен 2011, 09:45

В обрабочике у вас работа с ЖКИ - это не быстрый процесс и опрос ацп - тоже не айс. Работу с ЖКИ надо точно выносить из прерывания.

Про отладку вам правильно написали - посмотрите что происходит в протеусе или вмлабе.

Re: Прошу помощи - одновременное исп. трех таймеров на Atmeg

Michael_K » 30 сен 2011, 10:35

Да там проблем-то потенциальных куча.
Например то, что АЦП используется в двух прерываниях (что произойдет, если во время работы ацп происходит прерывание, которое хочет то же самое ацп задействовать?) Или то, что обработчики прерывания иногда явно не успевают отработать до следующего вызова (как минимум при штатных скоростях АЦП).

Но говорить все это бестолку, если код не отлаживать хоть как-то.

Добавлено спустя 9 минут 39 секунд:
Re: Прошу помощи - одновременное исп. трех таймеров на Atmega8
P.S.
Вообще, читая форум, я вижу, что отладка - это огромная проблема у многих.
"Собрал - не работает (а это почти всегда так!) - что делать?"
Нету ни понимания, что и как делать дальше, ни плана, ни средств отладки.

Re: Прошу помощи - одновременное исп. трех таймеров на Atmeg

=DeaD= » 30 сен 2011, 11:02

Про отладку - тут два варианта бывает обычно:

1. Человек не умеет отлаживать устройства.

2. Человек в целом может и умеет отлаживать, но собирает на уровне пользователя устройство, слишком сложное по ряду причин для понимания схемы его работы и отладки этим человеком (к примеру я когда прошивку "от Олега" ставил на DIR-320 - именно такая ситуация, я замечательно умею отлаживать всякие штуки, но тут я просто выполняю написанные кем-то команды и очень плохо представляю, что там от них внутри происходит и что делать, если что-то пойдёт не так).

Re: Прошу помощи - одновременное исп. трех таймеров на Atmeg

Alex_Sor » 30 сен 2011, 13:33

1. Человек не умеет отлаживать устройства.

:) человек отлаживал устройства на процессоре 1801ВМ1 когда вы еще не родились в этом мире.
...просто прошло много времени и пришлось опять вспоминать "С" и разбираться с Атмегой...

HarryStar писал(а):В обрабочике у вас работа с ЖКИ - это не быстрый процесс и опрос ацп - тоже не айс. Работу с ЖКИ надо точно выносить из прерывания.

Я всё это знаю.
но мои простые опыты "до того" показали что всё прекрасно успевает на 16Мгц.

Про отладку вам правильно написали - посмотрите что происходит в протеусе или вмлабе.

Извините но нет пару месяцев времени на отдельное изучение еще и вмлаба и протеуса :( - попытки "поженить" эти отладчики с CVAVR 2.5 не привели к нормальным успехам - поэтому просто не заморачиваюсь - я смотрю сигналы цифровым осциллографом и вижу что нет нормальных сигналов ШИМ на том порту что я прописал.

Я понимаю как это всё звучит в ваших глазах :) но и вы меня поймите - профи-разработчиком я не стану - мне это не надо - я решу эту задачу так или иначе и буду заниматься другими делами - поэтому советы "научись программить как мы=Профи" - не надо сюда писать, хорошо?

Задаю еще раз свой вопрос, на который я не смог найти ответа в Инете и учебниках:
"...
и в конце дебильный вопрос который возник при чтении кучи примеров программ разных авторов:
- в самом прерывании по переполнении - например таймера0 - надо-ли в первой строке писать TCCNT0=число ? Я так понял что если общий коэфф. пересчета мне не нужно менять - то достаточно в начале main процедуры проинитить все три таймера, и больше их не трогать - т.е. для шима я просто в регистр OCR2 ложу нужное число и получаю изменение скважности - и в прерывании по сравнению - просто меняю ногу порта с 1 на 0. Или надо каждый раз при входе в прогу по прерыв.по переполнению опять устанавливать "до куда считаем"?
..."


Мне нужен простой ответ на него :)

Облегчаю вашу задачу - вот ниже кусочек кода как я хочу написать.
Это правильная работа с таймерами или нет ?

Код: Выделить всёРазвернуть
...
...
unsigned char RA;
...

// Read the AD conversion result
#define FIRST_ADC_INPUT 0
#define LAST_ADC_INPUT 7
unsigned int adc_data[LAST_ADC_INPUT-FIRST_ADC_INPUT+1];
#define ADC_VREF_TYPE 0xC0

// ADC interrupt service routine
// with auto input scanning
interrupt [ADC_INT] void adc_isr(void)
{
  static unsigned char input_index=0;
   // Read the AD conversion result
  adc_data[input_index]=ADCW;
   // Select next ADC input
  if (++input_index > (LAST_ADC_INPUT-FIRST_ADC_INPUT))
     input_index=0;
  ADMUX=(FIRST_ADC_INPUT | (ADC_VREF_TYPE & 0xff))+input_index;
   // Delay needed for the stabilization of the ADC input voltage
  delay_us(10);
   // Start the AD conversion
  ADCSRA|=0x40;
  }


// interrupt [TIM0_OVF] - это основной цикл управления током
// происходит XXX раз в секунду (Гц)
// тут мы управляем данными OCR2 (TIMER2) - который дергает порт PORTB.1
//

interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
     // сначала заново заносим данные в TIMER0 --- !!!
  TCNT0=0xFE;  // XXX Гц задаем переключение по таймеру
               //  + включен делитель на ... от 16Мгц

       t0Uout=adc_data[7];   // замер напряжения идущего к ...
       t0Iout=adc_data[6];   // замер тока идущего к ...
.............моя короткая программа тут
в которой вычисляется значение для переменной RA, которое потом записывается(кем правильно писать???) в OCR2 ................
}

// Timer2 overflow interrupt [TIM2_OVF] service routine
// тут мы дергаем портом PORTB.1
// по сигналу "совпадение"
// частота 16Мгц/(8 делителя TCCR2 * TCNT2)

interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
   TCNT2=0xFF;  // Reinitialize Timer2 value
   OCR2=RA;
   PORTB.1=0;   // выключаем порт Б - ШИМим оптопару. !!!
  }

// Timer2 output compare interrupt service routine
interrupt [TIM2_COMP] void timer2_comp_isr(void)
{
   //OCR2=RA;
   PORTB.1=1;   // включаем порт Б - ШИМим оптопару.
  }


// interrupt [TIM1_OVF] - это основной цикл прерывания.
// occurs every (=fhz) seconds
// xtal = quartz crystal frquency [Hz]
// frequency [Hz]
// дальше по этих частях секунды уже отсчитывается все остальное что требует учета времени.

interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
  // сначала заново заносим данные в TIMER0 --- !!!

   #asm("cli")  // Global Interrupt Disable !!!
  TCNT1=0x10000-(xtal/1024/fhz);  // fhz= Гц задаем переключение по таймеру
                                  // 1024 - коэф. пересчета записан в регистр: TCCR0=0x05;
   #asm("sei")  // Global Interrupt Enable !!!

   Uout1=adc_data[7];  // читаем напряжение
.......тут моя программка короткая....

...переделал прогу под прерывания от АЦП ....
}

...

void main(void)
{
#asm("cli")          // Global Interrupt Disable !!!
...

// Timer/Counter 0 initialization
// Clock source: System Clock
//TCCR0=0x05; // == clk/1024 (From prescaler)
//TCCR0=0x01; // == No prescaler
//TCCR0=0x02; // == clk/8 (From prescaler)
TCCR0=0x03; // == clk/64 (From prescaler) == 64+255== 735 Гц
//TCCR0=0x04; // == clk/256 (From prescaler) == 256+255== 183 Гц
//TCCR0=0x05; // == clk/1024 (From prescaler)
TCNT0=0xFE; // 255 + Коэфф.пересчета

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 16000,000 kHz
// Mode: Normal top=0xFFFF
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00; //
TCCR1B=0x05; // clk/1024 (prescaling)
TCNT1H=0xE9; // старший байт  0xE91D==0.5sek(12Mhz)
TCNT1L=0x1D; // это расчет на полсекунды
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Mode: Fast PWM top=0xFF
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x49;     // делитель x1 быстрый ШИМ
//TCCR2=0x41;     // фазокорректный PWM, делитель x1
//TCCR2=0x42;     // фазокорректный PWM, делитель x8
//TCCR2=0x43;     // фазокорректный PWM, делитель x32
//TCCR2=0x44;     // фазокорректный PWM, делитель x64
TCNT2=0xFF;
OCR2=0xF0;

// Timer(s)/Counter(s) Interrupt(s) initialization
//TIMSK=0x41; // Bit 0=1 -- TOIE0: Timer/Counter0 Overflow Interrupt Enable
            // Bit 6=1 -- TOIE2: Timer/Counter2 Overflow Interrupt Enable
TIMSK=0xC5;  // разрешено прерывание по Т0 Т1 и Т2+сравнение OCR2

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// ADC initialization
// ADC Clock frequency: 1000,000 kHz
// ADC Voltage Reference: Int., cap. on AREF
ADMUX=FIRST_ADC_INPUT | (ADC_VREF_TYPE & 0xff);
ADCSRA=0xCC;

...
//WDTCR=0x0E;
WDTCR=0x0F;  // 2.1 секунды

// Global enable interrupts
#asm("sei")

...
........моя программа еще.....................
...................


Re: Прошу помощи - одновременное исп. трех таймеров на Atmeg

HarryStar » 30 сен 2011, 14:21

Alex_Sor писал(а):но мои простые опыты "до того" показали что всё прекрасно успевает на 16Мгц.

Успевает делать что?
Если у вас 1 прерывание, вы можете там хоть по суткам находится - проблем никаких и все будет успевать.
Когда же у вас 1 прерывание идет 5000 раз в секунду, а в другом идет вывод на ЖКИ, то у первого прерывания сразу падает частота или появляются глюки более серьезного характера. Тем более, что как уже говорили у вас идет разделение ресурсов, используемых в прерываниях, в частности - ацп, сам таймер (ШИМ и на нем же прерывание) и т.д. Все это плохо сказывается на программе.

Выводите опрос АЦП и ЖКИ из всех прерываний, переделывайте на работу через флаги например. Отлаживайте по частям и все будет нормально.

Re: Прошу помощи - одновременное исп. трех таймеров на Atmeg

Michael_K » 30 сен 2011, 14:37

Alex_Sor писал(а):в самом прерывании по переполнении - например таймера0 - надо-ли в первой строке писать TCCNT0=число ?


У этого таймера - куча режимов работы. В некоторых он сам перезагружается.
Но в самом простом случае (который вы и используете) - да, надо писать руками.
Это имеет смысл, если прескейлер достаточно большой (как у вас, например).

Re: Прошу помощи - одновременное исп. трех таймеров на Atmeg

=DeaD= » 30 сен 2011, 14:45

Alex_Sor писал(а)::) человек отлаживал устройства на процессоре 1801ВМ1 когда вы еще не родились в этом мире.
...просто прошло много времени и пришлось опять вспоминать "С" и разбираться с Атмегой...

Значит имеем второй вариант по причине неудачной организации программы.

Я бы таймер 1 ликвидировал и вынес это добро в основной цикл программы, где в начале времени цикла засекал бы таймер, а в конце через delay делал паузу, добивающую до 0.5сек, если хочется стабильности.

Добавлено спустя 2 минуты 18 секунд:
Re: Прошу помощи - одновременное исп. трех таймеров на Atmega8
И такая организация с таймером0 и таймером2 это та еще порнография. Если нет никакой возможности перейти на железный ШИМ - надо сначала эту пару таймеров аккуратно отладить, а в идеале - вообще бы слить в один.

Re: Прошу помощи - одновременное исп. трех таймеров на Atmeg

Alex_Sor » 30 сен 2011, 14:53

Я бы таймер 1 ликвидировал и вынес это добро в основной цикл программы, где в начале времени цикла засекал бы таймер, а в конце через delay делал паузу, добивающую до 0.5сек, если хочется стабильности.

Извините но это тупое и детское решение, я так делать не буду.
Мне есть чем заниматься в "основном цикле", чем тратить драгоценное процессорное время на тупую задержку и постоянное слежение "а не переполнился-ли счетчик?" - если у меня есть СВОБОДНЫЙ таймер!

У вас еще идеи будут ? :)
...я всегда не любил пути "спрыгнуть" с красивого решения на "быструю подпорку" в программировании - вы уж извините, "старая школа" дает знать...


Michael_K писал(а):
Alex_Sor писал(а):в самом прерывании по переполнении - например таймера0 - надо-ли в первой строке писать TCCNT0=число ?


У этого таймера - куча режимов работы. В некоторых он сам перезагружается.
Но в самом простом случае (который вы и используете) - да, надо писать руками.
Это имеет смысл, если прескейлер достаточно большой (как у вас, например).


:beer: спасибо!

а в Таймере1 и Таймере2 ?

по сути моей задачи:
Таймер0 должен за каждый свой вызов(прерывание по переполнению) изменить OCR2 на +1 или -1 и завершить свою программу. Это просто и быстро :)
Вопрос в том что если его сделать частотой в 100Гц то получится большое гуляние напряжения и тока стабилизации, ведь +1 или -1 делается за один "тик"(прерывание) этого таймера - соотв. получится что от 9 до 12В(например) он проедет за 1сек, а это уже заметно много :(

Таймер1 - отрабатывается раз в 0.5сек или в 1 сек.(не критично)

Таймер2 - это собственнно ШИМ с ноги PORTB.1. Тут частота его должна быть в пределах 50-100кГц(выход с него подстраивается в т.ч. RC-цепочкой сглаживания, если уж таймером никак).

Так вот вопрос именно в OCR2 - когда его писать ?
Писать (изменять) его должен Таймер0 - но лажа получается...

Мне не нужна суперточность ШИМ на выходе - он все равно выпрямляется в постоянку, и там небольшие пульсации никого не пугают.

Re: Прошу помощи - одновременное исп. трех таймеров на Atmeg

=DeaD= » 30 сен 2011, 15:08

Alex_Sor писал(а):...я всегда не любил пути "спрыгнуть" с красивого решения на "быструю подпорку" в программировании - вы уж извините, "старая школа" дает знать...

Прерывающие в неожиданные моменты друг друга 3 таймера, один из которых зачем-то заменяет железный ШИМ это красивое решение, да...

Если продолжать эту вакханалию с прерываниями, тогда надо определиться с их приоритетами и защитить одни от других. Разве что выключать в более приоритетном прерывании на входе все менее приоритетные, а на выходе включать обратно? Или в AVR-ке есть какие-то более приличные способы?

Re: Прошу помощи - одновременное исп. трех таймеров на Atmeg

Michael_K » 30 сен 2011, 15:24

Alex_Sor писал(а):а в Таймере1 и Таймере2 ?

В данном случае точно так же.


Что-то так и не понял, как используется (и используется ли вообще) прерывание от АЦП.
С ходу битики в регистрах, естественно, не помню - соответственно не понимаю, чего вы и куда настраиваете :pardon:

В вашем случае нужно обязательно не разрешать прерывания T0/T1 внутри прерываний T1/T0.
Иначе у вас прерывания будут ссориться из-за доступа к "общим" ресурсам (например к АЦП).
При этом как-то нужно оставить рабочим прерывание, которое генерирует ШИМ.
Кроме того возможны ситуации типа "всплывает стек".

По-моему, вы совершенно напрасно не хотите использовать аппаратный шим (от T1) на PORTB.1.
Это cамый прямой (и правильный) способ развязать ваш "узел".

Я бы, честно, сделал в основном цикле проверку флага от медленного прерывания и его обработку
(но это совсем не означает, что нужно кого-то ждать - проверил-"не пора еще"-пошел дальше).

Можно завязать все на один таймер.
То есть в обработчике T0 вести счетчик... Ну например 2499 раз измеряем ток-напряжение, а на 2500 - чего-то там еще...
Но это уже "извращения на любителя".

Добавлено спустя 3 минуты 35 секунд:
=DeaD= писал(а):Или в AVR-ке есть какие-то более приличные способы?

В АВР-ке по умолчанию прерывания внутри обработчиков прерываний запрещены... Но что там генерит компилятор - вопрос еще тот.
В GCC раньше различались слова SIGNAL и INTERRUPT (различались именно тем, что внутри одного прерывания запрещены, а внутри другого разрешены). Как в CVAVR - не знаю.

Re: Прошу помощи - одновременное исп. трех таймеров на Atmeg

=DeaD= » 30 сен 2011, 15:33

Если во всех прерываниях запрещены прерывания, то длинные прерывания будут серьезно портить жизнь коротким\быстрым, таким как генерация ШИМа и управление этим ШИМом.

Re: Прошу помощи - одновременное исп. трех таймеров на Atmeg

Michael_K » 30 сен 2011, 15:37

Именно так. Поэтому тут либо надо ручками все прописывать и распределять "приоритеты", либо искать другие решения - менять логику программы, правильно распределять ресурсы, использовать аппаратные возможности и т.п.

Re: Прошу помощи - одновременное исп. трех таймеров на Atmeg

Alex_Sor » 30 сен 2011, 16:46

Michael_K писал(а):
Alex_Sor писал(а):а в Таймере1 и Таймере2 ?

В данном случае точно так же.

спасибо. учту.

Что-то так и не понял, как используется (и используется ли вообще) прерывание от АЦП.

я переписал прогу так чтобы "сканирование" шло само по себе а все мои "смотрелки в цифры" просто смотрели в массив того что насчитало АЦП со скоростью миллион замеров / число каналов:
Код: Выделить всёРазвернуть
..................
// Read the AD conversion result
#define FIRST_ADC_INPUT 0
#define LAST_ADC_INPUT 7
unsigned int adc_data[LAST_ADC_INPUT-FIRST_ADC_INPUT+1];
#define ADC_VREF_TYPE 0xC0

// ADC interrupt service routine
// with auto input scanning
interrupt [ADC_INT] void adc_isr(void)
{
  static unsigned char input_index=0;
   // Read the AD conversion result
  adc_data[input_index]=ADCW;
   // Select next ADC input
  if (++input_index > (LAST_ADC_INPUT-FIRST_ADC_INPUT))
     input_index=0;
  ADMUX=(FIRST_ADC_INPUT | (ADC_VREF_TYPE & 0xff))+input_index;
   // Delay needed for the stabilization of the ADC input voltage
  delay_us(10);
   // Start the AD conversion
  ADCSRA|=0x40;
  }
.................



В вашем случае нужно обязательно не разрешать прерывания T0/T1 внутри прерываний T1/T0.

так они (насколько я понял вас) и так не разрешаются...
а раз НЕ разрешены - то вся моя работа по трем таймерам не имеет смысла :(
Почему? да потому что "длинное" прерывание покроет все остальные и... и всё... Т.е. получается что Atmega совсем тупое изделие, и его таймеры предназначены ТОЛЬКО для того чтобы рулить его "выходными ногами" ?
Если так - то дело совсем плохо :( ...самому придется писать обработчик прерываний, нечто типа "виртуальной машины", а это явно не для "С" задача и явно надолго... хреново... :( не думал я что в Атмеге все так печально с прерываниями... даташит на эту тему скромно умалчивает :( ...

По-моему, вы совершенно напрасно не хотите использовать аппаратный шим (от T1) на PORTB.1.
Это cамый прямой (и правильный) способ развязать ваш "узел".

я знаю что это самый прямой путь...
но хотелось сделать красиво и использовать вместо "часов точного времени" Т1, который умеет хоть 1-сек выдать сам, без всяких подгонок и подсчетов...
Было бы два 16 битных таймера - я бы не заморачивался с Т0 и Т2...

Я бы, честно, сделал в основном цикле проверку флага от медленного прерывания и его обработку

:no: тогда этим придется везде по ходу длинного кода заниматься...
...некрасивое решение... "подпорочное"...

Можно завязать все на один таймер.
То есть в обработчике T0 вести счетчик... Ну например 2499 раз измеряем ток-напряжение, а на 2500 - чего-то там еще...
Но это уже "извращения на любителя".

Это как раз не извращение.
Это всего один шаг от "виртуальной машины" и от реальной мультизадачности.
Но тут придется писать много и вдумчиво, а ради одной задачи это непрактично...

=DeaD= писал(а):Или в AVR-ке есть какие-то более приличные способы?

В АВР-ке по умолчанию прерывания внутри обработчиков прерываний запрещены... Но что там генерит компилятор - вопрос еще тот.
В GCC раньше различались слова SIGNAL и INTERRUPT (различались именно тем, что внутри одного прерывания запрещены, а внутри другого разрешены). Как в CVAVR - не знаю.

Ситуевина на экране осциллографа выглядит так что длинное прерывание таки прерывается мелкими. Но я там принудительно внутри обработки Т1 разрешил прерывания.
Похоже что "малой кровью" можно таки решить вопрос о работе всех трех таймеров.

Последний мой вопрос который остался:
посмотрите код прошлом моем посте - когда лучше(и правильнее) писать OCR2
(это величина "до которой считать" Таймеру2) ?

ответы возможные:
1) OCR2 пишем когда захотим, внутри программы в обработчике переполнения Т0 работающей, а Т2 тупо сам работает по своему прерыванию по переполнению. Возможные перебои во время переписывания Т2 - не отвлекаемся.
2) OCR2 пишем только в начале самого прерывания по переполнению Таймера2, там-же где и его "общий счетчик" TCNT2.
3) ????


Rambler\'s Top100 Mail.ru counter