реклама на сайте
подробности

 
 
> Обьясните разницу в прерываниях UART'a
kurtis
сообщение Dec 25 2008, 14:06
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 466
Регистрация: 21-06-05
Пользователь №: 6 205



Вероятно, я недостаточно внимательно читаю документацию, но возникает вопрос в чем разница между Data Register Empty Interrupt и Transmit Compete Interrupt ? Насколько я понял, это 2 прерывания которые возникают при оправке данных, но первое возникает когда данные из регистра данных попадают в сдвиговый регистр для отправки, а второе когда сдвиговый регистр выдал байт в сеть (насколько я понял). Но тогда получается что они выполняют практически одну и туже задачу.
В чем же тогда разница и зачем потребовалось делать именно 2 прерывания, а не одно ?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 12)
xelax
сообщение Dec 25 2008, 14:23
Сообщение #2


Местный
***

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



Например если управляете направлением передачи (в RS485 например и прочих полудуплексных линиях) чтобы не обрезать последний байт свалившийся в сдвиговый регистр.

Да много разных ситуаций на практике возникает, когда очень полезно иметь два этих прерывания.
Go to the top of the page
 
+Quote Post
kurtis
сообщение Dec 25 2008, 14:29
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 466
Регистрация: 21-06-05
Пользователь №: 6 205



Ну тогда получается что мне это прерывание нужно только при отправке последнего байта, а до этого оно как-то не к месту....
Ну а по скорости разницы нету? Прерывания по опустошения буфера, по идее, будут быстрее срабатывать чем по опустошению сдвигового регистра....
Go to the top of the page
 
+Quote Post
xelax
сообщение Dec 25 2008, 14:38
Сообщение #4


Местный
***

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



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


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

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


Есть конечно разница... Именно по опустошению буффера и будет быстрей. А ещё приятней использоват встроенный DMA если таковой имеется smile.gif
Go to the top of the page
 
+Quote Post
kurtis
сообщение Dec 25 2008, 14:52
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 466
Регистрация: 21-06-05
Пользователь №: 6 205



Ну т.е. если используется Data Register Empty Interrupt и все работает, то особого смысла нету лезть и переделывать что-то под Transmit Compete Interrupt ?
Go to the top of the page
 
+Quote Post
xelax
сообщение Dec 25 2008, 14:57
Сообщение #6


Местный
***

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



wink.gif В принципе надо что-то использовать не для того чтобы было, а чтобы решить поставленную задачу.

Если удалось оптимально решить поставленную задачу, без данного ресурса, то зачем лепить телеге пятое колесо? smile.gif
Go to the top of the page
 
+Quote Post
kurtis
сообщение Dec 25 2008, 15:07
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 466
Регистрация: 21-06-05
Пользователь №: 6 205



Понятно, спасибо за объяснения!=)
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 25 2008, 15:45
Сообщение #8


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
kurtis
сообщение Dec 25 2008, 17:29
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 466
Регистрация: 21-06-05
Пользователь №: 6 205



Спасибо, некоторые моменты начинают прояснятся.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Dec 25 2008, 20:20
Сообщение #10


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Сергей Борщ @ Dec 25 2008, 19:45) *
Если вы организуете запись в UDR по прерыванию TXC, то вы никак не сможете пердавать без пауз

И, кстати, это не всегда вредно. smile.gif Если Вам обязательно надо иметь паузу больше, чем 2 стоп-бита, то без TXC это очень сложно реализовать.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Dec 25 2008, 21:28
Сообщение #11


Нечётный пользователь.
******

Группа: Свой
Сообщений: 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);
    }
}


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Maik-vs
сообщение Dec 26 2008, 14:07
Сообщение #12


Местный
***

Группа: Участник
Сообщений: 246
Регистрация: 4-12-06
Пользователь №: 23 101



При отправке пакета по сети RS485.
переводим UART в режим передачи, записываем 1-й байт в UDR. Всё! Фоновый процесс идёт дальше, передача делается в прерываниях.

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

Пока идёт передача, стоит бит TXEN, фоновая задача может ориентироваться на него.
Go to the top of the page
 
+Quote Post
SysRq
сообщение Dec 26 2008, 21:24
Сообщение #13


Чайник, 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) приводило к тому что приёмники ловили мусор (он, конечно, отфильтровывался, но ненужное прерывание в МК вызывал).
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 15:15
Рейтинг@Mail.ru


Страница сгенерированна за 0.02297 секунд с 7
ELECTRONIX ©2004-2016