Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Обьясните разницу в прерываниях UART'a
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
kurtis
Вероятно, я недостаточно внимательно читаю документацию, но возникает вопрос в чем разница между Data Register Empty Interrupt и Transmit Compete Interrupt ? Насколько я понял, это 2 прерывания которые возникают при оправке данных, но первое возникает когда данные из регистра данных попадают в сдвиговый регистр для отправки, а второе когда сдвиговый регистр выдал байт в сеть (насколько я понял). Но тогда получается что они выполняют практически одну и туже задачу.
В чем же тогда разница и зачем потребовалось делать именно 2 прерывания, а не одно ?
xelax
Например если управляете направлением передачи (в RS485 например и прочих полудуплексных линиях) чтобы не обрезать последний байт свалившийся в сдвиговый регистр.

Да много разных ситуаций на практике возникает, когда очень полезно иметь два этих прерывания.
kurtis
Ну тогда получается что мне это прерывание нужно только при отправке последнего байта, а до этого оно как-то не к месту....
Ну а по скорости разницы нету? Прерывания по опустошения буфера, по идее, будут быстрее срабатывать чем по опустошению сдвигового регистра....
xelax
Цитата(kurtis @ Dec 25 2008, 17:29) *
Ну тогда получается что мне это прерывание нужно только при отправке последнего байта, а до этого оно как-то не к месту....


Просто привёл как очевидный пример использования. С чем сам сталкивался.

Цитата(kurtis @ Dec 25 2008, 17:29) *
Ну а по скорости разницы нету? Прерывания по опустошения буфера, по идее, будут быстрее срабатывать чем по опустошению сдвигового регистра....


Есть конечно разница... Именно по опустошению буффера и будет быстрей. А ещё приятней использоват встроенный DMA если таковой имеется smile.gif
kurtis
Ну т.е. если используется Data Register Empty Interrupt и все работает, то особого смысла нету лезть и переделывать что-то под Transmit Compete Interrupt ?
xelax
wink.gif В принципе надо что-то использовать не для того чтобы было, а чтобы решить поставленную задачу.

Если удалось оптимально решить поставленную задачу, без данного ресурса, то зачем лепить телеге пятое колесо? smile.gif
kurtis
Понятно, спасибо за объяснения!=)
Сергей Борщ
Цитата(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.
kurtis
Спасибо, некоторые моменты начинают прояснятся.
_Pasha
Цитата(Сергей Борщ @ Dec 25 2008, 19:45) *
Если вы организуете запись в UDR по прерыванию TXC, то вы никак не сможете пердавать без пауз

И, кстати, это не всегда вредно. smile.gif Если Вам обязательно надо иметь паузу больше, чем 2 стоп-бита, то без TXC это очень сложно реализовать.
ReAl
В не совсем явной форме это уже прозвучало, но хочу подчеркнуть - прерывание 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);
    }
}
Maik-vs
При отправке пакета по сети RS485.
переводим UART в режим передачи, записываем 1-й байт в UDR. Всё! Фоновый процесс идёт дальше, передача делается в прерываниях.

прерывание UDRE: записать следующий байт в UDR, если не конец пакета.
прерывание TXE: вернуть UART в режим приёма.

Пока идёт передача, стоит бит TXEN, фоновая задача может ориентироваться на него.
SysRq
Цитата(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) приводило к тому что приёмники ловили мусор (он, конечно, отфильтровывался, но ненужное прерывание в МК вызывал).
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.