LPC1768 + RS485

Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
greenrat
Родился
Сообщения: 7
Зарегистрирован: Чт авг 09, 2012 10:08:14

LPC1768 + RS485

Сообщение greenrat »

Приветствую разработчиков)

я новичок в программировании ARM, раньше все больше на Atmega программировал

начал разбираться с UART, брал стандартные примеры от Keil, но возникли непонятные проблемы. Сразу оговорюсь - на выходе с Уартов стоят изолированные RS485 - на каждый уарт свой изолированный ADM485.

Весь фокус в том что с одного на другой уарт с RS485-ми все нормально отсылается и принимается. А если послать пакет например на UART0 и ответить на этот же UART с контроллера - информация приходит искаженной, словно где то режется байт или не переключается какой то регистр...

вот пример как я отправляю пакет в шину RS485 (UART0)

Код: Выделить всё

void RS485_Send_Polling(uint32_t portNum, uint8_t *BufferPtr, uint32_t Length) 
{
  uint32_t i;

   if (portNum==0)
   {
        //Переключаем на передачу
     LPC_GPIO2->FIOSET = 1UL<<8

     for ( i = 0; i < Length; i++ ) {
      // Ждем освобождения места в буфере передачи
       while ( !((LPC_UART0->LSR>>LSR_THRE_BIT) & 1) );
       LPC_UART0->THR = *BufferPtr++;
     }
     while ( !((LPC_UART0->LSR>>LSR_TEMT_BIT) & 1) );

     //Переключаем на прием
           LPC_GPIO2->FIOCLR = 1UL<<8
   }
...
}


нет ли у кого примеров правильной работы LPC1768 c RS485? (в инете искал - но там все больше идет обсуждение нерабочих UART а про RS485 практически ничего нет или есть но советуют UART1)

Я знаю что есть UART1 и он завязан на RS485, но для задачи необходимо использование все 4-е уарта.
Реклама
Аватара пользователя
korsaj
Потрогал лапой паяльник
Сообщения: 330
Зарегистрирован: Чт июн 23, 2011 07:55:51

Re: LPC1768 + RS485

Сообщение korsaj »

485 - это физический уровень, т.е. неважно какой юарт вы используете. Как вариант контроллер не успевает передать байт до того как вы его переключаете на прием. Вначале проверте завершение передачи, а уж потом переводите на прием.
Реклама
Аватара пользователя
korsaj
Потрогал лапой паяльник
Сообщения: 330
Зарегистрирован: Чт июн 23, 2011 07:55:51

Re: LPC1768 + RS485

Сообщение korsaj »

Пользуюсь примерами от сюда http://code.google.com/p/32bitmicro/sou ... leSoftware

Я с компом через ЮАРТ общался без проблем, - прием байта от компа, изменение его и отправка обратно (типо эхосигнала).

А еще мне непонятно назначение этих строк

Код: Выделить всё

while ( !((LPC_UART0->LSR>>LSR_THRE_BIT) & 1) );
greenrat
Родился
Сообщения: 7
Зарегистрирован: Чт авг 09, 2012 10:08:14

Re: LPC1768 + RS485

Сообщение greenrat »

while ( !((LPC_UART0->LSR>>LSR_THRE_BIT) & 1) );


это проверка регистра на то что байт был отослан

в принципе сейчас вроде все работает, но иногда выскакивают странные глюки
то нормально обмен идет то при следующем включении обработается одна команда и все -
виснет в выше указанном цикле
возможно это как то связано с аппаратными буферами а именно передатчика - по умолчанию он настроен на 16 байт
попробую его поменять на 1 байт - если разберусь как :) ,
потом отпишусь о результате
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
korsaj
Потрогал лапой паяльник
Сообщения: 330
Зарегистрирован: Чт июн 23, 2011 07:55:51

Re: LPC1768 + RS485

Сообщение korsaj »

Не проверка, а зацикливание, пока условие не ложно.
Спрошу по другому - Обясните как у вас работает данное условие while ( !((LPC_UART0->LSR>>LSR_THRE_BIT) & 1) );
чему равна константа LSR_THRE_BIT и есть ли смысл тратить процессорное время на сдвиг..
Не проще ли было для процессора, написать так while ( !(LPC_UART0->LSR & LSR_THRE_BIT) ); где LSR_THRE_BIT = 0х0020
Или так while (((LPC_UART0->LSR & LSR_THRE_BIT) != LSR_THRE_BIT ); где LSR_THRE_BIT = 0х0020

Еще вопрос какой литературой пользуетесь для освоения данного мк?
Реклама
greenrat
Родился
Сообщения: 7
Зарегистрирован: Чт авг 09, 2012 10:08:14

Re: LPC1768 + RS485

Сообщение greenrat »

хорошо - приведу пример как у меня сейчас

Код: Выделить всё

#define rs485C0_init set(LPC_GPIO2->FIODIR,1UL<<8)
#define rs485C0_RX  LPC_GPIO2->FIOCLR = 1UL<<8
#define rs485C0_TX  LPC_GPIO2->FIOSET = 1UL<<8

volatile uint32_t UART0_rx_rd_index;
volatile uint32_t UART0_rx_counter;
volatile uint8_t UART0_TxEmpty = 1;
volatile uint32_t UART0_Status=0;
volatile uint8_t UART0_rx_Buffer[UART0_BufferSize];



Прерывание

Код: Выделить всё

void UART0_IRQHandler (void) 
{
  uint8_t IIRValue, LSRValue;
  uint8_t Dummy = Dummy;
   
  IIRValue = LPC_UART0->IIR;
   
  IIRValue >>= 1;            /* skip pending bit in IIR */
  IIRValue &= 0x07;            /* check bit 1~3, interrupt identification */
  if ( IIRValue == IIR_RLS )        /* Receive Line Status */
  {
    LSRValue = LPC_UART0->LSR;
    /* Receive Line Status */
    if ( LSRValue & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI) )
    {
 
      UART0_Status = LSRValue;
      Dummy = LPC_UART0->RBR;     
      return;
    }
   else
    if ( LSRValue & LSR_RDR )    /* Receive Data Ready */           
    {
      UART0_rx_Buffer[UART0_rx_counter] = LPC_UART0->RBR;
      UART0_rx_counter++;
     if (UART0_rx_counter == UART0_BufferSize)
      {
       UART0_rx_counter=0;
      }
    }
  }
  else if ( IIRValue == IIR_RDA )    /* Receive Data Available */
  {
      UART0_rx_Buffer[UART0_rx_counter] = LPC_UART0->RBR;
      UART0_rx_counter++;
     if (UART0_rx_counter == UART0_BufferSize)
      {
       UART0_rx_counter=0;
      }
  }
  else if ( IIRValue == IIR_CTI )    /* Character timeout indicator */
  {
    /* Character Time-out indicator */
    UART0_Status |= 0x100;        /* Bit 9 as the CTI error */
  }
  else if ( IIRValue == IIR_THRE )    /* THRE, transmit holding register empty */
  {
    /* THRE interrupt */
    LSRValue = LPC_UART0->LSR;        /* Check status in the LSR to see if
                                    valid data in U0THR or not */
    if ( LSRValue & LSR_THRE )
    {
      UART0_TxEmpty = 1;
    }
    else
    {
      UART0_TxEmpty = 0;
    }
  }
}


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

Код: Выделить всё

     
 uint8_t UART_Init( uint8_t PortNum, uint32_t baudrate )
{
  uint32_t pclkdiv;
  uint32_t pclk;
  uint32_t fdiv;
 uint32_t regVal;

        NVIC_DisableIRQ(UART0_IRQn); 
        CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCUART0, ENABLE);

         LPC_PINCON->PINSEL0 |=  (1 << 4);        // Pin P0.2 used as TXD0           
        LPC_PINCON->PINSEL0 |=  (1 << 6);        // Pin P0.3 used as RXD0           

        //Peripheral clock selection for UART0 - PCLKSEL0.7:6
        pclkdiv = (LPC_SC->PCLKSEL0 >> 6) & 0x03;
      
       switch (pclkdiv) {
         case 0x00:
         default:
         pclk = SystemCoreClock/4; break;
         case 0x01: pclk = SystemCoreClock;   break;
         case 0x02: pclk = SystemCoreClock/2; break;
         case 0x03: pclk = SystemCoreClock/8; break;
        }
       
      
        LPC_UART0->LCR = 0x83;            //8 bits, no Parity, 1 Stop bit, enable access to Divisor Latches
        fdiv = (pclk / 16) / baudrate;       //baud rate   
        LPC_UART0->DLM = fdiv / 256;   
        LPC_UART0->DLL = fdiv % 256;
        clr(LPC_UART0->LCR,(1<<7));      //Disable access to Divisor Latches
        //FIFO Control Register. Controls UART FIFO usage and modes.
        LPC_UART0->FCR = 0x07;          //Enable and reset TX and RX FIFO (16 and 16 byte)

        // Читаем регистр статуса линии для его очистки
        regVal = LPC_UART0->LSR;
       
        // Что бы удостовериться в отсутствии мусора ждем очистки буфера передачи
        while (LPC_UART0->LSR & (LSR_THRE | LSR_TEMT) != (LSR_THRE | LSR_TEMT));
        while (LPC_UART0->LSR & LSR_RDR) {
         regVal = LPC_UART0->RBR;        // и пока они есть считываем «в никуда» данные из буфера приёма
        }
        //Enable interrupt
        NVIC_EnableIRQ(UART0_IRQn);
        LPC_UART0->IER = IER_RBR | IER_RLS | IER_THRE;

  }


Отправка байта

Код: Выделить всё

void RS485x_Send_Polling(uint8_t portNum, uint8_t *BufferPtr, uint32_t Length) 
{
  uint32_t i;

     LPC_UART0->IER = IER_THRE | IER_RLS;         //Disable RBR
     rs485C0_TX;
     for ( i = 0; i < Length; i++ ) {
       while ( !(UART0_TxEmpty & 0x01) ); 
       LPC_UART0->THR = *BufferPtr++;
      UART0_TxEmpty = 0;
     }
    while ( !(UART0_TxEmpty & 0x01) );
     rs485C0_RX;
    LPC_UART0->IER = IER_THRE | IER_RLS | IER_RBR;   // Re-enable RBR

  return;
}



дальше просто в цикле смотрю есть что либо в буфере и если что есть - обрабатываю
если не вникая в код я тут использовал стандартный пример от Keil для работы с UART добавил только
переключение ножки RS485 (rs485C0_RX; rs485C0_TX;)

при обработке - смотрю есть ли у меня во входном буфере данные - если есть то их обрабатываю
Реклама
Аватара пользователя
korsaj
Потрогал лапой паяльник
Сообщения: 330
Зарегистрирован: Чт июн 23, 2011 07:55:51

Re: LPC1768 + RS485

Сообщение korsaj »

Пример стандартный. Только строкой while ( !((LPC_UART0->LSR>>LSR_THRE_BIT) & 1) ); вы "подвешиваете" цикл. Мк будет крутится на этой строке пока буфер не пуст. Лучще сделать проверку в основном цикле этого бита и если он не установлен продолжать выполнения программы.
А еще лучще сделать это в прерывании, тем более в примере все есть в обработчике прерываний. И по идеи вы должны в цикле проверять UART0_TxEmpty
Смотрите в побработчике последнюю инструкцию else if
Вот она:

Код: Выделить всё

else if ( IIRValue == IIR_THRE )    /* THRE, transmit holding register empty */
  {
    /* THRE interrupt */
    LSRValue = LPC_UART0->LSR;        /* Check status in the LSR to see if
                                    valid data in U0THR or not */
    if ( LSRValue & LSR_THRE )
    {
      UART0_TxEmpty = 1;
    }
    else
    {
      UART0_TxEmpty = 0;
    }
  }

Собственно в функции RS485x_Send_Polling уже все реализовано.

Вот в этой книге можно немного почерпнуть о работе мк Микроконтроллеры ARM7 семейств LPC 2300/2400. Вводный курс разработчика

А вот эту книгу я нигде не найду http://dodeca.ru/books/228/
greenrat
Родился
Сообщения: 7
Зарегистрирован: Чт авг 09, 2012 10:08:14

Re: LPC1768 + RS485

Сообщение greenrat »

Спасибо) я тоже уже подумал перенести отслеживание передачи пакета в прерывание и завершать - переключать ногу - там же
книжку поищу - если найду скину сюда ссылку
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Re: LPC1768 + RS485

Сообщение ibiza11 »

korsaj писал(а):Вот в этой книге можно немного почерпнуть о работе мк Микроконтроллеры ARM7 семейств LPC 2300/2400. Вводный курс разработчика
:facepalm: Вы хоть сами эту книжку читали? Если бы прочли, то такого бы не заявляли:
korsaj писал(а):и есть ли смысл тратить процессорное время на сдвиг..?
PS Книжка годная, советую! Несмотря на то, что LPC1768 - Cortex-M3, а в книжке про ARM7. Очень полезное чтиво для перехода от 8-битного "мышления".
korsaj писал(а):А вот эту книгу я нигде не найду http://dodeca.ru/books/228/
Не мудрено, её еще не напечатали даже) Пока можете почитать это: "Joseph Yiu. The Definitive Guide to the ARM Cortex-M3."
Ставим плюсы: )
Аватара пользователя
korsaj
Потрогал лапой паяльник
Сообщения: 330
Зарегистрирован: Чт июн 23, 2011 07:55:51

Re: LPC1768 + RS485

Сообщение korsaj »

ibiza11 писал(а): :facepalm: Вы хоть сами эту книжку читали? Если бы прочли, то такого бы не заявляли:
korsaj писал(а):и есть ли смысл тратить процессорное время на сдвиг..?

А собственно разве гуманно в цикле с проверкой условия каждый раз выполнять LPC_UART0->LSR>>LSR_THRE_BIT - что собственно значит сдвиг в право значения поля LSR структуры LPC_UART0 на LSR_THRE_BIT (32) бита?

Книгу читал, даю слово )
Может правда не все усвоил.
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Re: LPC1768 + RS485

Сообщение ibiza11 »

вот одна из команд, которая поддерживается Cortex-M3
AND{S}.W <Rd>,<Rn>,<Rm>{,<shift>} Bitwise AND register value with shifted register value
Будете Вы сдвигать значение регистра перед операцией побитового И(bitwise AND) со значением 0x01 или не будете, ядру все равно, команда одна. Компилятор хоть так, хоть эдак этот код преобразует в одну команду.
на LSR_THRE_BIT (32) бита?
LSR_THRE_BIT = 32? или что Вы имеете в виду? LSR - фактически это Line Status Register, а THRE - Transmitter Holding Register Empty - флаг опустошения регистра передачи UART (5ый бит 32-битного регистра LSR).
Ставим плюсы: )
Аватара пользователя
korsaj
Потрогал лапой паяльник
Сообщения: 330
Зарегистрирован: Чт июн 23, 2011 07:55:51

Re: LPC1768 + RS485

Сообщение korsaj »

С одной командой согласен..
Вот по тому мой вопрос выше в постах звучал, чему равен LSR_THRE_BIT?
LSR_THRE_BIT = 0000 0000 0010 0000 вот так выглядит в бинарке, вот так в кексе 0х0020 ну а вот так в дес. 32.
LSR_THRE_BIT = 5.

Исправляю последнююю строку чтоб бы меня понимали
или LSR_THRE_BIT = 5
Последний раз редактировалось korsaj Пт апр 26, 2013 16:35:47, всего редактировалось 7 раз.
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Re: LPC1768 + RS485

Сообщение ibiza11 »

А откуда Вы взяли значение этой константы? Я так понимаю, что эта константа (LSR_THRE_BIT) объявлена в стандартной библиотеке от NXP?
я стараюсь не пользоваться ей. В стандартном файле описания периферии более продвинутого семейства (LPC177x_8x.h) я такого объявления не нашел.
Зато нашел другое объявление

Код: Выделить всё

#define UART_LSR_THRE      ((uint8_t)(1<<5))    /*!<Line status register: Transmit holding register empty*/

korsaj писал(а):Книгу читал, даю слово )
Может правда не все усвоил.
Ну да, как то избирательно прочли) Глава 1. Раздел 1.6.2. Команды обработки данных (стр.22 моего издания) (Это у меня настольная книга, если что)
korsaj писал(а):LSR_THRE_BIT = 0000 0000 0010 0000 вот так выглядит в бинарке, вот так в кексе 0х0020 ну а вот так в дес. 32.
LSR_THRE_BIT = 5.
Вот этого совсем не понял. Как это одновременно и 32 и 5 ? :)
Ставим плюсы: )
Аватара пользователя
korsaj
Потрогал лапой паяльник
Сообщения: 330
Зарегистрирован: Чт июн 23, 2011 07:55:51

Re: LPC1768 + RS485

Сообщение korsaj »

Тю на вас..
Там же не написано что одновременно, я продположил что константа равна 32, а ниже написал второй вариант что она равна 5
)))
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Re: LPC1768 + RS485

Сообщение ibiza11 »

:o Ну Вы и хамло. Ваши предположения из головы необходимо в текст сообщения выносить, чтобы Вас понимали.
Ставим плюсы: )
Аватара пользователя
korsaj
Потрогал лапой паяльник
Сообщения: 330
Зарегистрирован: Чт июн 23, 2011 07:55:51

Re: LPC1768 + RS485

Сообщение korsaj »

ibiza11 писал(а):Ну да, как то избирательно прочли) Глава 1. Раздел 1.6.2. Команды обработки данных (стр.22 моего издания) (Это у меня настольная книга, если что)

Точно изберательно читал (успел только 1 раз прочесть, неделю с этим мк воюю), совершенно этого не помню. А может не понял сразу и потому незапомнилось. Вот у вас настольная, а я купить все не могу, хотя хочу. Конечно больше хочу купить ту которую еще не начали печатать, но к сожеелнию додека морозится, я им писал, и книга у них в анонсе уже давно вроде с 2011 года.
Аватара пользователя
korsaj
Потрогал лапой паяльник
Сообщения: 330
Зарегистрирован: Чт июн 23, 2011 07:55:51

Re: LPC1768 + RS485

Сообщение korsaj »

ibiza11 :o Ну Вы и хамло. Ваши предположения из головы необходимо в текст сообщения выносить, чтобы Вас понимали.

Пальцы чешутся? Так купите себе наждачку, а не об клаву их чешите.
Вот теперь я хамло, как и Вы.
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Re: LPC1768 + RS485

Сообщение ibiza11 »

я Вам не хамил.
Возвращаясь к теме, прошу автора пояснить чему же все таки равна эта злосчастная константа.
Ставим плюсы: )
greenrat
Родился
Сообщения: 7
Зарегистрирован: Чт авг 09, 2012 10:08:14

Re: LPC1768 + RS485

Сообщение greenrat »

У меня она равна
#define LSR_THRE_BIT 5


попробовал сегодня перенести все в прерывание - в принципе работает - теперь без бесконечного цикла, но все равно иногда какой то косяк выскакивает - шлет пакет - получает ответ
следующая команда почему то не проходит. раз несколько вызываю эту команду и через раз или пару раз - набор команд проходит как надо. Причем замечено - что если просто слать какому то девайсу
набор пакетов без ответа - все работает четко, как только вклинивается ответ то все идет на перекосяк... Странный вообщем глюк - на атмегах у меня такого не было.
Буду разбираться дальше - толи прерывание не срабатывает толи еще что...
Аватара пользователя
korsaj
Потрогал лапой паяльник
Сообщения: 330
Зарегистрирован: Чт июн 23, 2011 07:55:51

Re: LPC1768 + RS485

Сообщение korsaj »

Покажите обработчик прерывания. Возможно вы переключаете направление до того как UART успел передать/принять байт.
Ответить

Вернуться в «Периферия»