Хм. приведенный вами код ничем не отличается от моего, только расположением объявления переменной i. Компилятор ругается. Вынес объявление переменной в начало скетча.
Вы проверяли скетч? У вас работает? У меня нет. В сериал гонит одни "0"
wdrakula, спасибо большое. Код работает. Единственны вопрос: я несколько раз натыкался на высказывание что число (с которым нужно сравнивать счетчик) нужно писать на 1 меньше. То есть не 62500U а 62499U. Это верно?
А за помощь спасибо. Я перечитал около 5-7-и статей, пересмотрел кучу роликов, все о чем пишется перепробовал сотню раз прежде чем писать на форуме... везде говорится только о явном объявлении. То есть если нужно записать OCIE1A в TIMSK1 то только его и прописывать, и БОЛЬШЕ НИЧЕГО... вот по этому я и не мог понять при чем здесь TCCR1A и TCNT1 если в их биты ничего записывать не нужно... вот такой вот подвох...
Единственный правильный источник - родной даташит на МС. Там написано как правильно действовать. Инициализировать первый раз надо все регистры, значения которых отличны от дефолтных. Последняя команда пуск таймера. Потом можно менять всё что угодно и как угодно и сколько угодно регистров, при условии что таймер предварительно остановлен.
К сожалению часто статьи пишут люди, для которых это давно известно и на этой мелочи они не упоминают.
А за помощь спасибо. Я перечитал около 5-7-и статей, пересмотрел кучу роликов, все о чем пишется перепробовал сотню раз прежде чем писать на форуме... везде говорится только о явном объявлении. То есть если нужно записать OCIE1A в TIMSK1 то только его и прописывать, и БОЛЬШЕ НИЧЕГО... вот по этому я и не мог понять при чем здесь TCCR1A и TCNT1 если в их биты ничего записывать не нужно... вот такой вот подвох...
это не подвох, а недомыслие. Ты неправильно применил информацию из книг. Там, вероятно, речь шла о контроллере ВНЕ среды Ардуино.
Я написал вчера: "посмотите свой wiring.c". Там настраиваются ВСЕ таймеры, для ШИМ вывода (analogWrite()). То есть регистры таймеров НЕ ЧИСТЫЕ. Значит, перепрограмируя таймер, придется отказаться от analogWrite() на соответствующих ногах и установить по-своему ВСЕ регистры таймера.
И еще ты забыл, что 0 тоже число. Если мода таймера = 4, то это значит 0100, а не только 1 в WGM12.
В ардуиновском wiring.c "черт ногу сломит"... Для людей, которые только начинают более глубоко изучать МК, там вообще ничего не понятно. Про ШИМ знаю, уже успел прочитать. Я его и не планировал использовать.
Ну, про "черт ногу сломит" это конечно я погарячился :) но там много команд из асемблера. Простому начинающему ардуинщику это как какие-то магические заклинания :)
Я имел в виду что переходя с Ардуино ИДЕ на нормальный С++ вдруг сталкиваешься еще с другим языком - от этого по первой голова пухнет.
Почему в определение прерывания ISR(TIMER1_COMPA_vect) вместо имени прерывания TIMER1_COMPA_vect можно вставить абсолютно любую комбинацию букв и цифр - и это будет компилироваться без ошибок? Разве при обнаружении в программе неизвестного идентификатора не должна возникать ошибка компиляции что-то вроде "xx is not declared" ?
наткнулся случайно, написал часть имени вектора маленькими буквами - все компилировалось, но не работало. Перерыл все, прежде чем заметил....
Почему в определение прерывания ISR(TIMER1_COMPA_vect) вместо имени прерывания TIMER1_COMPA_vect можно вставить абсолютно любую комбинацию букв и цифр - и это будет компилироваться без ошибок?
Ну, во-первых, предупреждение то Вам выдаётся, просто Вы, видимо, не включили предупреждения компилятора в "Настройках". По умолчанию разработчики IDE выключили выдачу предупреждений, чтобы типа новички не пугались предупреждений компилятора. Оно ж завсегда удобно спрятать голову в песок и работать вслепую.
Зайдите в "Настройки" и включите печать предупреждений компилятора. И, если у Вас есть ISR(kaka){}, то увидите нечто вроде:
C:\...\Kaka0.ino:6:5: warning: 'kaka' appears to be a misspelled signal handler, missing __vector prefix [-Wmisspelled-isr]
Но ошибкой это действительно не является и всё компилируется правильно. Попробую объяснить почему.
Ваша
ISR(kaka)
разворачивается (с точностью до аттрибутов) в
extern "C" void kaka (void)
Во-первых это очевидно, если посмотреть на текст макроса ISR (находится в файле interrupt.h), а во вторых в этом легко убедиться косвенно. Попробуйте скомпилировать такой текст:
Получите ругань на двойное определение функции kaka.
Таким образом, если Вы пишете ISR(kaka) {} и при этом у Вас в программе нет функции с таким именем, то ничего страшного не происходит - просто заводится функция с таким именем и всё. Никаких ошибок.
Ну дополню темку .. кроме написания своей millis(), что сделал ТС заюзав таймер по-своему, можно вполне спокойно вставить внутрь типового обработчика таймера вызов нужной для себя функции. Это освобождает таймер для работы с ШИМ. А если это сделать грамотно, обрамив "контрольным выстрелом" от двойного вызова и "спец.защитой" контекста исполнения, то вполне можно вызывать и даже большие задачки, но только по одной.
В моем варианте реализации предлагался timerHook для таких целей..
То есть первая секция (UART, в которой пока рандомно заполняется массив) периодически выполняется на 1 мс (то есть вдвое!) дольше.
Это если настроить прерывание по совпадению. Если использовать тот же таймер в режиме переполнения, показания практически стабильны. Первоначально вместо прерывания была конструкция if( (millis() - currentMillis) > 500 ), время выполнения всех секций также плавало в пределах 8 мкс, то есть практически не менялось.
Кто-нибудь может просветить, с чем может быть связано такое поведение?
ПС Изменил код в секции UART:
if( tactNo == 0 ) { //-------------- Load UART
currentMicros = micros();
for(byte i = 0; i < 64; i++) {
massivLED[i] = (i * i + 789)/ 3 ; //random(0, 255);
}//*/
Serial.print("time us UART="); Serial.print(micros() - currentMicros);
}
Теперь вывод такой:
time us UART=1088 Key=60 LED=272 micros=91552620
time us UART=64 Key=60 LED=272 micros=91743788
time us UART=1088 Key=60 LED=272 micros=91935980
time us UART=1088 Key=60 LED=272 micros=92128172
time us UART=1092 Key=60 LED=272 micros=92320364
time us UART=1088 Key=60 LED=272 micros=92512556
time us UART=1088 Key=60 LED=272 micros=92704748
time us UART=1088 Key=60 LED=272 micros=92896940
time us UART=1088 Key=60 LED=272 micros=93088108
time us UART=1088 Key=64 LED=272 micros=93280300
time us UART=1088 Key=60 LED=272 micros=93472492
time us UART=1088 Key=60 LED=272 micros=93663660
time us UART=1088 Key=60 LED=272 micros=93855852
time us UART=1088 Key=60 LED=272 micros=94048044
time us UART=1088 Key=60 LED=276 micros=94239216
time us UART=1088 Key=60 LED=272 micros=94431404
time us UART=1088 Key=60 LED=272 micros=94623596
time us UART=64 Key=60 LED=272 micros=94814764
time us UART=1088 Key=60 LED=272 micros=95006956
То есть каждый 16-й расчёт пропускается!! Я в ауте...
Поторопился я с выводами... Поигрался с прескалером для режима overflow, получил такой же эффект - в среднем один такт из пяти расчёт занимает на 1 мс больше времени. Было:
Может вы не умеете программировать?
Хм. приведенный вами код ничем не отличается от моего, только расположением объявления переменной i. Компилятор ругается. Вынес объявление переменной в начало скетча.
Вы проверяли скетч? У вас работает? У меня нет. В сериал гонит одни "0"
volatile потерял. Обязательно при прерывании. Как и вы тоже.
delay(1488);
У меня всеравно не работает. Ваш пример тоже молчит. Может сам указатель не правильный TIM1_COMPA?
У меня всеравно не работает. Ваш пример тоже молчит. Может сам указатель не правильный TIM1_COMPA?
Здесь я не скажу. Я так глубоко не копаю. Зачем если надо повесить фонарики на крышу разбирать всю машину.
Я уже спать ушел. С телефона прочел. Вы блин абалдели!
Я же написал ВСЕ, БЛИН, настройки. TCCR1A Пушкин будет описывать?
я всё отменил.
Слава НАТОвским базам вокруг Суберии!
И вектор, конечно, TIMER1_COMPA_vect.
ок. и, вектор отменил к ебеням Трампа.
пропробуй, вдруг да влезеть
https://github.com/DetSimen/Arduino-
Причесал я твою помойку. Оно компилируется и работает.
Жду "спасибо". Гиннес подойдет.
Понял, где у тебя была ошибка, кроме ДНК?
wdrakula, спасибо большое. Код работает. Единственны вопрос: я несколько раз натыкался на высказывание что число (с которым нужно сравнивать счетчик) нужно писать на 1 меньше. То есть не 62500U а 62499U. Это верно?
А за помощь спасибо. Я перечитал около 5-7-и статей, пересмотрел кучу роликов, все о чем пишется перепробовал сотню раз прежде чем писать на форуме... везде говорится только о явном объявлении. То есть если нужно записать OCIE1A в TIMSK1 то только его и прописывать, и БОЛЬШЕ НИЧЕГО... вот по этому я и не мог понять при чем здесь TCCR1A и TCNT1 если в их биты ничего записывать не нужно... вот такой вот подвох...
Единственный правильный источник - родной даташит на МС. Там написано как правильно действовать. Инициализировать первый раз надо все регистры, значения которых отличны от дефолтных. Последняя команда пуск таймера. Потом можно менять всё что угодно и как угодно и сколько угодно регистров, при условии что таймер предварительно остановлен.
К сожалению часто статьи пишут люди, для которых это давно известно и на этой мелочи они не упоминают.
То есть не 62500U а 62499U. Это верно?
Да, счет идет от 0.
А за помощь спасибо. Я перечитал около 5-7-и статей, пересмотрел кучу роликов, все о чем пишется перепробовал сотню раз прежде чем писать на форуме... везде говорится только о явном объявлении. То есть если нужно записать OCIE1A в TIMSK1 то только его и прописывать, и БОЛЬШЕ НИЧЕГО... вот по этому я и не мог понять при чем здесь TCCR1A и TCNT1 если в их биты ничего записывать не нужно... вот такой вот подвох...
это не подвох, а недомыслие. Ты неправильно применил информацию из книг. Там, вероятно, речь шла о контроллере ВНЕ среды Ардуино.
Я написал вчера: "посмотите свой wiring.c". Там настраиваются ВСЕ таймеры, для ШИМ вывода (analogWrite()). То есть регистры таймеров НЕ ЧИСТЫЕ. Значит, перепрограмируя таймер, придется отказаться от analogWrite() на соответствующих ногах и установить по-своему ВСЕ регистры таймера.
И еще ты забыл, что 0 тоже число. Если мода таймера = 4, то это значит 0100, а не только 1 в WGM12.
В ардуиновском wiring.c "черт ногу сломит"... Для людей, которые только начинают более глубоко изучать МК, там вообще ничего не понятно. Про ШИМ знаю, уже успел прочитать. Я его и не планировал использовать.
Еще раз спасибо за помощь.
В ардуиновском wiring.c "черт ногу сломит"... Для людей, которые только начинают более глубоко изучать МК, там вообще ничего не понятно.
Да????? От оно как.... ну ладно.
Ну, про "черт ногу сломит" это конечно я погарячился :) но там много команд из асемблера. Простому начинающему ардуинщику это как какие-то магические заклинания :)
Я имел в виду что переходя с Ардуино ИДЕ на нормальный С++ вдруг сталкиваешься еще с другим языком - от этого по первой голова пухнет.
Я имел в виду что переходя с Ардуино ИДЕ на нормальный С++ вдруг сталкиваешься еще с другим языком - от этого по первой голова пухнет.
1. Чем С++ в IDE ненормален?
2. С каким "другим языком" Вы столкнулись?
А чёрт ногу сломит просто потому, что Вы не знаете языка (С и С++). Для тех, кто знает, там нет ничего сложного.
проштудировал эту тему, вроде все понятно :)
Но при переходе к практике возник вопрос -
Почему в определение прерывания ISR(TIMER1_COMPA_vect) вместо имени прерывания TIMER1_COMPA_vect можно вставить абсолютно любую комбинацию букв и цифр - и это будет компилироваться без ошибок? Разве при обнаружении в программе неизвестного идентификатора не должна возникать ошибка компиляции что-то вроде "xx is not declared" ?
наткнулся случайно, написал часть имени вектора маленькими буквами - все компилировалось, но не работало. Перерыл все, прежде чем заметил....
Почему в определение прерывания ISR(TIMER1_COMPA_vect) вместо имени прерывания TIMER1_COMPA_vect можно вставить абсолютно любую комбинацию букв и цифр - и это будет компилироваться без ошибок?
Ну, во-первых, предупреждение то Вам выдаётся, просто Вы, видимо, не включили предупреждения компилятора в "Настройках". По умолчанию разработчики IDE выключили выдачу предупреждений, чтобы типа новички не пугались предупреждений компилятора. Оно ж завсегда удобно спрятать голову в песок и работать вслепую.
Зайдите в "Настройки" и включите печать предупреждений компилятора. И, если у Вас есть ISR(kaka){}, то увидите нечто вроде:
Но ошибкой это действительно не является и всё компилируется правильно. Попробую объяснить почему.
Ваша
разворачивается (с точностью до аттрибутов) в
Во-первых это очевидно, если посмотреть на текст макроса ISR (находится в файле interrupt.h), а во вторых в этом легко убедиться косвенно. Попробуйте скомпилировать такой текст:
Получите ругань на двойное определение функции kaka.
Таким образом, если Вы пишете ISR(kaka) {} и при этом у Вас в программе нет функции с таким именем, то ничего страшного не происходит - просто заводится функция с таким именем и всё. Никаких ошибок.
Евгений, огромное спасибо за разъяснения.
Предупреждений компилятора не вижу, потому что мучаю код в симуляторе (живой ардуины под рукой сейчас нет).
Всем СПАСИБО, разобрался!)))
Ну дополню темку .. кроме написания своей millis(), что сделал ТС заюзав таймер по-своему, можно вполне спокойно вставить внутрь типового обработчика таймера вызов нужной для себя функции. Это освобождает таймер для работы с ШИМ. А если это сделать грамотно, обрамив "контрольным выстрелом" от двойного вызова и "спец.защитой" контекста исполнения, то вполне можно вызывать и даже большие задачки, но только по одной.
В моем варианте реализации предлагался timerHook для таких целей..
Прорабатываю путь, которым дуть, для нового проекта, столкнулся со следующим багом (или фичей??) при использовании таймера. Часть скетча (Мега2560):
В итоге получаю такой отчёт:
Поторопился я с выводами... Поигрался с прескалером для режима overflow, получил такой же эффект - в среднем один такт из пяти расчёт занимает на 1 мс больше времени. Было:
Стало:
То есть частота вызова прерывания осталось почти та же.
ПС Возникла мысль - может кто-то сбрасывает предделитель??