Serial и прерывания
- Войдите на сайт для отправки комментариев
Пт, 17/06/2016 - 14:21
Коллеги, подскажите решение.
Мне нужно управлять железкой в реальном времени с шагом времени 100 мкс. Нет проблем - использую прерывания по таймеру.
Но :( Одновременно мне нужно обмениваться данными с компьютером. Самое простое и очевидное - Serial
Однако прерывания и последовательный порт не работают :( Serial.write могу, а вот Serial.available Serial.read - нифига :(
Как быть?
Показать неработающий код, для начала :)
Если я делаю так:
То далее
Serial.print("ssf"); - работает
А вот
Serial.available() всегда возвращает 0
Serial.available() всегда возвращает 0
ок а, Serial.read(), что возвращает?
false
Я нашёл упоминание, что если повиснуть на прерываниях таймера, то Serial использовать низя :(
false
Я нашёл упоминание, что если повиснуть на прерываниях таймера, то Serial использовать низя :(
Без ума низзя, а с умом можно.
Кто согласен поделиться умом?
Кто согласен поделиться умом?
Так вроде DIYMan в посте №1 выразил такое желание и попросил Вас показать код. А Вы что сделали? Показали маленький огрызочек и опять стали руками разводить "а если так, а если эдак". А как человеку Вам помочь, если он не видит ни Вашей ISR, ни того, как именно Вы работаете с сериалом, ни функции loop? Хрустальный шар у него сейчас на техобслуживании, а без него Ваш код ему узнать неоткуда. Так что, если Вам нужна помощь, делайте. что Вам говорят. А если Вы боитесь публиковать код из опасений за свою интеллектуальную собственноть, так и решайте проблемы этой собственности самостоятельно.
Там нечего показывать :) Ну вот весь код для тестирования:
Если что-то пытаться ему отправлять, то видно, что контроллер мигает светодиодом, но эха нет.
Если сделать так:
Постоянно печатает 0-10-10-1... ну понимаете? Serial.available() всегда возвращает 0, Serial.read() всегда возвращает -1
Версия IDE?
1.23
Только, при чём тут версия IDE???? :)
Речь идёт о том, что аппаратный последовательный порт не желает работать, если я перенастраиваю прерывания.
TCNT2 = tcnt2; // вот здесь засада
суть в том, что Вы изменили время тика и а на него завязана скорость передачи UART
перевестте свой тик на другой таймер (который отвечает за ШИМ) и все наладится....
Ага... а примером не одарите?
1.23
Только, при чём тут версия IDE???? :)
Речь идёт о том, что аппаратный последовательный порт не желает работать, если я перенастраиваю прерывания.
Версия IDE при том, что если потребуется смотреть код Serial'а то надо знать, где смотреть.
Это Вам кажется. что Вы знаете о чём идёт речь. Если бы Вы и впрямь это знали, Вы бы сейчас здесь не задавали этот вопрос.
Какая у Вас Ардуина? В смысле контроллер какой? (На всякий случай, если Вам вопрос опять покахется пустым - есть большая разница между atmega328 2560
Ага... а примером не одарите?
нет, я на ардуинке таймеры никогда не программировал... просто понимаю принцепы по сколько делал подобное под DOS, только там все сложнее... а я Вам самое простое решение предложил...
а вообще поищите, здесь были классы для "многопоточности", там конечно сложно но там еще более правильное решение, расписывать его здесь не буду...
суть в том, что Вы изменили время тика и а на него завязана скорость передачи UART
На второй таймер??? Не могли бы Вы указать страницу даташита? Или другой источник?
ну и добавлю про версии IDE, там есть существенные различия в реализации прерываний, например раньше прерывания прерывали сами себя, сейчас вроде сделали вместо этого отдельную очередь....
Arduino nano 328
суть в том, что Вы изменили время тика и а на него завязана скорость передачи UART
На второй таймер??? Не могли бы Вы указать страницу даташита? Или другой источник?
всегда думал, что у меги несколько таймеров... если это не так, тогда нужно организовывать второй счетчик кратный делителю, о чем и написано выше (про многопоточность)
Хорошо. Nano у меня есть. Правда такой версии IDE как у Вас нету. Сегодня вечером я попробую запустить Ваш скетч и посмотрю на него. Всё там должно работать, я постоянно пользусь таймерами и Serial'ом - проблемы были только с мегой и там они тоже решабельны.
Спасибо
esisl,
это первая серия моего ответа. у меня Nano, 328, IDE - 1.6.5
Псмотрите, я использую тот же, что и Вы, таймер (2), тот же делитель (32) и то же количество тиков (206).
Как видите, в loop она проверяет нет ли чего в Serial'е, и, если есть, читает символ. Если символ буква, то она печатает её, затем знак равенства, затем значение переменной cnt.
Переменная же cnt просто увеличивается на 1 всякий раз при переполнении таймера.
Результат вполне ожидаемый:
Ну, я вводил t, o, p и т.п., а она в ответ печатад. cnt каждый раз успевала подрасти пока я там вводить собирался.
Всё адекватно?
Теперь запустите сами и убедитесь. что оно также работает и у Вас и никаких, как Вы думали "аппаратный последовательный порт не желает работать" нет в и в помине. Работает за милую душу, если нормально всё сделать.
Сейчас я внимательно посмотрю на Ваш код и будет вторая серия.
esisl, вы таймер программируете через #$$@. Зачем обнулять счётный регистр в прерывании? У таймера есть режим сброс по совпадению, записываете в регистр сравнения нужное число тактов, и всё. Вот то-же самое, но по-человечески:
На ввод данных реагирует.
Погодите, dimax, там смешнее всё. Бог с ней с Normal mode. Может человеку надо иногда менять длительность "переполнения", тогда он всё нормально делает.
Не подсказывайте, я хочу, что он сам дошёл почему у него не работает.
Вторая серия.
Теперь я взял ВАШУ инициализацию таймера (явно избыточную) вставил вместо своей. Всё остальное оставил как у меня было.
и опять ведь нормально работает!
Кстати, я не понял почему Вы при инициализации TCNT2 не проинициализировали? Первое прерывание у Вас когда попало наступит, ну да Бог с ним - работает ведь! Попробуйте!
Эээ... Потому, что я сбрасываю "лишние" биты?
P.S. На самом деле, потому, что это копипаста. Но я пытаюсь разобраться :-P
Третья серия.
Может дело в loop? Может там у Вас что не так? А может в том, что у меня скорость другая? Или в том, я сначала "Fun begins" печатаю?
Ладно, делаю ВСЁ как у Вас
Ну, что в окне терминала ввожу 1234<ENTER>qwerty<ENTER>zxcvb<ENTER> и что вижу? Так то и вижу
Попробуйте у Вас также?
И последняя серия.
Беру в точности Ваш скетч из поста №8.
Только убираю в нём дурацкую печать 0 при каждом проходе loop чтобы не засирала терминал
Убедитесь - это в чистом виде Ваш скетч. Одна строка закомментирована.
И .... он работает совершенно адекватно. Ввожу 1234<ENTER>qwerty<ENTER>zxcvb<ENTER> и получаю тоже, что и впрошлый раз! Запустите!
А теперь подумайте в чём у Вас проблема (не в той строке, что закомментировал - она не виновата).
Подумайте и скажите.
Сори, я это уже вечером попробую...
Попробуйте и скажите, что получится.
Т.е. не один из моих примеров Вы пока ещё не пробовали?
Да. Вот этот пример http://arduino.ru/forum/programmirovanie/serial-i-preryvaniya#comment-20... заработал.
Спасибо! :)
Так это ж Ваш пример, который вы мне выложили! Сравните!
Вы поняли в чём была проблема-то?
Нет. У Вас биты иначе выставляются.
Нет. У Вас биты иначе выставляются.
Евгений привёл РОВНО ваш скетч, только с одной закомментированной строчкой.
Нет. У Вас биты иначе выставляются.
Нет, все биты такие же. Это ВАШ скетч котрый я перенёс тупой копипастой в IDE и закомментировал одну строку. Но с той строкой тоже работает, только она все загаживает на экране и не видно ни хрена, так что дело не в ней. А вот в чём дело, Вам бы очень полезно разобраться.
В общем всем спасибо. Магия. Всё заработало, почему - не знаю.
Можно закрывать.
Магия. Всё заработало, почему - не знаю. Можно закрывать.
Жаль, что Вы не захотели разобраться. Значит, ждём следующей такой же темы.
А у меня не работает Serial.
Я использую библиотеку timer-api.h для установки прерывания по таймеру.
Библиотек решил юзать из-за простоты назначения таймеров (https://habr.com/ru/post/337430/)
Использую timer_init_ISR_500KHz(TIMER_DEFAULT);
Serial.write - работает
Serial.available и Serial.read - не работает.
При включенной строке timer_init_ISR_500KHz(TIMER_DEFAULT); не работает Serial.
При закомментированной строке Serial работает, но, соответственно, не работает функция прерывания по таймеру.
А как же ему бедному работать, если Вы ему работать не даёте. Прерывание работает дольше , чем Вы его вызываете.