Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Не получается сконфигурировать таймер ATMega8515
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
Sirko
Не могу даже понять, откуда проблема.
Необходимо запустить первый таймер в режиме - CTC по сравнению с регистром ICR1.

Вот исходник:
Код
void InitializationTimer1(void){
    TCCR1B |= _BV(CS11);                                //    Тактирование таймера clk/8 = 1843200 Гц
    TCCR1B | _BV(WGM13) | _BV(WGM12);                //    Режим работы - "Сброс при совпадении ICR1"
    ICR1 = (F_CPU/8)/100;                            //    Переполнение - через 10 mSec
    TIMSK |= _BV(TOIE1);                                //    Разрешить прерывание по переполнению
}

ISR (TIMER1_OVF_vect) {
    static u16 q = 0;
    if(q == 0){
        PORTA ^= _BV(PA3);
        q = 100;
    }else
        --q;
}

Теоретически, прерывание должно возникать 100 раз в секунду, соответственно, дерганье ногой, в моем случае, должно происходить каждую секунду. Но в железе видно, что это происходит раз за почти четыре секунды. Значит, почему-то в регистре ICR1 не мое значение, а 0xFFFF.
Решил глянуть в симуляторе студии. Оказывается, проблема в следующем:
строка TCCR1B |= _BV(CS11) отрабатывается корректно, а
строка TCCR1B | _BV(WGM13) | _BV(WGM12) не выставляет никакие биты, соответственно, таймер работает в режиме normal.
Когда я объединил эти строки в одну TCCR1B |= _BV(CS11) | _BV(WGM13) | _BV(WGM12), в симуляторе начали выставляться все положенные биты, но в железе нога больше не дергается.

Понимаю, что чего-то я не знаю. Вот собственно и вопрос - ЧЕГО?

Компилятор с WinAVR-20100110, makefile - студийный, оптимизация Os
demiurg_spb
Обычно делают так:
Код
cli();
TCCRxB = 0;    // stop
TCNTx  = QQ;   // setup1
ICRx    = XX;  // setup2
TCCRxA = YY;  // configure1
TCCRxB = ZZ;  // configure2 + start
....
sei();

Т.е. прямо пишут байты в регистры таймера, а не по маске. И при остановленном таймере и запрещённых прерываниях.

Что у Вас с cобакой (watchdog'ом)?
И есть-ли у этой модели меги предделитель тактирования и выключен-ли он?
Sirko
Цитата
Т.е. прямо пишут байты в регистры таймера

В этой меге регистры общие для двух таймеров, так, что придется по маске.

Цитата
Что у Вас с cобакой (watchdog'ом)?
И есть-ли у этой модели меги предделитель

В моем случае задействование T1 - это дополнение к существующему проекту. В настоящее время на этом-же камне параллельно функционируют T0, INT0, UART, MODBUS исправно, во всяком случае визуально. Иключение - та самая нога из прерывания TIMER1_OVF_vect.

Цитата
и запрещённых прерываниях

Инициализация производится на старте при выключеных прерываниях.
Цитата
И при остановленном таймере

Попробовал переписать так
Код
    ICR1 = (F_CPU/8)/100;                            //    Переполнение - через 10 mSec
    TIMSK |= _BV(TOIE1);                                //    Разрешить прерывание по переполнению
    TCCR1B |= _BV(CS11)                                //    Тактирование таймера clk/8 = 1843200 Гц
         | _BV(WGM13) | _BV(WGM12);            //    Режим работы - "Сброс при совпадении ICR1"

Визуально - прерывания нет, в симуляторе все нужные биты регистров выставлены, а счетный регистр почему-то стоит в нулях.
demiurg_spb
Цитата(Sirko @ May 16 2011, 10:14) *
В этой меге регистры общие для двух таймеров, так, что придется по маске.
Не верю!
У неё всего 2 таймера timer0 (8бит) и timer1 (16бит) и у каждого из них собственные TCCRA, TCCRB, ICR, OCR, TCNT иначе быть не может.
Из общего у них лишь TIMSK пожалуй.
Это общепринятая идеология у всех AVR.
XVR
Цитата
Решил глянуть в симуляторе студии. Оказывается, проблема в следующем:
строка TCCR1B |= _BV(CS11) отрабатывается корректно, а
строка TCCR1B | _BV(WGM13) | _BV(WGM12) не выставляет никакие биты, соответственно, таймер работает в режиме normal.
Вопрос на засыпку - найдите хоть один знак присваивания во 2й строке. Когда не найдете - задайте себе вопрос, а с чего собственно TCCR1B должен был измениться?
Sirko
Цитата
а с чего собственно TCCR1B должен был измениться?

Действительно не видел twak.gif
Хотя это, в настоящий момент - не актуально, т.к. TCCR1B |= _BV(CS11) | _BV(WGM13) | _BV(WGM12) отрабатывает корректно.

Цитата
Не верю!

Вероятно, у меня ассоциация с TIMSK.

Цитата
И при остановленном таймере и...

Вернусь домой, попробую, отпишусь.

Спасибо.
Sirko
Чет невыходит ниче.
Инициализирую вот так:
TCCR1B = 0; // stop
TCNT1 = 0; // setup1
ICR1 = 0x4800; // setup2
TCCR1A = 0; // configure1
TCCR1B = _BV(CS11) | _BV(WGM13) | _BV(WGM12); // configure2 + start
TIMSK |= _BV(TOIE1);

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

Вроде все верно.
Че ему нужно?
sad.gif

ILYAUL
Очень интересно, ждём прерывание по совпадению , а разрешили только по переполнению и чего в итоге ждём
Sirko
Цитата
Очень интересно, ждём прерывание по совпадению...

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

Цитата
и чего в итоге ждём
Скорее не ждем, а хотим запустить таймер в режиме "сброс по совпадению". Почему-то счетный регистр не хочет шевелиться.
В чем кроется загвоздка - не знаю.
ILYAUL
Цитата(Sirko @ May 16 2011, 23:58) *
Простите, - не совсем понял. Если Вы имеете в виду прерывание по сравнению, то действительно, мне будут нужны прерывания и сравнения и переполнения. Вот только в этом топике я не вижу, где я использовал сравнение.

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

Это же Ваше
Цитата
Необходимо запустить первый таймер в режиме - CTC по сравнению с регистром ICR1.

И каким образом Вы собираетесь добирвться до переполнения , если выставлен режим сравнения, что ознaчает - при совпадении немедленный сброс и счёт заново до значения 0х4800 , что значительно меньше чем 0xFFFF
2. Проверьте , что записывается в бит CS11 и какую частоту Вы поставили процессору в симмуляторе
demiurg_spb
Цитата(Sirko @ May 16 2011, 22:36) *
Че ему нужно?
Используйте mode 4.
Вот вам рабочий пример, правда не для вашей меги, но поправить его 1 мин:
Код
//=============================================================================
// TIMER1 ATmega(16)(128)(64):
// Mode:2 (CTC) clear on compere (TCNTn[0->OCRnA])
// TOP: OCRnA
// Div: 256
// FTIMER = F_CPU/(DIV*(OCR+1))
// actual value:  1,000Hz (0,0%)
//=============================================================================
static void timer1_init(void)
{
    #define F_NEED1     1UL
    #define F_DIV1      256UL
    #define OCR1_VALUE   (F_CPU/(F_DIV1*F_NEED1)-1)

    TCCR1B = 0x00; //stop      

    OCR1AH = BYTE1(OCR1_VALUE);
    OCR1AL = BYTE0(OCR1_VALUE);

    TCCR1A = 0x00;
    TCCR1B = (1<<WGM12)|(1<<CS12); // start timer with div=256

    TIMSK |= (1<<OCIE1A); //timer interrupt sources
}

ISR(TIMER1_COMPA_vect)
{
    sec++;
}
alexeyv
В вашем случае проще использовать режим таймера №4 (CTC with OCR1A) и обрабатывать прерывание "Timer/Counter1 Compare Match A"

Sirko
Цитата
Это же Ваше

Мое. Только я считал, что при сравнении с ICR1 отработает прерывание по переполнению.
Нажмите для просмотра прикрепленного файла
Цитата
Используйте mode 4.

Суть в том, что мне потребуются прерывания и от OCR1A и от OCR1B. По поводу прерывания от ICR1 - я обойдусь. Только вот вопрос, не столько жизненно важный, а скорее для общего развития остается. А именно, как запустить таймер, у которого бы при достижении регистра TCNT значения 1000 отработало бы прерывание OCR1A, значения 2000 - OCR1B, значения 3000 - OVERFLOW ? Даже не как, а реально-ли.
В голове уже каша.

ILYAUL
Цитата(Sirko @ May 17 2011, 23:20) *
Мое. Только я считал, что при сравнении с ICR1 отработает прерывание по переполнению.
Нажмите для просмотра прикрепленного файла

Суть в том, что мне потребуются прерывания и от OCR1A и от OCR1B. По поводу прерывания от ICR1 - я обойдусь. Только вот вопрос, не столько жизненно важный, а скорее для общего развития остается. А именно, как запустить таймер, у которого бы при достижении регистра TCNT значения 1000 отработало бы прерывание OCR1A, значения 2000 - OCR1B, значения 3000 - OVERFLOW ? Даже не как, а реально-ли.
В голове уже каша.

Ну у Вас же на приведённом Вами рисунке написано , при совпадении с ICR установится флаг ICF, соответственно в регистре TIMSK надо разрешить прерывание захвата TICIE1 и соответсвенно изменить обработчик прерывания.
Максимальное значение здесь -надо понимать , это значение записаное в регистр ICR или OCR1A,B

2. Надо понимать , что режим называется СБРОС при совпадении, т.е при достижении значения 1000, TCNT сбросится в ноль и счёт начнётся снова. Но программно Вы сможете посчитать сколько было прерываний по 1000 и обработать 2000 или 3000.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.