|
|
  |
Гарантия того, что по USART все данные ушли |
|
|
|
Jan 15 2010, 09:23
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
А кто как борется с коллизиями? RXE всегда включен - это ясно. При отправке байта пишем его в переменную типа: Код volatile uint8_t RS485_last_sent; //............................................... UDR = RS485_last_sent = *rx_ptr++; Прерывание от RX не выключается никогда. Но можно нарваться на момент, когда прерывание RX не успело подхватить RS485_last_sent и сравнить его. Поскольку UDR буферизирован, прочтем старое принятое значение - и кирдык. Ложная реакция обеспечена.
|
|
|
|
|
Jan 15 2010, 10:59
|

Профессионал
    
Группа: Свой
Сообщений: 1 818
Регистрация: 15-10-09
Из: Владивосток
Пользователь №: 52 955

|
Цитата(_Pasha @ Jan 15 2010, 19:23)  А кто как борется с коллизиями? Если имеется в виду исключение одновременного выхода на линию нескольких мастеров, то 1. Все слушают всех и не выходят в передачу, когда линия занята 2. После освобождения линии у каждого девайса СВОЙ таймаут выхода в передачу (с повторной проверкой свободности линии) 3. Для большей надежности можно завести прерывание по старт-биту (на переход в 0 сигнала на линии), по нему - таймаут на передачу байта-полутора, и если в заданный промежуток перепадов больше не пришло - линия свободна. UART контроллер при этом не задействован, и проблемы с буферированием исчезают
|
|
|
|
|
Jan 15 2010, 11:54
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(Палыч @ Jan 15 2010, 10:12)  Да и "тяжелость" определяется ещё и скоростью передачи, особенно на очень высоких скоростях (тут уж - как не облегчай прерывания, а при некотором числе высокоприоритетных прерываний они всё равно превращаются в "тяжелое"). Да все так, только давайте посмотрим что может бегать по 485-му: В Modbus RTU например, который бегает по 485-му, недопустимы какие-то непрогнозируемые паузы между символами. Пауза больше чем 1.5 символа по стандарту является поводом для отбраковки всего пакета! Чтобы получить несвоевременный TXC, обработка UDRE должна опоздать аж на 2 символа! Т.е. межсимвольная пауза в системе где может случайно вылезти TXC посреди пакета - может достигать 2х символов. Как следствие этого - работа в Modbus RTU протоколе становится невозможной впринципе в такой системе. Что делать? Отказаться от RTU? - нельзя, причины сами знаете. Поэтому обработчики более выскоприоритетных прерываний строятся так, чтобы была гарантия отработки более низкоприоритетных во-время. Если не получается это сделать на одном AVR, тогда ставится еще один чип в помощь, либо берется другой МК, т.к. заранее известно, что система без этого захлебнется. PS: С очень высокими скоростями по UART'у на AVRках не работаю - 115200 макс. AVRки у меня всегда не ниже 11.059 тактируются, в основном 14.7456.
|
|
|
|
|
Jan 18 2010, 07:31
|
Участник

Группа: Участник
Сообщений: 19
Регистрация: 14-12-07
Из: Беларусь, Гомель
Пользователь №: 33 305

|
Цитата(HALFer @ Jan 15 2010, 00:35)  admiral, если "правильность" софта не пугает и это будет временной мерой, то достаточно будет перед засыпанием установить задержку в виде N*2 холостых циклов. где N - это к-во тактов необходимые для отправки одного байта по USART. а умножаем на 2, т к у USART'а двойная буферизация.
глупее не бывает, но вроде как временная мера сойдет Я так и сделал - установил задержку 2мс перед засыпанием и стало все нормально. Просто мучал меня этот вопрос т.к. нерационально получается - вдруг когда-то придется использовать USART не только для отладки. Да и думал может в документации ошибка закралась, т.к. не пойму почему не сделали сброс флага TXC при занесении данных в UDR.
|
|
|
|
|
Jan 20 2010, 12:35
|
Местный
  
Группа: Участник
Сообщений: 246
Регистрация: 4-12-06
Пользователь №: 23 101

|
Цитата(admiral @ Jan 18 2010, 10:31)  Я так и сделал - установил задержку 2мс перед засыпанием и стало все нормально. Просто мучал меня этот вопрос т.к. нерационально получается - вдруг когда-то придется использовать USART не только для отладки. Да и думал может в документации ошибка закралась, т.к. не пойму почему не сделали сброс флага TXC при занесении данных в UDR. Сбрасывать флаг прерывания должно только прерывание, иначе разрушится мир  Затраты на сброс флага невелики - если прерывание разрешено, это время на 2 загрузки адреса + 1 такт на reti. Если же флаг сбрасывать при загрузке UDR, то вы не сможете отследить те самые разрывы между байтами, которые могут быть критичны. Вам нужно вместо задержки 2 мс поставить ожидание флага TXC, его сброс (записью в TXC единицы!) и можно засыпать. Прерывание TXC должно быть запрещено (бит TXCIE =0), чтобы флаг TXC стоял не сбрасывался.
|
|
|
|
|
Jan 20 2010, 22:47
|
Местный
  
Группа: Свой
Сообщений: 256
Регистрация: 6-03-06
Из: Украина, г. Винница
Пользователь №: 15 017

|
Цитата Если же флаг сбрасывать при загрузке UDR, то вы не сможете отследить те самые разрывы между байтами, которые могут быть критичны. А что мешает отслежить состояние флага перед записью в UDR?
|
|
|
|
|
Jan 21 2010, 11:10
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(defunct @ Jan 15 2010, 14:54)  В Modbus RTU например, который бегает по 485-му, недопустимы какие-то непрогнозируемые паузы между символами. Пауза больше чем 1.5 символа по стандарту является поводом для отбраковки всего пакета! Вы забыли упомянуть ещё о такой особенности таймаутов Modbus RTU: Код #define MB_MIN_15T_TIMEOUT MB_SEC_TO_TCNT_TIC( 0.000750f ) // 750 us if bps>19200 #define MB_MIN_35T_TIMEOUT MB_SEC_TO_TCNT_TIC( 0.001750f ) // 1.750 ms if bps>19200 Я её использую. Раз уж пошёл разговор про Modbus RTU, то хочу спросить кто как обеспечивает гарантию паузы 3,5T меду пакетами? Я всегда отправляю преамбулу из 4 dummy байтов с отключенным передатчиком драйвера RS485. Какие у Вас соображения на сей счёт? Может это лишняя паранойя, ведь я и так отлавливаю конец посылки по паузе?
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Jan 21 2010, 17:28
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(demiurg_spb @ Jan 21 2010, 13:10)  Я всегда отправляю преамбулу из 4 dummy байтов с отключенным передатчиком драйвера RS485. Такой подход имеет смысл применять тогда, когда мастер отправляет несколько broadcast сообщений (address 0x00 / 0xFF) подряд, не дожидаясь ни от кого ответа. Настройка системы, синхронизация времени, старт синхро-измерения и т.п. Во всех остальных случаях - достаточно факта определения конца посылки по паузе в 3,5Т, и мастеру и слейвам. Но на мой взгляд отправка 4х dummy байтов с отключенным передатчиком ломает всю "тупизну и прямолинейность"  драйвера UART'a. Если без этого действует простейший алгоритм: - включить передатчик - отправить символ - выключить передатчик если TXC. то в случае с преамбулой будут варианты.
|
|
|
|
|
Jan 22 2010, 20:18
|
Местный
  
Группа: Свой
Сообщений: 256
Регистрация: 6-03-06
Из: Украина, г. Винница
Пользователь №: 15 017

|
Что ж тут непонятного. Время на передачу байта фиксированное. Оно и используется в качестве таймера. А байт дальше драйвера 485 не уйдет. На быcтрую руку примерно так: По RxC: UDR = dummy; TimeOut = 0; По TxC: if (++TimeOut <= N) {UDR = dummy;} else {DoOnTimeOut} N, по моему, должен быть равен 4. таким образом обнаруживается пауза > (4T...5T) (т.е. не факт, что пауза 4,5Т будет обнаружена) P.S. Можно в качестве dummy-байта взять 0x0F. ТОгда получим фронт в середине байта на 0,5Т. И выход Tx завести на прерывание (по фронту). ТОгда можно будет обнаруживать паузы > (3,5Т...4,5Т). Но надо ли?
|
|
|
|
|
Jan 29 2010, 18:26
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(_Pasha @ Jan 23 2010, 08:02)  Проще надо быть с модбасом  Товарищи! Возник у меня ещё один вопрос про modbus. Хотелось бы узнать какие-нибудь элегантные способы решения проблемы поддержания функционирования стандартных функций чтения-записи регистров и коилов в контексте 8-ми битного little-endian MCU. Я решаю сейчас данную закавыку через remap-таблицу во FLASH. Она зараза большая становится, когда много данных нужно ремапить, да и нудно её редактировать (хоть всё уже и так через макросы зафигачено). Я уже и так и сяк, но ничего другого выдумать не могу. Прошу ALL не стеснятся и высказывать любые здравые предложения! Спасибо!
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|