Atmega8 LTO (перенос кода с ардуино)

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

Что то вы совсем поплыли ...

Да... "Зеленый змий" стал преобладать. Да и хрен с ним.

Прошу прощения за отнятое время.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

1 Интервалы обратно пропорционально зависят от скорости вращения энкодера !!!

Логично, ведь при увеличении вращения увеличивается количество импульсов/за время.

Komandir пишет:

2 Где обновление prevTime ?

Оно на самом деле есть, я вчера вычищал комментарии и "промазал" (удалил эту строчку).

Komandir пишет:

3 Дребезг по паспорту энкодера - около 2 мс !!!

На радиокоте проскакивали сообщения о времени от 30 до 120 мс.

Komandir пишет:

4 На осциллограмме дребезга не видно СОВСЕМ.

И я о том же сначала сказал. Однако ж были "перескакивания". Но змий и "мудрство" творят "чудеса" ))

Komandir пишет:

5 Внешняя подтяжка выходов энкодера есть ?

Внешней нет, есть внутренняя (на осциллограмме хорошо видно, что импульсы генерируются подтяжкой к GND).

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

 digitalRead(PIN_PC5) ? number += 1000 :number -= 1000) ;

А он точно работает у Вас? У меня только так скомпилировалось:

digitalRead((PIN_PC5) ? number += 1000 : number -= 1000);

И не заработало ))

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

BOOM пишет:

Komandir пишет:

 digitalRead(PIN_PC5) ? number += 1000 :number -= 1000) ;

А он точно работает у Вас? У меня только так скомпилировалось:

digitalRead((PIN_PC5) ? number += 1000 : number -= 1000);

И не заработало ))

и не заработает

в коде от Komandir скобка лишняя в конце.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

xDriver пишет:

в коде от Komandir скобка лишняя в конце.

Ну я в начале поставил еще одну (как ты не заметил выше). Я думаю это потому, что он как и в бибилиотеке Rotary использовал пины 2 и 3, а у меня используется только один - 2.

Я бы попробовал еще опрос энкодера через таймер (как деда говорил), но его код очень сложный для меня еще. А как проще сделать я не знаю.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

На самом деле вот этот код:

ISR(INT0_vect) {      // Это для Atmega8/16/32
  int8_t tick, res1, res2;
  uint16_t currentTime = millis();

  if (currentTime - prevTime > rtInterval) {
    //  digitalRead(PIN_PD2) ? tick = 1 : tick = -1;
    //  delay(1);                                             // Не помогает
    prevTime = currentTime;
    res1 = digitalRead(PIN_PC5);
    //  delay(1);                                             // Не помогает
    res2 = digitalRead(PIN_PD2);
    //  if ( ((res1 ? tick = 1 : tick = -1) == 1) && (((res2) ? tick = 1 : tick = -1) == -1 ) ) {
    if ( (( digitalRead(PIN_PC5) ? tick = 1 : tick = -1) == 1) && ((digitalRead(PIN_PD2) ? tick = 1 : tick = -1) == -1 ) ) {
      number += (int16_t)tick * 1000;
    } else {
      number -= (int16_t)tick * 1000;
    }

  }
}

Работает хорошо, но почему то есть "пропуски", не в смысле крутишь и пропустил, а в смысле - 1,2,3,7,8,9 (конечно же меняются самые правые "биты" "дисплея".

И не понятно почему. Ведь на осциллограмме нет дребезга (да и в коде "антидребезг есть"). Как это так?

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

У меня нет atmega8 и код для нее я рисовал на основе кода 328 (который работает), подправьте синтаксис ...

У меня для прерываний используется только PD2 !!!

Надо включить подтяжки на оба вывода PD2 и PC5 - digatslWrite(..., HIGH) !!!

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

подправьте синтаксис ...

Не понял о каком синтаксисе речь.

 

Komandir пишет:

У меня для прерываний используется только PD2 !!!

У меня тоже. Второй вывод энкодера на PC5.

Komandir пишет:

Надо включить подтяжки на оба вывода PD2 и PC5 - digatslWrite(..., HIGH) !!!

Так изначально и сделано (и это хорошо видно на осциллограмме).

nik182
Offline
Зарегистрирован: 04.05.2015

Попробуйте выбросить миллис и всё что с ним связано и вставить delayMicroceconds(100) самой первой строчкой прерывания и после проверять кто LOW. 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Мне кажется, что все-же виновником является энкодер (а так как памяти у DSO5102P мягко говоря - маловато, то я просто не могу на осциллограмме это увидеть). Я провел другой эксперимент.

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

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

Ну и, честно говоря, мне непонятно - как так то? По осциллограмме вообще не должно быть срабатываний, а в коде есть.

Использовал этот код (комментарии не стал удалять), задержка была 2мс.

ISR(INT0_vect) {      // Это для Atmega8/16/32
  int8_t tick, res1, res2;
  uint16_t currentTime = millis();

  if (currentTime - prevTime > rtInterval) {
    //  digitalRead(PIN_PD2) ? tick = 1 : tick = -1;
    //  delay(1);                                             // Не помогает
    prevTime = currentTime;
    res1 = digitalRead(PIN_PC5);
    //  delay(1);                                             // Не помогает
    res2 = digitalRead(PIN_PD2);
    //  if ( ((res1 ? tick = 1 : tick = -1) == 1) && (((res2) ? tick = 1 : tick = -1) == -1 ) ) {
    if ( (( digitalRead(PIN_PC5) ? tick = 1 : tick = -1) == 1) && ((digitalRead(PIN_PD2) ? tick = 1 : tick = -1) == -1 ) ) {
      number += (int16_t)tick * 1000;
    } else {
      number -= (int16_t)tick * 1000;
    }

  }
}

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Запаял новый (другой уже и тоже новый)  энкодер - проблема ушла. Прекрасно работает и с задержкой и без нее (думаю, что это потому что у DSO5102P на мнооого меньше памяти чем у того же DSO5102B (2Mb) и он просто пропускал дребезг). Работает схема только на этом коде (код от komandir'а работает только одно значение (либо только инкремент, либо только декремент):

const uint8_t Rotary1 = PIN_PD2;    // | Первый пин энкодера
const uint8_t Rotary2 = PIN_PC5;    // | Второй пин энкодера
const uint16_t rtInterval = 2;     // | Интервал между срабатыванием энкодера (устранение дребезга контактов энкодера)

void setup() {
  /*
    Komandir:
  */
  MCUCR |= (1 << ISC01);
  MCUCR |= (1 << ISC00);
  GICR |= (1 << INT0);
  sei();

    pinMode(Rotary1, INPUT_PULLUP);
    pinMode(Rotary2, INPUT_PULLUP);
}

ISR(INT0_vect) {
  int8_t tick, res1, res2;
  uint16_t currentTime = millis();

  if (currentTime - prevTime > rtInterval) {
    prevTime = currentTime;
    res1 = digitalRead(PIN_PC5);
    res2 = digitalRead(PIN_PD2);
    if ( (( digitalRead(PIN_PC5) ? tick = 1 : tick = -1) == 1) && ((digitalRead(PIN_PD2) ? tick = 1 : tick = -1) == -1 ) ) {
      number += (int16_t)tick * 1000;
    } else {
      number -= (int16_t)tick * 1000;
    }
  }
}

(Конечно же это только часть кода, что относится к энкодеру)

nik182
Offline
Зарегистрирован: 04.05.2015

Не правильно ты дядя Фёдор бутерброд ешь. Его надо колбасой на язык... перевести осциллограф в однократный режим, поставить разрешение микросекунд 200 на клетку, запуск от фронта любого канала, память процентов 25 и крутануть ручку, разок в одну сторону сохраниться и разок в другую. Можно будет увидеть дребезг. Возможно надо развертку по времени ещё уменьшить. Так, что бы на весь кадр только один импульс был. Не надо много импульсов. Не видно ничего. 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

nik182 пишет:

Не правильно ты дядя Фёдор бутерброд ешь. Его надо колбасой на язык... перевести осциллограф в однократный режим, поставить разрешение микросекунд 200 на клетку, запуск от фронта любого канала, память процентов 25 и крутануть ручку, разок в одну сторону сохраниться и разок в другую. Можно будет увидеть дребезг. Возможно надо развертку по времени ещё уменьшить. Так, что бы на весь кадр только один импульс был. Не надо много импульсов. Не видно ничего. 

Это хорошая идея на "отвлечься", энкодер я выпаял, но не выкинул. Отложил в сторону (хотя хотелось по нему молотком! Но молотка дома нет сейчас, да и я сейчас "под шафэ" )) В гараж точно не поеду. Да и хожу "морской походкой" ))

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Надо было не добавлять скобку, а убрать одну в конце !

digitalRead(PIN_PC5) ? number += 1000 : number -= 1000;

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:
Надо было не добавлять скобку, а убрать одну в конце ! digitalRead(PIN_PC5) ? number += 1000 : number -= 1000;

Ты серьезно считаешь, что это что-либо изменило бы? Я могу проверить. Подожди...

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

BOOM пишет:

Ты серьезно считаешь, что это что-либо изменило бы? Я могу проверить. Подожди...

Да! А я, тупая голова, думал в это нет смысла (расставил скобки как захотел), но все же РАБОТАЕТ! Значит я не совсем ущербен. ОГРОМНОЕ СПАСИБО!!!

Код:

ISR(INT0_vect) {      // Это для Atmega8/16/32
  uint16_t currentTime = millis();
  if (currentTime - prevTime > rtInterval) {
    prevTime = currentTime;
    digitalRead(PIN_PC5) ? number -= 1000 : number += 1000;
  }
}

РАБОТАЕТ!!! ))

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

И да, я сейчас именно (видимо трезветь начал) понимаю, что скобки мои были "далеко не на своих местах". Ну чтож, если не помру в ближайшее время от "зеленого змия", то точно завяжу с ним. Ну и с парочкой соседей в общении. Большое спасибо, что хоть на последней отдушине души не бросили в омут.

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

BOOM пишет:

BOOM пишет:

Ты серьезно считаешь, что это что-либо изменило бы? Я могу проверить. Подожди...

Да! А я, тупая голова, думал в это нет смысла (расставил скобки как захотел), но все же РАБОТАЕТ! Значит я не совсем ущербен. ОГРОМНОЕ СПАСИБО!!!

Код:

ISR(INT0_vect) {      // Это для Atmega8/16/32
  uint16_t currentTime = millis();
  if (currentTime - prevTime > rtInterval) {
    prevTime = currentTime;
    digitalRead(PIN_PC5) ? number -= 1000 : number += 1000;
  }
}

РАБОТАЕТ!!! ))

пиз@дец, я те че в #104 сказал

завязывай бухать.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

xDriver пишет:

завязывай бухать.

Вот кстати вопрос - что значит «бухать» и что значит «запой»? Это так - куда я качусь..

Green
Offline
Зарегистрирован: 01.10.2015

Бухой - не бухой, но азы то знать надо! А не методом тыка всё.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

BOOM пишет:

Я на самом деле удивлен - Почему в решении этого вопроса мне откликнулся помогать только komandir?

Так радоваться надо: диалог - разговор двоих - наиболее эффективный вариант. Когда советчиков много, всегда проявляется эффект лебедя, рака и щуки. Поэтому при эффективном взаимодействии двоих третьему лучше не вмешиваться (сколько бы этих "третьих" ни было).

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Хочу поднять тему вот по какому "случаю". Я поменял энкодер и пару-тройку недель все было в шоколаде, но спустя время и поменянный энкодер стал выдавать "то +/то-". Знаю, этого популяризатора ардуино тут не любят, но именно его код заработал отлично. Со старым энкодером:

/*
 * Данный код выполнен из примера "Гайвера". Это подключаемый .h файл, который обеспечил стабильную работу энкодера.
 */

#define ENC_A PIN_PD2              // | Первый пин энкодера
#define ENC_B PIN_PC5              // | Второй пин энкодера

volatile boolean state0, lastState, turnFlag;

extern uint32_t number;

// Код по гайверу:
void int0() {
  state0 = digitalRead(ENC_A);
  if (state0 != lastState) {
    turnFlag = !turnFlag;
    if (turnFlag) {
      number += (digitalRead(ENC_B) != lastState) ? -1000 : 1000;
    }
    lastState = state0;
  }
}

/*
 * В мэйн части (основном скетче) написано следующее:
 */

void setup() {
  attachInterrupt(0, int0, CHANGE); // | Привязываем функцию int0() к прерыванию INT0 по любому изменению уровня (CHANGE)
  sei();                            // | Разрешаем глобальные прерывания

  pinMode(ENC_A, INPUT_PULLUP);
  pinMode(ENC_B, INPUT_PULLUP);
}

Код отлично работает. На "правильность" кода - усмотрение читающих, в моем случае (одно прерывание) он подошел идеально!...

Ну и чтоб никого не обидеть ссылка на статью: Быстрая обработка энкодера digitalRead()

Не рекламы ради, а пользы для...

Green
Offline
Зарегистрирован: 01.10.2015

А sei() для надёжности?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Осталось "по наследству" )))

Kakmyc
Offline
Зарегистрирован: 15.01.2018

А расскажи зачем там нужен CHANGE ?
Может просто стоит вникнуть в то как работает энкрдер и понять , что за один щелчок он совершает полный цикл переключений ?
Тогда очевидно станет ясно, что RISING/FALLING тупо сократят половину кода прерывания и весь код для FALLING будет выглядеть так:
digitalRead(EncB)?val++:val--;

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Поясню как это работает:
Вход в прерывание только по смене состояния пина EncA по заднему фронту сигнала.
Т.е. мы уже знаем, что на пине EncA лог0, мы же в прерывание из за этого и попали.
Теперь нам осталось прочитать состояние пина EncB.
Если там лог1 то инкрементируем счётчик, если лог0 то декрементируем(или наоборот , по желанию).
Борьба с дребезгом отдельная песня.
Можно тот же миллис использовать, чтоб результат опроса учитывать скажем не чаще чем 1 раз в 20мс.

Я предпочитаю делать это аппаратно посредством mc14490

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Kakmyc пишет:
ясно, что RISING/FALLING тупо сократят половину кода прерывания и весь код для FALLING будет выглядеть так: digitalRead(EncB)?val++:val--;

Собственно говоря у меня и был подобный код (по прерываю FALLING):

ISR(INT0_vect) {    
  uint16_t currentTime = millis();
  if (currentTime - prevTime > rtInterval) {
    prevTime = currentTime;
    digitalRead(PIN_PC5) ? number -= 1000 : number += 1000;
  }
}

Но он работал не корректно - При медленном вращении наблюдалось 4/5/6/5/6.

 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018
void int0() {
  state0 = digitalRead(ENC_A);
  if (state0 != lastState) {
    turnFlag = !turnFlag;
    if (turnFlag) {
      number += (digitalRead(ENC_B) != lastState) ? -1000 : 1000;
    }
    lastState = state0;
  }
}

Ну это же как раз программный перевод CHANGE к FALLING или RISING.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

Ну это же как раз программный перевод CHANGE к FALLING или RISING.

Это понятно.

Не понятно - Почему же с этим кодом корректно стало медленное вращение работать?

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Код более антидребезговый получился. Подозреваю что на больших скоростях будет пропускать щелчки.

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Чего непонятного то ?
Тут идёт проверка на то что было вращение.
Увеличь время на устранение дребезга(в твоём случае на щелчок убитого энкодера и нормально всё будет).
Я делаю так:

if(!EncTick)digitalRead(EncA)?EncTick=1:EncTick=-1;

EncTick в коде сбрасывается в 0 после использования.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

Подозреваю что на больших скоростях будет пропускать щелчки.

Даже если и будет - я этого на больших скоростях и не замечу (то есть - для меня приемлемо). )))

Kakmyc пишет:
Я делаю так:

if(!EncTick)digitalRead(EncA)?EncTick=1:EncTick=-1;

EncTick в коде сбрасывается в 0 после использования.

Хм, интересный подход - надо будет попробовать.

По поводу времени на антидребезг - я начал с 2мс (как советовал Командир) и постепенно добрался до 50мс. При этом ситуация не улучшилась... (((( (Может нужно было и дальше увеличивать? Но я побоялся).

ЗЫ: От тактовой это как-то зависит? У меня всего 1МГц от внутреннего генератора...

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Все равно и с новым кодом проблема на медленных оборотах  проявлялась. Хоть и не так часто.

В общем принял кардинальное решение:

1. Поднял тактовую до 8МГц (от внутреннего генератора)

2. Подключил библиотеку Rotary и опрашиваю энкодер в loop()

Все стало просто великолепно!

Green
Offline
Зарегистрирован: 01.10.2015

А если до 16-ти поднять, то станет в 2 раза великолепнее. Не просто, а просто - просто!

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Green пишет:

А если до 16-ти поднять, то станет в 2 раза великолепнее. Не просто, а просто - просто!

Не исключено!  )))))

Тактовую поднял по другой причине (пошло бонусом )) )...

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Прошу обратить внимание на дату предыдущих сообщений. Сегодня уже 2е... ))

b707
Offline
Зарегистрирован: 26.05.2017

BOOM пишет:

Сегодня уже 2е... ))

ты отставешь от жизни, 7-е !

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Посмотри на Календарь - 8е уже! 
(Специально ждал, не отвечал )))) )

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Прошу более опытных товарищей проверить ход моих вычислений и, если нужно, поправить:

/*
 * Atmega8. Тактовая 8 МГц
 * За 1 сеунду: 8*1000*1000, значит переполнится 8 битны таймер2 с предделителем 256:
 * ( 8*1000*1000 / 256 ) / 256 = 122 раза в сек. Это составляет:
 * 1 / 122 = ~0,0082 сек. Или другими словами - каждые ~8,2 миллисекунды.
 */

void setup() {

  TIMSK |= (1<<TOIE2);                          // включаем timer2
  TCCR2 |= (1<<CS22) | (1<<CS21);    // предделитель 1/256
  sei();
}

void loop() {
}

ISR(TIMER2_OVF_vect) {

  // Выполняю какие-то действия каждые 8,2 миллисекунды
}

Даташит на Atmega8: https://static.chipdip.ru/lib/547/DOC005547852.pdf

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Как то ты считаешь непонятно.
1млнмкс/8мгц=0.125мкс время одного такта
0.125*256=32мкс время переполнения таймера(без делителя)
С предделителем 256
32*256=8192мкс
1млнмкс/8192мкс=122.07

Неровненько

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Я округлял (~), значит правильные у меня вычисления?

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Если от внутреннего генератора, то там точность +- километр, особенно если меняется температура...

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Ничего прецизионного не нужно, +/- меня вполне устроит.

А как использовать один таймер для двух задач? Где-то читал про использование таймера на переполнение и совпадение одновременно (счетчик не сбрасывается), но не могу вспомнить и найти - где я это видел...

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Задай точку сравнения и разреши прерывание... Только тикать они будут с одинаковой частотой, но разнесутся по времени.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Во, нашел где видел. Получается так:

void setup() {

  TIMSK |= (1<<TOIE2);                // включаем timer2
  TCCR2 |= (1<<WGM21) | (WGM20)       // Активируем режим FastPWM, в этом режиме при совпадении счетчика он не обнуляется и считает до переполнения
  TCCR2 |= (1<<CS22) | (1<<CS21);     // предделитель 1/256
  OCR2 = 128;
  sei();
}

void loop() {
}

ISR(TIMER2_OVF_vect) {

  // Выполняю какие-то действия каждые ~8,2 миллисекунды
}

ISR (TIMER2_COMP_vect){
  // Выполняю какие-то действия примерно каждые ~4,1 миллисекунды  
}

Правильно?

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Не вижу разрешения прерывания по совпадению OCIE2

TIMSK |= (1<<TOIE2);                // включаем timer2

это не включение таймера - это разрешение прерываний по переполнению

включается/выключаются таймер выставлением значения предделителя !

И режим работы таймера скорее всего должен быть NORMAL !!!

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

Не вижу разрешения прерывания по совпадению OCIE2

TIMSK |= (1<<TOIE2);                // включаем timer2

это не включение таймера - это разрешение прерываний по переполнению

включается/выключаются таймер выставлением значения предделителя !

Точно! Исправляемся:

void setup() {

  TIMSK |= (1<<TOIE2) | (1<<OCIE2);        // Разрешаем прерывания timer2 по переполнению (TOIE2)и совпадению (OCIE2)
  TCCR2 |= (1<<WGM21) | (1<<WGM20)         // Активируем режим FastPWM, в этом режиме при совпадении счетчика он не обнуляется и считает до переполнения
  TCCR2 |= (1<<CS22) | (1<<CS21);          // предделитель 1/256
  OCR2 = 128;                              // Устанавливаем значение для совпадения
  sei();
}

void loop() {
}

ISR(TIMER2_OVF_vect) {

  // Выполняю какие-то действия каждые 8,2 миллисекунды
}

ISR (TIMER2_COMP_vect){
  // Выполняю какие-то действия примерно каждые 4,1 миллисекунды  
  // А вот так можно делать?::
  if (OCR2 == 128) {
    // Что-то делаем
    OCR2 = 180;
  }
  if (OCR2 == 180) {
    // Что-то делаем
    OCR2 = 128;
  }
}

Komandir пишет:

И режим работы таймера скорее всего должен быть NORMAL !!!

Не могу ничего сказать, так как не совсем понимаю вот это:

Бит 6,3 — WGM21:0: Режим генерации сигнала
Эти биты управляют последовательностью подсчета счетчика, источником максимального (TOP) значения счетчика и какой тип генерации сигнала будет использоваться. Режимы работы, поддерживаемые блоком Таймер/Счетчик: Нормальный режим Clear Timer on Compare Match (CTC) и два типа режимов широтно-импульсной модуляции (PWM). Видеть Табл. 18-2 и «Режимы работы» на стр. 111.

Что такое TOV2 Flag Set и Update of OCR2 ?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Если режим NORMAL, то получается так:

void setup() {

  TIMSK |= (1<<TOIE2) | (1<<OCIE2);        // Разрешаем прерывания timer2 по переполнению (TOIE2)и совпадению (OCIE2)
  TCCR2 |= (1<<CS22) | (1<<CS21);          // предделитель 1/256
  OCR2 = 128;                              // Устанавливаем значение для совпадения
  sei();
}

void loop() {
}

ISR(TIMER2_OVF_vect) {

  // Выполняю какие-то действия каждые 8,2 миллисекунды
}

ISR (TIMER2_COMP_vect){
  // Выполняю какие-то действия примерно каждые 4,1 миллисекунды  
  // А вот так можно делать?::
  if (OCR2 == 128) {
    // Что-то делаем
    OCR2 = 180;
  }
  if (OCR2 == 180) {
    // Что-то делаем
    OCR2 = 128;
  }
}

 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Строки 5 и 6 я бы поменял местами - сначала настраиваем таймер, потом запускаем.

каждые 4.1 не получится - для этого надо менять OCR в прерывании - прописывая по очереди 0 и 128

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

Строки 5 и 6 я бы поменял местами - сначала настраиваем таймер, потом запускаем.

Понял

Komandir пишет:

каждые 4.1 не получится - для этого надо менять OCR в прерывании - прописывая по очереди 0 и 128

А как же TOP 0xFF, то есть я так понимаю что в отличии от CTC в этом режиме сработало прерывание и счетчик пошел дальше до переполнения. Не прав?