Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: UART ATmega128 портится последний байт посылки
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Д_М
Здравствуйте!
При использовании хорошо отлаженного кода MODBUS, но несколько адаптированного для особых условий, контроллер входит в устойчивое состояние, кода на любой запрос он даёт вменяемый ответ, но последний байт всегда 0xFF. В моём случае с MODBUS - это CRC. Предпоследний байт соответствует правильному CRC. Не зависит от длины ответа - хоть длинный, хоть короткий. Проблема залечивается путём передёргивания питания. Передача производится массивом. Каждый новый байт передаётся из обработчика прерывания. После отправки последнего байта запрещается прерывание UDRIE и разрешается прерывание TXCIE.

CODE
#pragma vector=USART1_UDRE_vect
__interrupt void UDRE1_handler (void)
{
char data;

if (size_SIO1)// not complete
{
size_SIO1--;
data = *ptr_SIO1++;
UDR1 = data;
#ifdef SIO1_poly
UDRIE_1 = 0;
GI_enable
CRC(data, &CRC1, SIO1_poly);
UDRIE_1 = 1;
#endif
}
else /* Array sent */
{
#ifdef SIO1_poly
if (!CRC1Lo_sent)
{
UDR1 = (char)(CRC1);
CRC1Lo_sent = 1;
return;
}

if (!CRC1Hi_sent)
{
UDR1 = (char)(CRC1>>8);
CRC1Hi_sent = 1;
LED = 0;
return;
}
#endif
UDRIE_1 = 0;
TXCIE_1 = 1;
}
}

#pragma vector=USART1_TXC_vect
__interrupt void TXC1_handler (void)
{
TXCIE_1 = 0;
if (handler_SIO1)
{
GI_enable
(*handler_SIO1)(); // Activate handler execution
}
}

Одно важнейшее отличие от такого же кода, который никогда не выдавал таких проблем - добавлена функция широковещания. То есть слэйв выступает мастером, когда есть на то условия. Дважды передаёт одну и ту же посылку. При этом, приём у него отключен. Не выявил закономерностей, которые приводят контроллер в такое устойчивое состояние. Даже не занаю за что зацепиться. Как мне кажется. Что-то меняется в формате передачи данных. То есть не было передачи 0xFF, а был только один старт бит и всё, далее пассивная линия, которая и воспринемается приёмником, как 0xFF и стоп-бит. Но что могло бы привести к этому - даже нет зацепок. Благодарен за любые мысли, даже самые невероятные.
Спасибо!
kovigor
Цитата(Д_М @ Nov 4 2014, 14:48) *
То есть не было передачи 0xFF, а был только один старт бит и всё, далее пассивная линия, которая и воспринемается приёмником, как 0xFF и стоп-бит. Но что могло бы привести к этому - даже нет зацепок.Спасибо!

1. А почему вы решили, что передачи 0xFF не было ? На экране осциллографа этого не увидишь. Был старт-бит ? Был. А потом надолго - лог.1. Это может быть как 0xFF, так и банальное зависание или перезагрузка (сброс) МК.
2. Кстати, о зависаниях и перезагрузках. Вы уверены, что у вас, например, ничего не зависает, стек не переполняется, одни данные не наезжают на другие, и проч. Я - не уверен. Возможно, дело вообще не в UART. Попробуйте "отрезать" от вашего кода все второстепенное, оставить только необходимую, тестовую часть и проверить, что будет.
Сергей Борщ
Такая версия: вы разрешаете TCIE, а флаг TXC у вас уже стоит, после предыдущей посылки, например. В результате - пока вы выходите из этого прерывания и входите в прерывание TXC, у вас успевает передаться стартовый бит. Затем вы в прерывании TXC выключаете передатчики и приемная сторона вместо остатка байта принимает из линии паузу - единицы. Я бы на вашем месте перед разрешением TCIE принудительно сбросил TXC записью 1 в этот флаг.
Д_М
Цитата(kovigor @ Nov 4 2014, 16:15) *
1. А почему вы решили, что передачи 0xFF не было ? На экране осциллографа этого не увидишь. Был старт-бит ? Был. А потом надолго - лог.1. Это может быть как 0xFF, так и банальное зависание или перезагрузка (сброс) МК.
2. Кстати, о зависаниях и перезагрузках. Вы уверены, что у вас, например, ничего не зависает, стек не переполняется, одни данные не наезжают на другие, и проч. Я - не уверен. Возможно, дело вообще не в UART. Попробуйте "отрезать" от вашего кода все второстепенное, оставить только необходимую, тестовую часть и проверить, что будет.


Спасибо большое за отклик! Передачи 0xFF не было точно. Этот глюк выявляется тогда, когда на ведущем устройстве не обновляется информация от ведомых. Ведущее устройтво отбраковывает ответы с некорректным CRC. Специально проверил CRC. Действительно не 0xFF. Скорее всего, имеет место наезжание данных. Но ума не могу предположить - что можно такое затереть, чтобы портился именно последний байт. Это происходит очень редко. Прибор работает в составе очень хитро мудрой системы. Затыки происходят тогда, когда происходят технологические события. Что-то выкинуть не представляется возможным, так как тогда не будет работать, и как следствие, затыкаться. Передёргивание питания восстанавливает функциональность. Один плюс - дурное состояние устойчивое, значит нет частого перезагруза контроллера, что ещё хуже.
kovigor
Цитата(Д_М @ Nov 4 2014, 19:52) *
Затыки происходят тогда, когда происходят технологические события.

Технологическое событие -> Прерывание -> Вызов обработчика прерывания -> Разрушение стека или "наезд" стека на данные (при вызове обработчика как минимум контекст помещается в стек). Попробуйте увеличить размер стека.
И еще - проверьте программу на наличие таких классических ошибок, как не соответствующие требованиям задачи типы данных (например, ы с помощью указателей пытаетесь записать 16-разрядную переменную в ячейку, выделенную для 8-разрядной). И на ошибки при работе с памятью проверьте. Например, вы выделили память, а потом освободили ее, затем забыли об этом и снова пишете что-то по тому же адресу, а там уже не ваши данные, а что-то другое ...
Д_М
Цитата(Сергей Борщ @ Nov 4 2014, 16:27) *
Такая версия: вы разрешаете TCIE, а флаг TXC у вас уже стоит, после предыдущей посылки, например. В результате - пока вы выходите из этого прерывания и входите в прерывание TXC, у вас успевает передаться стартовый бит. Затем вы в прерывании TXC выключаете передатчики и приемная сторона вместо остатка байта принимает из линии паузу - единицы. Я бы на вашем месте перед разрешением TCIE принудительно сбросил TXC записью 1 в этот флаг.


Спасибо!
Интересная мысль. Тогда возникает ещё более интересный вопрос - что можно было сделать с контроллером, что он перестал сбрасывать TXC автоматически?

Сергей Борщ
Цитата(Д_М @ Nov 4 2014, 19:45) *
Тогда возникает ещё более интересный вопрос - что можно было сделать с контроллером, что он перестал сбрасывать TXC автоматически?
Ничего. В документации четко написано: TXC сбрасывается при входе в обработчик или вручную, записью единицы. Вам наоборот надо его сбросить перед разрешением прерывания. Причем желательно сбрасывать перед записью последнего байта в UDR, чтобы в случае чего не потерять его. Он у вас не сброшен, он у вас выставлен когда не нужно.
kolobok0
Цитата(Д_М @ Nov 4 2014, 14:48) *
..но последний байт всегда 0xFF. В моём случае с MODBUS - это CRC....


Обратите внимание на протокол MODBUS. Особенно временнЫе задержки до и после передачи. Именно их обязательно надо выдерживать.
Т.е. неправильная реализация выключают передачу после задвигания в регистр передатчика
(что явный косяк, и по внешним признакам похож на Ваш случай), немного получше - когда передача выключается после ухода байта из переатчика
USART. И правильная реализация - когда после ухода байта выдерживается необходимая пауза согласно скорости передачи.
Именно такое поведение увеличивает помехоустойчивость протокола - т.е. линии практически не болтаются в воздухе.
Lagman
Цитата(kolobok0 @ Nov 10 2014, 05:11) *
Обратите внимание на протокол MODBUS. Особенно временнЫе задержки до и после передачи. Именно их обязательно надо выдерживать.
Т.е. неправильная реализация выключают передачу после задвигания в регистр передатчика
(что явный косяк, и по внешним признакам похож на Ваш случай), немного получше - когда передача выключается после ухода байта из переатчика
USART. И правильная реализация - когда после ухода байта выдерживается необходимая пауза согласно скорости передачи.
Именно такое поведение увеличивает помехоустойчивость протокола - т.е. линии практически не болтаются в воздухе.

Интересно, а в каких процессорах нет флага что "последний байт ушел", и не в регистр, а уже в линию?
P.S. Сейчас работают с RX210 от ренесас, там есть такой бит.
kolobok0
Цитата(Lagman @ Nov 10 2014, 12:24) *
...а в каких процессорах нет флага что "последний байт ушел", и не в регистр, а уже в линию?...


вас этот флаг всё равно не спасёт при реализации MODBUSа sm.gif
Д_М
Здравствуйте!
Кажется, я нашёл причину. Выше я писал, что имеется механизм подачи широковещательных команд, когда происходит некоторое технологическое событие. Было замечено, что если такое событие происходит, когда контроллер отвечает на запрос, передача ответа прерывается и начинается передача широковещательного сообщение. Разумеется, передача ответа могла прерваться в любой момент. Пробовал смоделировать ситуацию. Эффект с 0xFF целенаправленно получить не удалось. Сделал программную блокировку, препятствующую прерыванию ответа. С тех пор эффект 0xFF не наблюдался. Прошло уже несколько недель. Надеюсь, что победил. Однако, для меня так и остаётся загадкой - действительно ли наслоение одного процесса передачи на другой могло вызвать такой эффект? Если да, то какова его природа?
Всем ещё раз большое спасибо!
kovigor
Цитата(Д_М @ Nov 30 2014, 12:06) *
Надеюсь, что победил. Однако, для меня так и остаётся загадкой ...

Слово "надеюсь" вполне точно отражает суть вещей. Я бы продолжил эксперименты и попытался "добить" эту проблему до конца, иначе не может быть уверенности в работоспособности проекта ...
kolobok0
Цитата(Д_М @ Nov 30 2014, 11:06) *
...действительно ли наслоение одного процесса передачи на другой могло вызвать такой эффект? Если да, то какова его природа?..


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

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