Easyelectronics.ru

Электроника для всех
Текущее время: 14 окт 2019, 03:49

Часовой пояс: UTC + 5 часов



JLCPCB – Прототипы печатных плат за $2/10pcs (Любой цвет!)
Крупнейший производитель печатных плат и прототипов. Более 600000 клиентов и свыше 10000 заказов в день!
Получите скидку на почтовую отправку при первом заказе в JLCPCB!

Начать новую тему Ответить на тему  [ Сообщений: 26 ]  На страницу 1, 2  След.
Автор Сообщение
 Заголовок сообщения: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 08 дек 2016, 16:27 
Старожил

Зарегистрирован: 28 ноя 2013, 14:12
Сообщения: 275
Хотел написать прием данных UARTа с использованием DMA.
Но количество принимаемых данных в буфере всегда разное.

Начало и конец четко определены. Но длинна пакета разная.

В этом случае есть смысл применять DMA?
Принятые буфер придется вручную проверять и делить на правильные куски ?
Или есть какой нибудь более правильный алгоритм ?

(Пытаюсь попроще обработать данные с GPS)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 08 дек 2016, 16:31 
Старожил

Зарегистрирован: 11 сен 2012, 11:19
Сообщения: 5688
У F0 есть прерывание по определенному символу. Заводим DMA на максимальную длину пакета ...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 08 дек 2016, 16:57 
Старожил

Зарегистрирован: 28 ноя 2013, 14:12
Сообщения: 275
а где про такое чудо почитать ? что то даташит полный не нахожу


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 08 дек 2016, 16:59 
Старожил

Зарегистрирован: 11 сен 2012, 11:19
Сообщения: 5688
Не даташит а RM http://www.st.com/content/ccc/resource/ ... 091010.pdf


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 08 дек 2016, 17:16 
Старожил

Зарегистрирован: 28 ноя 2013, 14:12
Сообщения: 275
23.6 USART interrupts
Table 92. USART interrupt requests
Это я так понял все возможные прерывания.

Character match - соответствует прерыванию по получению конкретного символа ?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 08 дек 2016, 17:31 
Старожил
Аватара пользователя

Зарегистрирован: 01 авг 2016, 10:47
Сообщения: 284
Откуда: Таганрог
r0cket писал(а):
23.6 USART interrupts
Table 92. USART interrupt requests
Это я так понял все возможные прерывания.

Character match - соответствует прерыванию по получению конкретного символа ?


да, это оно.

Ещё один вариант: DMA настраиваем на длину N >= максимальной. Далее используется либо IDLE, либо ReceiveTimeout.
В первом случае USART выдаст прерывание когда на линии возникнет тишина. Во втором случае - по прошествию указанного таймаута.

При этом количество принятых данных: N - DMA_channel->CNDR;


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 08 дек 2016, 17:35 
Старожил
Аватара пользователя

Зарегистрирован: 01 авг 2016, 10:47
Сообщения: 284
Откуда: Таганрог
в том же F0 кстати есть и таймаут, и IDLE. Так что возможна реализация аж трех варинатов, на любой вкус как говорится. И да, укажите конкретно какой у вас МК. Или товарищ dosikus_2 через хрустальный шар угадал?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 08 дек 2016, 17:42 
Старожил

Зарегистрирован: 28 ноя 2013, 14:12
Сообщения: 275
МК могу любой взять. Спасибо за советы. IDLE тоже неплохой вариант.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 08 дек 2016, 17:48 
Старожил

Зарегистрирован: 28 ноя 2013, 14:12
Сообщения: 275
А вот еще по поводу IDLE вопрос.

Прерывание придет. Я сброшу флаг. Тишина на линии продлится еще какое то время.

Мне следующий флаг придет сразу. Или при следующем IDLE после новых данных ?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 08 дек 2016, 17:52 
Старожил
Аватара пользователя

Зарегистрирован: 01 авг 2016, 10:47
Сообщения: 284
Откуда: Таганрог
r0cket писал(а):
МК могу любой взять. Спасибо за советы. IDLE тоже неплохой вариант.


В целом разницы нет никакой, единственное что IDLE или таймаут более универсальны. Делал оба варианта, отличие только в флаге для обработке.

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

Читаем reference:

IDLE: IDLE line detected
This bit is set by hardware when an Idle Line is detected. An interrupt is generated if the
IDLEIE=1 in the USART_CR1 register. It is cleared by a software sequence (an read to the
USART_SR register followed by a read to the USART_DR register).
0: No Idle Line is detected
1: Idle Line is detected
Note: The IDLE bit will not be set again until the RXNE bit has been set itself (i.e. a new idle
line occurs).


находим ответ)))


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 08 дек 2016, 17:56 
Старожил

Зарегистрирован: 28 ноя 2013, 14:12
Сообщения: 275
Спасибо еще раз)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 08 дек 2016, 18:00 
Старожил

Зарегистрирован: 11 сен 2012, 11:19
Сообщения: 5688
CheMax писал(а):
В целом разницы нет никакой, единственное что IDLE или таймаут более универсальны. Делал оба варианта, отличие только в флаге для обработке.


Поправочка, таймаут настраивается в отличии от IDLE...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 08 дек 2016, 18:12 
Старожил
Аватара пользователя

Зарегистрирован: 01 авг 2016, 10:47
Сообщения: 284
Откуда: Таганрог
dosikus_2 писал(а):
Поправочка, таймаут настраивается в отличии от IDLE...


Точно, забыл упомянуть :)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 08 дек 2016, 18:28 
Старожил
Аватара пользователя

Зарегистрирован: 27 мар 2015, 04:10
Сообщения: 1931
Откуда: Харьков
Character match это вообще отличное прерывание, жалко что его нет в других камнях. Хотя IDLE в большинстве случаев хватает.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 08 дек 2016, 19:01 
Старожил

Зарегистрирован: 26 янв 2010, 21:47
Сообщения: 345
По работе с GPS приёмниками есть нюанс.
Не все приёмники одинаково выдают все предложения NMEA0183 в одном кадре ДМА, ДМА имеется ввиду в самом приёмнике. Я на это был наступил. Так что у меня реализовано через IDLE плюс таймер. Обработчик прерывания юсарта вот такой:
Код:
//=============================================================================
void USART2_IRQHandler ( void )
{
   portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
   uint8_t ISRcChar2;
//=============================================================================
   if ( USART_GetITStatus ( USART2, USART_IT_IDLE ) == SET )
   {
      USART_ReceiveData ( USART2 );// сброс PE,FE,NE,ORE,IDLE bits in USART_SR

      xTimerResetFromISR ( xIntervalTimer2_IDLE_100ms, &xHigherPriorityTaskWoken );
   }
//=============================================================================
   if ( USART_GetITStatus ( USART2, USART_IT_RXNE ) == SET )
   {
      USART_ITConfig ( USART2, USART_IT_RXNE, DISABLE );
      USART_ITConfig ( USART2, USART_IT_IDLE, ENABLE );

      xTimerStartFromISR ( xIntervalTimer2_IDLE_100ms, &xHigherPriorityTaskWoken );

      RxDMA1_Stream5 ();
   }
//=============================================================================
// выход из обработчика прерывания
   portEND_SWITCHING_ISR ( xHigherPriorityTaskWoken );
}

Обработчик прерывания ДМА:
Код:
void RxDMA1_Stream5 ( void ) //настройка DMA на чтение данных из UART2
{
   DMA_InitTypeDef dma_Init;

   DMA_Cmd ( DMA1_Stream5, DISABLE );//отключаю DMA для получения доступа к регистрам

   DMA_DeInit ( DMA1_Stream5 );//на всякимй случай

   DMA_StructInit ( &dma_Init );

   while ( DMA_GetCmdStatus ( DMA1_Stream5 ) != DISABLE )
   {
   }

   dma_Init.DMA_Channel = DMA_Channel_4;
   dma_Init.DMA_PeripheralBaseAddr = (uint32_t) &USART2->DR;

   switch ( CurrentBuf2 )
   {
      case buf1:
      {
         dma_Init.DMA_Memory0BaseAddr = (uint32_t) &USART2_Buf1_IDLE[0];
      } break;

      case buf2:
      {
         dma_Init.DMA_Memory0BaseAddr = (uint32_t) &USART2_Buf2_IDLE[0];
      } break;
   }

   dma_Init.DMA_DIR = DMA_DIR_PeripheralToMemory;
   dma_Init.DMA_BufferSize = buf_SIZE;
   dma_Init.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
   dma_Init.DMA_MemoryInc = DMA_MemoryInc_Enable;
   dma_Init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
   dma_Init.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
   dma_Init.DMA_Mode = DMA_Mode_Normal;
   dma_Init.DMA_Priority = DMA_Priority_High;
   dma_Init.DMA_FIFOMode = DMA_FIFOMode_Disable;
   dma_Init.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
   dma_Init.DMA_MemoryBurst = DMA_MemoryBurst_Single;
   dma_Init.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

   DMA_Init ( DMA1_Stream5, &dma_Init );

   DMA_Cmd ( DMA1_Stream5, ENABLE );//включаю DMA... и он начинает складывать поступающие данные в заданный буфер
}

Как видно из кода, приём происходит в два массива, накапливаем в первый, второй обрабатываем, потом переключаем.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 12 янв 2017, 13:28 
Старожил

Зарегистрирован: 28 ноя 2013, 14:12
Сообщения: 275
Настроил f407 на прием по IDLE.
Все работает.

Вот кусок с настройками.
При этих настройках. IDLE вызывает прерывание "void USART3_IRQHandler ( void )"

Код:

   NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);


  USART_InitStructure.USART_BaudRate = UART_DMA_COM_BAUD;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  USART_Init(UART_DMA_COM_PORT, &USART_InitStructure);

  // UART enable
  USART_Cmd(UART_DMA_COM_PORT, ENABLE);
  USART_ITConfig ( USART3, USART_IT_IDLE, ENABLE );

  DMA_DeInit(UART_DMA_RX_STREAM);
  DMA_InitStructure.DMA_BufferSize = UART_DMA_RX_BUF_SIZE;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single ;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t) (&(UART_DMA_COM_PORT->DR));
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;

  DMA_InitStructure.DMA_Channel = UART_DMA_CHANNEL;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
  DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)rx_temp1;
  DMA_Init(UART_DMA_RX_STREAM,&DMA_InitStructure);

  // enable DMA-RX request
  USART_DMACmd(UART_DMA_COM_PORT, USART_DMAReq_Rx, ENABLE);

  // DMA-RX Transfer-Complete Interrupt enable
//  DMA_ITConfig(UART_DMA_RX_STREAM, DMA_IT_TC, ENABLE);

  // DMA-RX enable
  DMA_Cmd(UART_DMA_RX_STREAM,ENABLE);




Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 12 янв 2017, 14:56 
Старожил

Зарегистрирован: 11 сен 2012, 11:19
Сообщения: 5688
А теперь без спл простыней попробуй , одновременно читая RM . И придет осознание - что все просто и прозрачно...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 13 янв 2017, 00:38 
Старожил

Зарегистрирован: 26 ноя 2012, 10:28
Сообщения: 3992
Откуда: КЧР, поселок Нижний Архыз
dosikus_2, уже 15 минут сижу, втыкаю в RM и не могу врубиться, как мне посчитать количество уже принятых символов (чтобы лишнее не копировать во второй буфер, когда получили строку).
Настраиваю USART (у меня STM32F402-nucleo, у нее USART идет через проксирование VCP встроенным st-link'ом):
Код:
void usart2_setup(){
    // setup pins: PA2 (Tx - AF1), PA15 (Rx - AF1)
    RCC_AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_DMAEN;
    // AF mode
    gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2|GPIO15);
    gpio_set_af(GPIOA, GPIO_AF1, GPIO2|GPIO15);
    // DMA: Tx - Ch4, Rx - Ch5
    DMA1_CPAR4 = (uint32_t) &USART2_TDR; // periph
    DMA1_CMAR4 = (uint32_t) tbuf; // mem
    // Tx CNDTR set @ each transmission due to data size
    DMA1_CCR4 |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE; // 8bit, mem++, mem->per, transcompl irq
    DMA1_CPAR5 = (uint32_t) &USART2_RDR;
    DMA1_CMAR5 = (uint32_t) rbuf;
    DMA1_CNDTR5 = UARTBUFSZ;
    DMA1_CCR5 |= DMA_CCR_MINC | DMA_CCR_TCIE; // 8bit, mem++, per->mem, transcompl irq
    nvic_set_priority(NVIC_DMA1_CHANNEL4_5_IRQ, 0);
    nvic_enable_irq(DMA1_CHANNEL4_5_IRQHandler);
    // setup usart2
    RCC_APB1ENR |= RCC_APB1ENR_USART2EN; // clock
    USART_CR2 = USART_CR2_ADD_VAL('\n'); // set newline as 'character match' interrupt
    // oversampling by16, 115200bps (fck=48mHz)
    USART2_BRR = 0x1a1; // 48000000 / 115200
    USART2_CR3 = USART_CR3_DMAR | USART_CR3_DMAT; // enable DMA Tx/Rx
    USART2_CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; // 1start,8data,nstop; enable Rx,Tx,USART
    while(!(USART1_ISR & USART_ISR_TC)); // polling idle frame Transmission
    USART1_ICR |= USART_ICR_TCCF; // clear TC flag
    USART1_CR1 |= USART_CR1_CMIE; // Enable CM interrupt
}

И прерывание по концу строки:
Код:
void usart2_isr(){
    if(USART2_ISR & USART_ISR_CMF){ // character match
        linerdy = 1; // set 'line ready' flag
        memcpy(recvdata, tbuf, UARTBUFSZ); // how to know real size of received string?
    }
    USART2_ISR = 0;
}

Не хочется каждый раз все 128 байт копировать, если, скажем, придет 10-15 байт.

Получится ли считать принимаемые символы внутри прерывания RXNE, или же оно не будет генерироваться из-за DMA?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 13 янв 2017, 01:03 
Старожил

Зарегистрирован: 26 ноя 2012, 10:28
Сообщения: 3992
Откуда: КЧР, поселок Нижний Архыз
А, счетчик же декрементируется!
Вот как вышло:
Код:

void dma1_channel4_5_isr(){
    if(DMA1_ISR & DMA_ISR_TCIF4){ // Tx
        DMA1_IFCR |= DMA_IFCR_CIF4; // clear TC flag
        txrdy = 1;
    }
    if(DMA1_ISR & DMA_ISR_TCIF5){ // Rx
        DMA1_IFCR |= DMA_IFCR_CIF5; // clear TC flag
        DMA1_CCR5 &= ~DMA_CCR_EN; // turn off Rx DMA to refresh CNDTR
        DMA1_CNDTR5 = UARTBUFSZ;
        DMA1_CCR5 |= DMA_CCR_EN;
        bufovr = 1; // set buffer overrun flag: Rx buffer full, but no '\n' met!
    }
}

void usart2_isr(){
    if(USART2_ISR & USART_ISR_CMF){ // character match
        linerdy = 1; // set 'line ready' flag
        memcpy(recvdata, tbuf, UARTBUFSZ - DMA1_CNDTR5); // copy full received string into buffer
        USART2_ICR |= USART_ISR_CMF;
        // reload DMA Rx
        DMA1_CCR5 &= ~DMA_CCR_EN;
        DMA1_CNDTR5 = UARTBUFSZ;
        DMA1_CCR5 |= DMA_CCR_EN;
    }
}


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 13 янв 2017, 02:08 
Старожил
Аватара пользователя

Зарегистрирован: 04 окт 2011, 10:19
Сообщения: 1762
А не проще второй буфер добавить и ничего не копировать ?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 13 янв 2017, 02:11 
Старожил

Зарегистрирован: 26 ноя 2012, 10:28
Сообщения: 3992
Откуда: КЧР, поселок Нижний Архыз
Ваша правда.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 03 июл 2019, 12:41 
Старожил

Зарегистрирован: 16 окт 2013, 01:27
Сообщения: 1102
Обновлю тему:
Столкнулся с такой же проблемой, в итоге родилось вот такое решение.


Обработчик прерываний:
Код:
void USART1_IRQHandler(void)       {//USART1 IRQ HANDLER
   if (USART1->ISR & USART_ISR_RXNE)   {} // Got Data in RX - Buffer
  if (USART1->ISR & USART_ISR_RTOF)          { // TimeOut - message receidved
   dma_qnt=DMA1_Channel3->CNDTR;
   word_flag=1;
   USART1->ICR |=USART_ICR_RTOCF;
  }
  if (USART1->ISR & USART_ISR_ORE)              {// Reset OverRun
         USART1->ICR |=USART_ICR_ORECF;      
   }   
}

void DMA1_Ch2_3_DMA2_Ch1_2_IRQHandler (void)  {} // DMA IRQ - if use Circular buffer, do not applicable.


Настройки:
Код:
//--------------------------USART--------------------------------   
/*PB6, PB7 - Alternative function USART1*/
GPIOB->MODER |= GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1;;                         // AFR=0 - UART TX, UART RX
      
RCC->APB2ENR |=RCC_APB2ENR_USART1EN;
#ifdef UBLOX
   USART1->BRR = 0x1388; // 9600  ((48000000 /9600))
#endif
#ifdef NL3333
   USART1->BRR = 0x1A0; // 9600  ((48000000 /115200))
#endif

//USART1->CR2 |=   0x24<<USART_CR2_ADD_Pos; //Activate when receive '$'

USART1->CR2 |=   USART_CR2_RTOEN;
USART1->RTOR |=10; //10 symbols and activate idle

USART1->CR1 |=    USART_CR1_RE | USART_CR1_RTOIE | USART_CR1_UE ;//
USART1->CR3 |=   USART_CR3_DMAR;

NVIC_EnableIRQ (USART1_IRQn); //    
NVIC_SetPriority(USART1_IRQn,0x02);
      
//====================== DMA==================================
RCC->AHBENR |=RCC_AHBENR_DMA1EN;

DMA1_Channel3->CPAR =(uint32_t)&USART1->RDR;
DMA1_Channel3->CMAR =(uint32_t)CIRC_BUF;
DMA1_Channel3->CNDTR = 600;

DMA1_Channel3->CCR    |= DMA_CCR_MINC | DMA_CCR_CIRC | DMA_CCR_PL_1;

DMA1_Channel3->CCR    |= DMA_CCR_EN;
NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
NVIC_SetPriority(DMA1_Channel2_3_IRQn,0);


Размер буфера 600 байт, ищет только последнюю строчку с заголовком GxRMC, на остальные не обращает внимание.
CIRC_BUF - кольцевой буфер,USART_BUF - операционный буфер, в который копируются данные, как только нашли RMC строчку - выходим из цикла поиска.
Разбор и поиск строки:
Код:
pos_b=   600- (DMA1_Channel3->CNDTR);
for (j=0; j   <600; j++)
   {
    if ((pos_b-j)>=0)    {jj=pos_b-j;}
    else                      {jj=599-(pos_b-j);}
   
    if ((CIRC_BUF[jj]=='$') && (CIRC_BUF[jj+3]=='R') &&  ((CIRC_BUF[jj+17]=='A') || (CIRC_BUF[jj+18]=='A')))
       {
    do {
         USART_BUF[buf_c]=CIRC_BUF[jj+buf_c];
       buf_c++;
         } while ( (CIRC_BUF[jj+buf_c]!=0x0A) && (CIRC_BUF[jj+(buf_c-1)] !=0x0D));
    j=600;
    }
   }
   sscanf(USART_BUF,"$G%cRMC,%2d%2d%2d.%f,A,%f,%c,%f,%c,%f,%f",
   &symb,&hh, &mm, &ss, &ms, &t_lat,&GNSS_RMC.lat_sign, &t_lon,
   &GNSS_RMC.lon_sign, &speed, &course);


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 03 июл 2019, 13:17 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 1015
sed_alex писал(а):
Код:
if ((CIRC_BUF[jj]=='$') && (CIRC_BUF[jj+3]=='R') &&  ((CIRC_BUF[jj+17]=='A') || (CIRC_BUF[jj+18]=='A')))

Уверен, что у тебя jj не может быть больше 599 - 18?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 03 июл 2019, 13:59 
Старожил

Зарегистрирован: 02 ноя 2015, 19:21
Сообщения: 607
Откуда: Санкт-Петербург
я в работе с gps отказался от DMA. Вернее когда скорость обработки была не важна, я просто заносил в буфер , а потом его парсил. Когда скорость стала важна, стал в обработчике заносить данные в буфер и выставлять флаг начала и конца посылки.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: UART DMA прием (количество неизвестно)
СообщениеДобавлено: 03 июл 2019, 15:56 
Старожил

Зарегистрирован: 16 окт 2013, 01:27
Сообщения: 1102
Reflector писал(а):
sed_alex писал(а):
Код:
if ((CIRC_BUF[jj]=='$') && (CIRC_BUF[jj+3]=='R') &&  ((CIRC_BUF[jj+17]=='A') || (CIRC_BUF[jj+18]=='A')))

Уверен, что у тебя jj не может быть больше 599 - 18?


По идее в буфере всегда два кадра, если первый будет на перегибе то второй точно поймает,
за подсказку огромное спасибо, на самом деле нужна проверка.


Цитата:
я в работе с gps отказался от DMA. Вернее когда скорость обработки была не важна, я просто заносил в буфер , а потом его парсил. Когда скорость стала важна, стал в обработчике заносить данные в буфер и выставлять флаг начала и конца посылки.


Была реализация сначала с двойным буфером и прерыванием, но сейчас на столе лежит модуль морской, который фигачит на скорости 115200, 10 раз в секунду, и при таком раскладе при максимальной длинне посылки 712 байт получается в секунду прилетает 7 кб данных, из которых нужно выцеплять каждый раз 2 строчки $GPRMC и $GNRMC
Так вот если это все делать в прерывании, то контроллер слишком много времени занимается всякой ерундой.
Вообще разбор данных это очень скользкая тема и нужно смотреть исходя из ситуации.

для сравнения обработчик который был до этого:
Код:
void USART1_IRQHandler(void)       {//USART1 IRQ HANDLER
   if (USART1->ISR & USART_ISR_RXNE)                                                   {   // Got Data in RX - Buffer
   if (act_usart) {USART_BUF = USART_BUF1;}
   else                   {USART_BUF = USART_BUF0;}

   USART_BUF[usart_rx]=(uint8_t)(USART1->RDR);         //PutChar(UART1->DR,0);
      if((USART_BUF[usart_rx]==0x24) || (USART_BUF[usart_rx]==0x21))
            {USART_BUF[0]=USART_BUF[usart_rx]; usart_rx=0;}                      //Preambule detected
      usart_rx++;
      if((USART_BUF[usart_rx-1]==0x0D)&&(USART_BUF[usart_rx]==0x0A))    {   //Frame Received
         if ((USART_BUF[3]=='R')&& ((USART_BUF[17]=='A')||(USART_BUF[18]=='A')))                        {   //There is good RMC frame received
                usart_rx--;
               act_usart++;
               if (act_usart>1) {act_usart=0;}
               word_flag=1;
         }
         else                                                                                        {   //Not RMC frame
               usart_rx=0;
            //   char USART_BUF[82]={0x00}; //Flush not RMC Frame
               }   
      }
         if (usart_rx > 82) usart_rx =0;
      }

   if (USART1->ISR & USART_ISR_ORE)      {
         USART1->ICR |=USART_ICR_ORECF;      // Reset OverRun
   }   
   
   }


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 26 ]  На страницу 1, 2  След.

Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB