|
Обьясните разницу в прерываниях UART'a |
|
|
|
 |
Ответов
(1 - 12)
|
Dec 25 2008, 14:38
|

Местный
  
Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035

|
Цитата(kurtis @ Dec 25 2008, 17:29)  Ну тогда получается что мне это прерывание нужно только при отправке последнего байта, а до этого оно как-то не к месту.... Просто привёл как очевидный пример использования. С чем сам сталкивался. Цитата(kurtis @ Dec 25 2008, 17:29)  Ну а по скорости разницы нету? Прерывания по опустошения буфера, по идее, будут быстрее срабатывать чем по опустошению сдвигового регистра.... Есть конечно разница... Именно по опустошению буффера и будет быстрей. А ещё приятней использоват встроенный DMA если таковой имеется
|
|
|
|
|
Dec 25 2008, 15:45
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(kurtis @ Dec 25 2008, 16:52)  Ну т.е. если используется Data Register Empty Interrupt и все работает, то особого смысла нету лезть и переделывать что-то под Transmit Compete Interrupt ? UART имеет двойную буферизацию. Вы кладете байт в UDR, он "проваливается" в сдвигатель (UDR при этом оказывается свободным), и начинает передаваться из сдвигателя. В момент "проваливания" генерится прерывание UDRE, т.е. вы можете писать в UDR следующий байт и он будет ждать в UDR пока освободится сдвигатель. Сдвигатель освободился (заметьте, выданы только биты данных, биты четности и стоп-биты еще не переданы) - в него тут же будет записан новый байт из UDR (при этом UDR освободился и сгенерировано очередное прерывание UDRE), и после передачи стопового бита UART сможет сразу же, без пауз, начинать передачу очередного байта. Т.е. при передачи без пауз у вас есть запас по времени на запись очередного байта в UDR, равный времени передачи 8 бит+бита четности+стоп-битов. Прерывание TXC возникает, когда выдвинут весь ваш байт из сдвигаетеля, после него выданы на выход бит четности (если включен) и стоп-биты, и к этому моменту в UDR нового байта нет. Если вы организуете запись в UDR по прерыванию TXC, то вы никак не сможете пердавать без пауз - после выдачи стоп-бита будет пауза пока вы отреагируете на прерывание и положите очередной байт в UDR.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 25 2008, 21:28
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
В не совсем явной форме это уже прозвучало, но хочу подчеркнуть - прерывание TXC действительно возникнет только при отправке последнего байта. Флага прерывания TXC имеет шанс взвестить - на высокой скорости, при нагруженном другими, более приоритетными прерываниями процессоре - UDRE может "опоздать" и взведётся ещё и TXC. Но у UDRE выше приоритет и поэтому сначала вызовется его обработчик. И вот в нём можно проверить - есть ли ещё байты для передачи и если есть - то сбросить флаг TXC, а если нет - самозапретиться и не трогать флаг TXC, пусть вызовется его обработчик. Смысл такого действа - под операционной системой сделать (более частое) прерывание UDRE более "лёгким", не обращащимся к сервисам ОС (и, как следствие, имеющим шансы не вызывать не-inline функции и сохранять/восстанавливать только реально необходимые для работы регистры), а обращение к ОС поместить в прерывание TXC. Приблизительно так: Код template<uart_channel_t channel> void uart_t<channel>::tx_isr() { OS::TISRW isrw; tx_event.SignalISR(); }
template<uart_channel_t channel> void uart_t<channel>::udre_isr() { if( tx_available() ) { uint8_t temp = tx_get_byte(); if( channel == uart_ch0) { UDR0 = temp; UCSR0A |= (1 << TXC); } else { UDR1 = temp; UCSR1A |= (1 << TXC); } } else { if( channel == uart_ch0) UCSR0B &= ~(1 << UDRIE); else UCSR1B &= ~(1 << UDRIE); } }
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Dec 26 2008, 21:24
|

Чайник, 1 литр
   
Группа: Свой
Сообщений: 655
Регистрация: 17-05-06
Из: Moscow
Пользователь №: 17 168

|
Цитата(ReAl @ Dec 26 2008, 00:28)  Флаг прерывания TXC имеет шанс взвестить - на высокой скорости, при нагруженном другими, более приоритетными прерываниями процессоре - UDRE может "опоздать" и взведётся ещё и TXC. Хочется добавить, что это весьма ценное замечание. Его следует учесть тут: Цитата(Maik-vs @ Dec 26 2008, 17:07)  При отправке пакета по сети RS485... //... прерывание UDRE: записать следующий байт в UDR, если не конец пакета. прерывание TXE: вернуть UART в режим приёма. Наступил на эти грабли при работе с каналом RS485, где линии НЕ подтянуты к уровню 2.5В, и в режиме молчания по линии гуляет мусор. Ошибочное переключение передача-приём-передача в такой ситуации при передаче пакета (протокол типа недо-MODBUS ASCII) приводило к тому что приёмники ловили мусор (он, конечно, отфильтровывался, но ненужное прерывание в МК вызывал).
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|