Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Таймер работает не корректно
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
e-leks
Процессор: ATmega
Частота: 8 МГц.
Компилятор: AVR GCC
После пробного запуска кода в симуляторе импульс на ножке имеет верхний и нижний участки одинаковой длины, хотя я добиваюсь обратного. Прошу посмотреть код, не могу объяснить ситуацию.

Спасибо.
CODE
#include <avr/io.h>
#include <avr/interrupt.h>

int t = 0x90;
ISR(TIMER0_COMP_vect)
{
if(PINA & 0x01)
{
PORTA &= ~0x01;
OCR0 = 0x90;
}
else
{
PORTA |= 0x01;
OCR0 = 0x0C;
}
TCNT0=0x00;
}

int main(void)
{
DDRA = 0x01;

// Делитель на 1024 (8МГц / 1024 = 7,8125КГц)
// 128 мкс
TCCR0=0x05;
TCNT0=0x00;
//OCR0=0x0C;

TIMSK=0x02;

// Разрешаем прерывания глобально
sei();

while(1)
;

return 0;
}
Xenia
Перейдите лучше на таймер 2:
TCCR2 = 0xF; // CTC-mode + divisor=1024
занулять в прерывании
TCNT2 = 0;
тогда не надо будет.
А на нулевом таймере, не уверена, что CTC-мод работает. Да и в даташите OCR0 вообще не вижу. Откеда вы его взяли?
Палыч
Цитата(e-leks @ Oct 3 2013, 19:27) *
Процессор: ATmega

Хорошо бы задавая вопрос указывать конкретный тип МК.

Цитата(Xenia @ Oct 3 2013, 19:51) *
А на нулевом таймере, не уверена, что CTC-мод работает.

Ксения, Вы знаете AVR у которого таймер не имеет СТС ?
Xenia
Цитата(Палыч @ Oct 3 2013, 20:05) *
Хорошо бы задавая вопрос указывать конкретный тип МК.

Ксения, Вы знаете AVR у которого таймер не имеет СТС ?


Знаю. Таймер 0 у ATmega8.
e-leks
Цитата(Палыч @ Oct 3 2013, 20:05) *
Хорошо бы задавая вопрос указывать конкретный тип МК.

Простите... Процессор: ATmega16
Я убрал строчку
Код
TCNT0=0x00;
и получил несимметричный импульс, но верх равен 16 мс, а низ 50 мс. Почему? Так же увидел строчку "• Clear Timer on Compare Match (Auto Reload)" в описании. Ситуация для меня не разрешимая.
e-leks
Попробовал на втором таймере
Код
#include <avr/io.h>
#include <avr/interrupt.h>

ISR(TIMER2_COMP_vect)
{
    if(PINA & 0x01)
    {
        PORTA &= ~0x01;
        OCR2 = 0x90;
    }
    else
    {
        PORTA |= 0x01;
        OCR2 = 0x0C;
    }
    //TCNT0=0x00;
}

int main(void)
{
    DDRA = 0x01;

    // Делитель на 1024 (8МГц / 1024 = 7,8125КГц = 128 мкс)
    // CTC режим
    TCCR2=0x0F;
    TCNT2=0x00;
    OCR2=0x0C;

    TIMSK=0x80;

    // Разрешаем прерывания глобально
    sei();

    while(1)
  ;

    return 0;
}
, верх импульса - 33 мс, низ - 1,65 мс.
Вопросов два:
1. Код вроде как правильный?
2. Если нужно сделать генератор с варьируемым коэффициент заполнения и с одинаковым периодом, есть код проще моего?
Спасибо.
ПС:
Цитата(Xenia @ Oct 3 2013, 19:51) *
Да и в даташите OCR0 вообще не вижу. Откеда вы его взяли?
В моем даташите есть ( Rev. 2466T–AVR–07/10), если интересно могу прислать.
Xenia
Цитата(e-leks @ Oct 3 2013, 22:28) *
В моем даташите есть ( Rev. 2466T–AVR–07/10), если интересно могу прислать.

У ATmega16 регистр OCR0 у таймера есть, но у ATmega8 его нет. Я же высказала свое сомнение о наличии OCR0 только потому, что вы к тому времени не назвали тип своего МК. Я всегда так поступаю - отвечаю на вопросы по AVR, подразумевая по умолчанию ATmega8. Если не угадала - вопрошающий сам виноват. А то уже обрыдло всякий раз задавать один и тот же встречный вопрос "А что у вас?".

Цитата(e-leks @ Oct 3 2013, 22:28) *
2. Если нужно сделать генератор с варьируемым коэффициент заполнения и с одинаковым периодом, есть код проще моего?

Есть проще sm.gif. Тогда частоту меандра задают по переполнению таймера, а скважность задают через OCR. Тогда прерываться в прерывание вообще не нужно, но сигнал надо снимать с ноги OC2 (PD7).

Еще вариант - использовать таймер 1, который имеет пару OC1A (PD5) и OC1B (PD4). Тогда одним из них задают периодичность меандра, а вторым задают уровень, на котором возникает переключение уровня на ножке ОС.
e-leks
Люди добрые, я использовал "стандартные" подходы:
1. Установил делитель
2. Настроил таймер на сравнение
3. Использовал режим СТС для сброса
4. Включил прерывания глобально
Мне не нужно больше ничего придумывать, мне нужно понять: либо я написал что то неправильно, либо ошибка не в моих действиях. Прошу Вас помочь заставить мой код работать или ответить почему он не работает корректно. Неужели у столь большого сообщества специалистов нет ответа на далеко не самый сложный вопрос?

Благодарю!
Палыч
Поправьте оператор if в процедуре прерывания
Код
    if(PORTA & 0x01)
Поскольку непонятно, что у Вас там к соответствующей ноге подключено. То, что Вы на ногу РА0 выдали высокий уровень, вовсе не значит, что он там появится - может на эту ногу "навалиться" низкий уровень "извне".
e-leks
Цитата(Палыч @ Oct 4 2013, 19:12) *
Поправьте оператор if в процедуре прерывания

Не помогло, а может симулятор не корректно работать? Просто осциллографа нет, проверить не где. Попробую подключить к сервомашинке, посмотрю будет ли реагировать.
Палыч
Цитата(e-leks @ Oct 4 2013, 19:21) *
Не помогло, а может симулятор не корректно работать? Просто осциллографа нет, проверить не где.

Прошу прощения, не дочитал: "После пробного запуска кода в симуляторе..."
Что ж, попробую и я "прогнать" в симуляторе Вашу программу.
Имеем:
Низкий уровень = 18.56мс. Проверяем (0x90+1)*0.128=(144+1)*0.128=145*0.128= 18.56мс
Высокий уровень = 1.664мс. Проверяем (0x0C+1)*0.128=(12+1)*0.128=13*0.128= 1.664мс

Где некорректная работа таймера?
e-leks
Цитата(e-leks @ Oct 3 2013, 22:28) *
верх импульса - 33 мс, низ - 1,65 мс.

У меня получается участок с высоким уровнем 33 мс, а с низким 1,65 мс. Получается что симулятор (Proteus) врет.
Палыч
Цитата(e-leks @ Oct 4 2013, 20:03) *
У меня получается участок с высоким уровнем 33 мс, а с низким 1,65 мс. Получается что симулятор (Proteus) врет.

Я использовал симулятор AVRStudio.

В догонку: по поводу "правильности" программы - таймер следует запускать (заносить в поле CS22:0 регистра TCCR2 значение отличное от нуля) после того, как будут занесены нужные значения в остальные регистры таймера.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.