UART+Interrupt

alfik777
alfik777 аватар
Offline
Зарегистрирован: 29.06.2015

Меня, как всегда,  тянет изобретать велосипед... По UART  необходимо организовать обмен. Опрос в цикле не подходит.  В скетче используется прерывание по таймеру- 10 ms. Хочется  нему прикрутить проверку буфера UART, при появлении в буфере данных выставляю флажок, пока он висит - формирую строку:

 void intTimer()
 {
 .....Что-то там...
     if (Serial.available() > 0   && readSerialFlag==0) //пришли данные из PC
     {readSerialFlag=1;readSerialStr();}
 }

Обработка полученных данных:

 void    readSerialStr()
 {
  recString="";
   while (Serial.available())
    {
     char c = Serial.read();     //читаем символ
     recString += c;                     //добавляем к строке
     if (c=='\n') 
        {             //--тут анализ строки   recString-----             }        

         readSerialFlag=0;
     }//----while

 }

В результате часть данных при приеме теряется, просто обрезается текст. Для пробы поставил таймер на 100мс - и стало почти всё нормально, дальнейшее увеличение времени таймера , равно как и уменьшение- становится только хуже. Ткните ,в чем проблема, а то зациклился уже.

 

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

я думаю, что теряется у тебя при отправке, а не приёме - при отправке проверяй не равно ли место в буфере сериала нулю.

и, зачем прерывание, если и без прерывания всё должно корректно приниматься - если не принялось, то отправитель должен подождать, т.к. ты не сразу впуливаешь в сериал, а проверяешь не забит ли буфер ещё не отправленным.

в DigiUSB так делаю, как в Сериале не нашёл, но должен быть аналог tx_remaining

// эхо строки. (необязательная часть кода, используется для отладки)
if (DigiUSB.tx_remaining() > (b.length() + 1)) { // проверка места в буфере USB для строки длиной + 1 символ.

//***эхо-печать в DigiUSB собранной строки(для отладки).
DigiUSB.print(b);

}

 

alfik777
alfik777 аватар
Offline
Зарегистрирован: 29.06.2015

Клапауций 322 пишет:

я думаю, что теряется у тебя при отправке, а не приёме - при отправке проверяй не равно ли место в буфере сериала нулю.

Ну такая же ситуация когда отправляю с терминала IDE Arduino.

Клапауций 322 пишет:

и, зачем прерывание, если и без прерывания всё должно корректно приниматься - если не принялось, то отправитель должен подождать.

Да самому мне не нравится идея с прерыванием, но у меня для каждого из  режимов работы устройства своя подпрограмма. Мне в нескольких местах  вставлять проверку буфера UART  - как-то тоже не очень красиво.

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

alfik777 пишет:

Ну такая же ситуация когда отправляю с терминала IDE Arduino.

сделай скетч, где у тебя отправляется строка из терминала ИДЕ в контроллер и отправляется обратно в терминал - смотри, где у тебя что теряется.

я тебе подсказал, что может теряться, когда забивается буфер в ноль.

Gres
Gres аватар
Offline
Зарегистрирован: 26.03.2013

Прерывания.

 Замечание по использованию

Внутри функции обработки прерывания не работает delay(), значения возвращаемые millis() не изменяются.
Возможна потеря данный передаваемых по последовательному соединению (Serial data) в момент выполнения функциии обработки прерывания.
Переменные, изменяемые в функции, должным быть объявлены как volatile.

А еще есть разница между аппаратным и программным сериалом, прерывания там по разному работают. Это уже было тут гдето на форуме. там даже для аппаратного сериала файлики в среде правили вроде. И еще, у сериала свое прерывание есть ведь которое срабатывает при появлении данных в буфере.

Чего то я ваял с прерываниями и уартом, пока на софтварном уарте отлаживал, все работало нормально, как только после отладки перешел на аппатантый, начались глюки с приемом/передачей и прерываниями. Чего делал не помню, но запустит все удалось в итоге.

alfik777
alfik777 аватар
Offline
Зарегистрирован: 29.06.2015

Спасибо за ответы. Тут разговор только об аппаратном сериале. То, что  у сериала свое прерывание есть  -да, видел, №18, думается это самый правильный вариант был бы.. файлики в среде для этого правили - тоже смотрел, но там вроде бы только для старых версий IDE ? Т.е. штатно доступно только 2 внешних прерывания получается:-(

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

alfik777 пишет:

Спасибо за ответы. Тут разговор только об аппаратном сериале. То, что  у сериала свое прерывание есть  -да, видел, №18, думается это самый правильный вариант был бы.. файлики в среде для этого правили - тоже смотрел, но там вроде бы только для старых версий IDE ? Т.е. штатно доступно только 2 внешних прерывания получается:-(

я не понимаю, почему ты рогом упёрся в прерывания - что у тебя такого срочного должен сериал отправить, что для этого нужно всё бросать?

alfik777
alfik777 аватар
Offline
Зарегистрирован: 29.06.2015

Нет, конца света нет чтоб всё бросать... Повторюсь, в зависимости от команд извне, выполняется та или иная подпрограмма, т.е. в основной цикл loop она может и не вернется, так как по приходу новой команды начнется выполнение другой подпрограммы ( долго или в цикле). Поэтому не хочется во всех местах расставлять чтение буфера UART. Возможно такой вариант не ахти - из одной процедуры кидаться в другую, но это уже другой вопрос.

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

alfik777 пишет:

в зависимости от команд извне, выполняется та или иная подпрограмма, т.е. в основной цикл loop она может и не вернется, так как по приходу новой команды начнется выполнение другой подпрограммы ( долго или в цикле). 

это плохая архитектура программы

*смотри в инетах "конечные автоматы".

temenator
Offline
Зарегистрирован: 26.12.2015

У меня похожий вопрос возник.

Хочу повесить прерывание на таймер с целью опроса D1820, раз в секунду и управления релюшкой.

С разделением запроса и ответа, что бы не вешать основную программу.

В один из входов в прерывание делаем сброс далласа, на через секунду получаем значение.

Возник вопрос как это скажеться на работе библиотеки serial ?

Не будет ли пропускать символы.

Цель отвязать регулятор температуры от работы с GSM либо еще какими модулями через Serial.

Logik
Offline
Зарегистрирован: 05.08.2014

temenator пишет:

Возник вопрос как это скажеться на работе библиотеки serial ?

Не будет ли пропускать символы.

Цель отвязать регулятор температуры от работы с GSM либо еще какими модулями через Serial.

Смотря как реализуете и какая скорость Serial. Я так понимаю Ware хотите програмный из обработчика прерывания таймера. Если обработчик прерывания таймера будет отрабатывать дольше чем время передачи 1 байта Serial то возможны проблемы. Можна организовать разрешение прерывания Serial при нахождении в обработчике прерывания таймера, но это тоже плохо.

Правильный путь подсказывает спецификация Ware. Передача каждого 0 и 1 требует выдерживать интервалы, а вот паузы между ними могут гулять в широком диапазоне. Потому если каждый вызов обработчика прерывания таймера отправит или приймет 1 бити завершится настроив таймер на некоторую паузу то все будет работать. Можно и еще сложней - таймер использовать для формирования длительностей высокого и низкого уровней (и ещё кое чего), т.е. два вызова обработчика таймера для отправки 1 бита.  Это понятно не просто писать, конечный автомат в обработчике не для новичка задача, но если интересно могу отписать подробней.

temenator
Offline
Зарегистрирован: 26.12.2015

Была такая идея переписать обработку 1-wire.

Пока теплиться надежда, что проще скорость сериал снизить, все равно это не критично.

Был бы FIFO в меге. Цены бы ей не было.

А можно Ваши контакты ?

Gres
Gres аватар
Offline
Зарегистрирован: 26.03.2013

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

temenator
Offline
Зарегистрирован: 26.12.2015

А мы хотим, что бы две сравнительно медленные задачи выполнились.