ATMega128.Переполнение таймера.

te238s

★★✩✩✩✩✩
14 Ноя 2021
374
97
Суть в чём. Понадобилось для отладки сделать шим на светик. Аппаратные выводы OCnA и подобные заняты. Поэтому решил дёргать другими программно по прерываниям переполнения и совпадения. Такое делал сотню раз на других авр. Но тут...
1й и 3й 16 битные таймеры пробовал. Короче,в режиме 10 битного фаст-шим и шим с точной фазой при значении счета 1023,как и должно,появляется флаг переполнения,счет начинается с 0 и флаг сбрасывается аппаратно,одновременно входя в обработчик. Но! При счете с 0 на 1 флаг снова устанавливается! Соответственно процедура обработчика выполняется ещё раз. Пробовал режимы шим 8,9,10 бит. Бесполезно. Вряд ли глючит МК. Ибо Авр Студия симулирует так же. Протеус вообще на выводах не показывает сигнал. Каждую букву даташита перечитал,не пойму проблемы.
На 8 битном таймере 0 всё ок.
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
464
134
@te238s,
Покажите пожалуйста минимальный код, который можно скомпилировать и увидеть проблему.
 

te238s

★★✩✩✩✩✩
14 Ноя 2021
374
97
Вечером скину код.
Режим phase correct PWM.10 bit
Разрешаем прерывания переполнения TOIE1и совпадения OCR1B.
Делитель 1/8 ( хотя глюк на любом делении).
Физические выводы отключены.
Заодно попробую на другой меге симулировать аналогичное.
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
464
134
@te238s,
В первом сообщение вы описали проблему с FastPWM. Для phase correct PWM флаг переполнения работает по другому. Наверное лучше привести пример для FastPWM т.к. меньше вероятность запутаться.
 

te238s

★★✩✩✩✩✩
14 Ноя 2021
374
97
C++:
#include"Ship_main.h"

volatile timer_t timer[TIMER_NUM];//timer5-мигание светодиодом
uint8_t main_buf[SIZE_PACKET]={23,2,0,98,150};
uint8_t i;
volatile uint8_t flags;

void init(void)
{
    OCR1A=255;//main_buf[2];
    timer16_init(TIMER_NUM,timer);
    TCCR1A=(1<<WGM10)|(1<<WGM11);
    TCCR1B=(1<<WGM12)|(1<<CS11);
    TIMSK|=(1<<OCIE1A)|(1<<TOIE1);
}

ISR(SIG_INTERRUPT7)
{
    flags|=(1<<1);
}

ISR(TIMER1_COMPA_vect)
{
    flags|=(1<<LED1RED);
}
ISR(TIMER1_OVF_vect)
{
    flags&=~(1<<LED1RED);
}

int main(void)
{
    sei();
    init();
    PAUSE(50,0);//задержка для включения
    timer_on(80,1,1);
    ind_res_all();
    while(1)
    {
        if(flags&(1<<LED1RED)) ind_res(LED1RED); else ind_set(LED1RED);
    }
}
Это реальный код,который симулирую в Студии. Всё лишнее убрал.
Что удалось выяснить:
1) Режим 7 по даташиту Фаст ШИМ 10 битный (счет 0...1023) Биты WGM3...0=0111( как в коде выше).
Флаг TOV устанавливается дважды. При,собственно,переполнении с 1023 до 0 и второй раз с 0 до1.
2) В режиме 14 Фаст ШИМ,модуль счёта определяется регистром ICR1, пробовал разные значения,всё работает как надо.
Может глюк Студии? Именно на этом МК я уже нашел один. В симуляции не правильно показывал режим таймера.
 

te238s

★★✩✩✩✩✩
14 Ноя 2021
374
97
Момент входа в прерывание. Как положено флаг сбросился. На следующем тике таймера он установиться второй раз.
Безымянный.jpg
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
464
134
@te238s,
У меня тестовый код работает нормально и в AtmelStudio7 и в Proteus8
тестовый код, это минимальный код относящийся к вопросу, который можно скомпилировать и запустить.
C++:
#include <avr/io.h>
#include <avr/interrupt.h>

#define LED1RED 2                // просто для примера

volatile uint8_t flags;

void init(void)
{
    OCR1A=255;
    TCCR1A=(1<<WGM10)|(1<<WGM11);    // FastPWM 10 bit 0x3FF
    TCCR1B=(1<<WGM12)|(1<<CS11);    // clk/8
    TIMSK|=(1<<OCIE1A)|(1<<TOIE1);
}

ISR(TIMER1_COMPA_vect)
{
    flags|=(1<<LED1RED);
}
ISR(TIMER1_OVF_vect)
{
    flags&=~(1<<LED1RED);
}


int main(void)
{
    init();
    sei();
    while(1)
    {
      sei();
      sei();      
    }
}
 

te238s

★★✩✩✩✩✩
14 Ноя 2021
374
97
@Bruzzer,у меня Студия 4.19. Видимо глюк проявился. Пользуясь случаем,подскажи,в Студии 7 вообще симулятор-отладчик есть? Пытался разобраться однажды,так и не нашел.