Странная реакция Atmega128

Тема в разделе "Микроконтроллеры AVR", создана пользователем An-SU, 16 окт 2018.

  1. An-SU

    An-SU Нуб

    Здравствуйте, форумчане! Такой вопрос:
    Есть Atmega128, отладочная плата STK500/501 и Atmel studio 7.0
    Написана скромная программка, в которой мигают светодиоды с определенной частотой (Частота схемы 8МГц). При нажатии на определенные кнопки должна изменяться частота мигания.
    Так вот проблема в том, что светодиоды меняют частоту мерцания лишь при удержании этой кнопки, а не нажатия. В последних редакциях кода при изменении предделителя вообще не хочет мигать.
    Итак, в чём странность - при выставлении в фьюзах бита включения режима соответствия с atmega103(установка 0 бита) код работает адекватно!
    Но оставлять так не могу, ибо нацелен на разрешение вопроса без последующих возможных еще больших несуразицах.

    В чем может быть дело?
     
  2. b707

    b707 Гуру

    Выложите код "скромной программки" и попытайтесь изложить проблему более ясным языком.... а то пока у меня возникло бредовое предположение. что вы частоту мигания светодиода пытаетесь изменять с помощью фьюзов :confused:
     
  3. An-SU

    An-SU Нуб

    Проблема в том, что при включении режима совместимости с С103 на атмеге128 программа начинает нормально работать, в то время как должна это делать без включения данного фьюза
    Собственно, вот:

    #define F_CPU 8000000UL //Объявление частоты мк
    #include <avr/io.h> //библиотека мк
    #include <avr/interrupt.h> //библиотека прерываний
    #include <util/delay.h> //подключение задержек

    unsigned char count=0; //предполагаемое время (в мс)
    int Sch=250; //для начала частота 250 мс

    static void ti_in(void) //функция инициализации таймера
    {
    TCCR1A|=0; //регистр управления таймером/счетчиком
    TCNT1|=0; //Регистр таймера/счетчика
    OCR1A=125; //значение сравнения для появления сравнения на 1 мс
    TIMSK|=(1<<OCIE1A);
    TCCR1B|=(1<<CS12)|(1<<WGM12); //установка делителя, режима работы таймера
    }

    ISR(TIMER1_COMPA_vect) //функция, выполняемая при совпадении чисел
    {
    count++; //увеличение кол-ва мс
    if (count == Sch)
    {
    PORTC=~PORTC; //инвертирование порта светодиодов
    count=0;
    }
    }

    int main(void)
    {
    cli();
    DDRC=0xFF; //порт со светодиодами настроен на вывод
    PORTC=0xFF; //стартовое значение - горящие светодиоды
    PORTE = (1<<PE0) | (1<<PE1);
    ti_in();
    sei();
    while (1)
    {
    if (!(PINE & (1<<PE1)))
    {
    Sch=3000;
    _delay_ms(100);
    }
    if (!(PINE & (1<<PE0)))
    {
    Sch=5000;
    }
    }
    }
     
  4. b707

    b707 Гуру

    Во-первых, у вас грубая ошибка - переменная count меняется в прерывании, значит она должна быть описана как volatile. Поправьте, может именно в этом дело.
    Если уверены в настройках таймера (лень лезть искать даташит на Атмегу 128) - других явных ошибок не вижу.
     
  5. An-SU

    An-SU Нуб

    Вы абсолютно правы, но что с volatile, что без него программа работает одинаково
    Таймер сам уже перелопачивал сотню раз, и по осциллографу сейчас показывает всё верно
    Вот в том-то и дело, что совершенно непонятно, в чем может быть зарыта @
     
  6. b707

    b707 Гуру

    кстати, переменную Sch тоже попробуйте обьявить волатильной. Хоть она явно в прерывании не меняется, но меняется между вызовами - мало ли что накрутит компилятор в рамках "оптимизации"
     
  7. An-SU

    An-SU Нуб

    Спасибо! Сделано, но.. опять не влияет на исход
     
  8. parovoZZ

    parovoZZ Гуру

    симулятор что показывает?
     
  9. An-SU

    An-SU Нуб

    я смотрю сразу по плате, в симуляторе с задержками и прерываниями неудобно
     
  10. parovoZZ

    parovoZZ Гуру

    ну тогда удачи!