Перейти к содержанию
    

Непонятное поведение RS485-UART1

MAX487 подключен к UART1-LPC2138, скорость 38400, VPB_CLOCK= 14745600. Передатчик передает 16 байт (пакет) 5501160800000000000000000000E0AA(HEX) на приемник LPC2138 приходит 55408B0800000000000000000000E0AA00, последний байт (00) левый, в лучшем случае из 20 отправленный пакетов приходит 6 правильных. В сети несколько различных устройств на AVR, везде установлена MAX487, они обмениваются с передатчиком нормально.

 

Инициализация UART1:

//UART1 - 38400 - RS485
PINSEL0 |= 0x00050000;                                 //Enable RxD and TxD pins
U1LCR = 0x83;                                         //8 bits, no Parity, 1 Stop bit
U1DLL = (VPB_CLOCK/16/BAUD_RATE1) & 0xFF;              //Setup Baudrate
U1DLM = ((VPB_CLOCK/16/BAUD_RATE1) >> 8) & 0xFF;
U1LCR = 0x03;                                         //DLAB = 0
U1FCR = 0x07;                                       // Разрешение работы и сброс TX and RX FIFO, граница - 1 байт

//настройка прерывания UART1
VICVectAddr7 = (unsigned long)uart1_interrupt;      //прерывание на 7 векторе
VICVectCntl7 = 0x20 | 0x07;
VICIntEnable |= 0x00000080;                //включить прерывание от UART1
U1IER = IER_RBR | IER_THRE;                            

Обработка прерываний:

    IIRValue = U1IIR;
    IIRValue = (IIRValue & 0x0E) >> 1;    // Выделяем информацию об источнике прерывания

    if ( IIRValue == 0x03 ) {
        //Изменился статус приемной линии
        //сбросим времени счетчик последнего обмена
        LSRValue = U1LSR;
        if ( LSRValue & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI) ) {
            //Пустое чтения для сброса флага прерывания
            Dummy = U1RBR;    
            VICVectAddr = 0;
            return;
          }   
        if ( LSRValue & LSR_RDR ) {
            // В FIFO остаются не прочитанные данные
            RBRValue = U1RBR;
            RecvByte( RBRValue );
            if ( DebugMode == 2 )
                PutStr( PrintNumb( HEX, 2, FALSE, '0', RBRValue ) );
            if ( RBRValue == 0xaa )
                PutStr( CrLf );
          }
      }
    if ( IIRValue == IIR_RDA ) {
        //Принят новый байт данных и достигнута граница тригера 
        //количества принятых байт в FIFO
        //сбросим времени счетчик последнего обмена
        //данные приняты
        FlgRecv = 1;
        RBRValue = U1RBR;
        RecvByte( RBRValue );
        if ( DebugMode == 2 )
            PutStr( PrintNumb( HEX, 2, FALSE, '0', RBRValue ) );
        if ( RBRValue == 0xaa )
            PutStr( CrLf );
      } 
    if ( IIRValue == IIR_THRE ) {
        //Прочитаем статус и убедимся, что действительно THR пуст
        LSRValue = U1LSR; 
        if ( LSRValue & LSR_THRE ) {
            //буфер передачи пуст
            if ( SendByte( &ch ) )
                U1THR = ch;
             }
      }
    //сброс прерывания
    VICVectAddr = 0;

 

Мозг кипит, смотрел анализатором принимаемые данные, все правильно :( причем кривится только первые байты в пакете, если передать что-то типа 5501160801234567890… данные придут правильно начиная с «01234567890» такое ощущение, что нарушается синхронизация при приеме первых байтов. :help:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Неясно где и как идёт переключение, есть/нужны ли "растяжки" по RS485. Почему бы не попробовать передавать 0x55. И что за дебажные вставки? может, они могут мешать?

Рекомендую взглянуть

http://electronix.ru/forum/index.php?showtopic=42125

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня работа по RS485 на UART1 реализована так:

 

#define RX_DATA    0x04
#define TX_DATA    0x02

//Обработчик прерывания UART1 (RS485)
void Uart1_Int(void)
{
  dwIntSrc=U1IIR;
  dwIntSrc&=0x0F;
  switch (dwIntSrc)
  {
  case RX_DATA: rs485.Rs485Rx(); break;
  case TX_DATA: rs485.Rs485Tx(); break;
  }
}

//Обработчик прерывания от передатчика
void Crs485::Rs485Tx()
{
  if (btTx_index++ < btTxPacketLen)
  {
    U1THR = pTxBuffer[btTx_index];
  }
  else 
  {
    bTxBlocking=false;
    rx_en;  //макрос переключения драйвера на приём
  }
}

//Обработчик прерывания от приёмника
void Crs485::Rs485Rx()
{
  BYTE btData=U1RBR;
  ...  //процедуры обработки преамбул, ID, пакета, CRC
}

 

Есть подозрение, что вы перемудрили с FIFO или в "IIRValue == 0x03". У меня настроено прерывание по наличию/передаче одного байта, дополнительного и принудительного высасывания из FIFO не делал. Обмен полудуплексный, потому необходимо было иметь задержку ~1мс при переходе с приёма на передачу. Проц на 57600 практически не загружен в слэйве при 32 модулях на шине.

Изменено пользователем Altemir

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Неясно где и как идёт переключение, есть/нужны ли "растяжки" по RS485. Почему бы не попробовать передавать 0x55. И что за дебажные вставки? может, они могут мешать?

Рекомендую взглянуть

http://electronix.ru/forum/index.php?showtopic=42125

 

Переключение в данном случае не идет, только прием, "растяжки" - что имеется в виду ?

"55" - это и есть 0x55, я указал в скобках что строка HEX.

PutStr - пишет в очередь для вывода в UART0.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мусор может появляться если выходы драйвера ни куда не подтянуты: "прямой" должен быть подтянут к "+", "инверсный" к земле.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мусор может появляться если выходы драйвера ни куда не подтянуты: "прямой" должен быть подтянут к "+", "инверсный" к земле.

Это классическое левое решение типа конденсатора на выводах ТТЛ-логики.

И не объясняет искажения символов внутри посылки.

В данном случае осциллограф - лучший друг программиста, и если он показал отличие данных в линии от принятых, то ясно, что контроллер неправильно принимает, то есть ничего не ясно. :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это классическое левое решение типа конденсатора на выводах ТТЛ-логики.

Это почти нормальное решение. По-хорошему, конечно, протокол верхнего уровня должен игнорировать мусор между посылками, но это не повод испытывать его на прочность, этот мусор специально подсовывая.

 

И не объясняет искажения символов внутри посылки.

Внутри посылки ничего не искажается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это почти нормальное решение. По-хорошему, конечно, протокол верхнего уровня должен игнорировать мусор между посылками, но это не повод испытывать его на прочность, этот мусор специально подсовывая.

Осталось третий провод обсудить :-)

Как минимум, протокол должен быть. Т.е. время включения и отключения приемопередатчика у мастера и слэйва должны быть определены и соответствовать друг другу.

Внутри посылки ничего не искажается.

Тогда я ничего не понимаю. Автор в первом посте пишет...

 

5501160800000000000000000000E0AA(HEX) на приемник LPC2138 приходит 55408B0800000000000000000000E0AA00,

 

Последний нуль можно списать на дефекты реализации протокола, а искажения после 55 - на что?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тогда я ничего не понимаю. Автор в первом посте пишет...

 

5501160800000000000000000000E0AA(HEX) на приемник LPC2138 приходит 55408B0800000000000000000000E0AA00,

 

Последний нуль можно списать на дефекты реализации протокола, а искажения после 55 - на что?

Виноват, невнимательно смотрел :(

 

Как минимум, протокол должен быть. Т.е. время включения и отключения приемопередатчика у мастера и слэйва должны быть определены и соответствовать друг другу.

Вы полагаете, что тут конфликт между передатчиками?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

:) Тема ожила !

 

Как минимум, протокол должен быть. Т.е. время включения и отключения приемопередатчика у мастера и слэйва должны быть определены и соответствовать друг другу.

 

В данном случае у слэйва приемопередатчик всегда был на приеме.

 

Что касается сети в целом, приемопередатчики у всех девайсов в сети включены в прием, перед началом передачи мастер ждет "тишину" в канале в течении 8ms, если это случилось, начинает передачу.

Изменено пользователем srg_co

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А проверьте baud rate и вообще все настройки uart-ов передатчика и приемников... Когда я начинал работу с rs485 была такая проблема с немного отличающимися настройками по baud rate у разных устройств, в результате приходит стабильно повторяющаяся ошибка на некоторых байтах. Можно кстати проверить, послав Ваш пакет наоборот.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

На всех 38400, кварц 14,7456M, ошибка = 0.

И что планируете дальше делать? :)

 

Последние нули легко устраняются растяжкой и/или промежуточным уровнем протокола. После EOT ака 55 нечего ловить (т.е. писать в буфер) - автомат состояний поддержки протокола должен остановить прием.

Кстати, у приборов на AVR были другие авторы? Может, там так и было сделано.

 

Ну а искажение информации после начального 55... Подключите ПиСишный терминал на вход ARM (соблюдая преобразование уровней). Малые емкости в драйвере RS232 при питании 3,3 В творят чудеса.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А проверьте baud rate и вообще все настройки uart-ов передатчика и приемников... Когда я начинал работу с rs485 была такая проблема с немного отличающимися настройками по baud rate у разных устройств, в результате приходит стабильно повторяющаяся ошибка на некоторых байтах. Можно кстати проверить, послав Ваш пакет наоборот.

 

Человек идею сказал!!! Надо проверить настройку УАПП. Вероятно проблема в несовместимотсти протоколов. Больше похоже на лишний стоповый бит.

Запишите принятый байт. А после этого отправте через передатчик аналогичный байт и сравните длительности и количество стоповых/информационных бит.

Я думаю, что ситуация прояснится :-)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Действительно ли в конце происходит прерывание и из приемника принимается 0? Может софтовый указатель сбился. Имхо 0 в конце похож на результат пустого прерывания - допустим после последнего не почистился буфер. Еще как вариант - если у вас драйвер 485 постоянно на приеме, может быть результатом приема передаваемых данных. Мне не удалось при передаче избежать приема эха. Т.к. к прибору подключается или 485 или 232 пришлось решить радикально - при передаче переключал пинсел приемника на гпио.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...