Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Окончание передачи UART
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Ioann
Может, кому-то будет полезно...

Делал RS485 на ATMega128. Нужно было отлавливать момент окончания передачи символа - есть соответствующий бит TXC. Так вот, оказалось, что этот бит устанавливается почему-то ДО окончания передачи последнего символа (одновременно с TXE), хотя по datasheet должен по окончании. Когда по этому биту делал переключение драйвера на приём, последний символ не передавался. Пришлось делать программную задержку в виде пустого цикла.

Интересно, это был глюк только у меня или везде так. И также интересно, как у других ATMeg. Если кто-то сталкивался - поделитесь.
bgc
у меня на 64 меге все ок. По биту освобождения буфера передачи (окончания передачи) (отличается от готовности передатчика к приему следующего байта) я отключаю передатчик 485.
На глюк не похоже. Либо ошибка в программе, либо непонимание описания.
Dog Pawlowa
Цитата(Ioann @ Apr 5 2007, 07:23) *
Может, кому-то будет полезно...
Интересно, это был глюк только у меня или везде так. И также интересно, как у других ATMeg. Если кто-то сталкивался - поделитесь.

Полезно не будет :-)
На 128, 32 - все нормально. Ищите ошибку у себя.
VladimirYU
Пример передачи символа из DS не привязан к конкретной реализации интерфейса, сам налетел на эти грабли с RS485. Смотри предыдущие сообщения ( биты окончания передачи и освобождения буфера) и все будет нормально.
Палыч
TXE - это что за бит? Наверное, нужно читать - UDRE?
Проблема с определением окончания передачи у меня возникала только на больших скоростях (2 Mбод). При прерываниях по UDRE за время запихивания очередного (последного в последовательности на передачу) байта иногда оказывался переданным байт из сдвигового регистра - и бит TXC оказывался установленным. Сброс ТXC после записи в UDR исправляет ситуацию.
tag
Цитата(Ioann @ Apr 5 2007, 07:23) *
Может, кому-то будет полезно...

Делал RS485 на ATMega128. Нужно было отлавливать момент окончания передачи символа - есть соответствующий бит TXC. Так вот, оказалось, что этот бит устанавливается почему-то ДО окончания передачи последнего символа (одновременно с TXE), хотя по datasheet должен по окончании. Когда по этому биту делал переключение драйвера на приём, последний символ не передавался. Пришлось делать программную задержку в виде пустого цикла.

Интересно, это был глюк только у меня или везде так. И также интересно, как у других ATMeg. Если кто-то сталкивался - поделитесь.



...работаю с 128 и таких проблем не было, поищете ошибку у себя
Ioann
1. прошу прощения, UDRE, а не TXC...

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


// ждать окончания передачи...
while((UCSR0A & (1<<TXC0)) == 0); - вот это и не даёт нужного эффекта






// очистить регистр признака приёма символов
while (UCSR0A & (1<<RXC0)) symbol = UDR0;

// временная задержка - подобрано - это взамен ожидания окончания передачи.
for(i=0;i<3500;i++);

// разрешить прерывания по приёму символов
UCSR0B = UCSR0B | (1<<RXCIE0);

// запретить передачу в драйвере RS-485
PORTE = PORTE & ~(1<<TxEN); - TxEN - это ножка порта E, что управляяет
драйвером 485
Палыч
Выдержка из исходника - обработчик прерывания по UDRE? Обработчика прерывания по TXC - нет? TXC сбрасывается аппаратно по обработке прерывания по TXC. Если обработчика этого прерывания нет, то бит TXC нужно сбрасывать программно.
Dog Pawlowa
Цитата(Ioann @ Apr 5 2007, 09:03) *
1. прошу прощения, UDRE, а не TXC...
2. если подскажете, буду благодарен если укажете на ошибку (сам что-то не нашёл...)


Использование прерывания несколько удобнее и понятнее (по крайней мере для меня)
Код
#pragma vector=USART0_TXC_vect
__interrupt void USART0_transmit_complete(void)
{
  usart0_status_timer = 2;
  usart0_status = Usart0WaitReceiving;
}


фрагмент процесса обслуживания порта:

switch (usart0_status)
.....
  case Usart0Transmitting:    
    if (!usart0_status_timer)
    {
      usart0_status = Usart0Unconfigured;
    }
    break;

  case Usart0WaitReceiving:
    if (usart0_status_timer == 0)
    {
      ClearRxBuffer0();
      SetReceiveDirection0();
      usart0_status = Usart0Waiting;
    }
    break;
  }
mse
Цитата(Ioann @ Apr 5 2007, 10:03) *
1. прошу прощения, UDRE, а не TXC...

2. если подскажете, буду благодарен если укажете на ошибку (сам что-то не нашёл...)

Ошыбку искать впадлу, скажу в обчем:
УДРЕ устанавливается, когда регистр УДР на запись освобождается. При переносе из УДР в сдвиговый регистр УАРТа, например.
ТХС устанавливается, когда из сдвигового регистра ушол хвост стоп-бита.

485 драйверить надо так:
Засылаем строку в УАРТ. По УДРЕ набиваем УДР до блевоты. И контролируем загрузку последнего символа. ТХС игнорируем, т.е. запрещщяем. Загрузили последний символъ. Прерывания по УДРЕ запрещаем, сбрасываем ТХС, разрешаем прерывания по ТХС. Имеем в виду, что сейчас у нас один символ в сдвиговом регистре, второй - в УДР. Значить на втором ТХС калитку закрываем на приём.
Палыч
Цитата(mse @ Apr 5 2007, 09:38) *
Имеем в виду, что сейчас у нас один символ в сдвиговом регистре, второй - в УДР. Значить на втором ТХС калитку закрываем на приём.

Цитата из DS на m128: USART Control and Status Register A Bit 6 – TXCn: USART Transmit Complete

This flag bit is set when the entire frame in the Transmit Shift Register has been shifted
out and there are no new data currently present in the transmit buffer (UDRn).
XsanyaX
Цитата(mse @ Apr 5 2007, 09:38) *
Ошыбку искать впадлу, скажу в обчем:
Имеем в виду, что сейчас у нас один символ в сдвиговом регистре, второй - в УДР. Значить на втором ТХС калитку закрываем на приём.


Палыч правильно сказал - прерывания по TXC не будет пока в UDR будут данные....
т.е прерывание по TXC будет только одно - по выдаче на TX стопового бита последнего передаваемого байта..
Kuzmi4
2 bgc - в принципе если вам будет интересно , то я тут где то выкладывал проэктик как раз такого плана, поищите по форуму - то что он рабочий - проверял не я один и не один день, и всё работало как надо.
Если не найдёте, могу выслать - мне не жалко..
да , проверял на меге 8-й и 168-й, и 16-й..
mse
Цитата(XsanyaX @ Apr 5 2007, 11:02) *
Палыч правильно сказал - прерывания по TXC не будет пока в UDR будут данные....
т.е прерывание по TXC будет только одно - по выдаче на TX стопового бита последнего передаваемого байта..

Да, имана так. Тормознул. В программках имана так и закладывал.
SasaVitebsk
Делал на м640 и на 8515. Использовал все признаки и прерывания. Использовал все сигналы интерфейса. Также ни одной ошибки или неточности не находил!
Ioann
Понял, что надо мне проверить, сбрасываю ли TXC при последнем символе.
Спасибо всем откликнувшимся.
defunct
Цитата
Делал RS485 на ATMega128. Нужно было отлавливать момент окончания передачи символа - есть соответствующий бит TXC. Так вот, оказалось, что этот бит устанавливается почему-то ДО окончания передачи последнего символа (одновременно с TXE), хотя по datasheet должен по окончании. Когда по этому биту делал переключение драйвера на приём, последний символ не передавался. Пришлось делать программную задержку в виде пустого цикла.

У вас ошибка в программе.

Взведите прерывание по TX. В обработчике прерывания переключайте 485-й на прием.
Уже ж писал где-то об этом.


Пример одного из самых простых способов:

Пусть PD2 - пин выбора направления 485
PD2 = 1 - передача
PD2 = 0 - прием.

Тогда

Код
putchar(char ch)
{
    while (PORTD & (1 << PD2));  // ждем пока 485-й в режиме передачи
    PORTD |= (1 << PD2); // взвести передачу
    UDR = ch;  // засунуть отправляемый символ в UDR
}

void UartTxISR(void)
{
       // в обработчике Tx переключить 485-й обратно на прием.
       PORTD &= ~(1  << PD2);
}
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.