Easyelectronics.ru

Электроника для всех
Текущее время: 19 фев 2020, 11:26

Часовой пояс: 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
Сообщения: 5796
У 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
Сообщения: 5796
Не даташит а 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
Сообщения: 285
Откуда: Таганрог
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
Сообщения: 285
Откуда: Таганрог
в том же 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
Сообщения: 285
Откуда: Таганрог
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
Сообщения: 5796
CheMax писал(а):
В целом разницы нет никакой, единственное что IDLE или таймаут более универсальны. Делал оба варианта, отличие только в флаге для обработке.


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


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

Зарегистрирован: 01 авг 2016, 10:47
Сообщения: 285
Откуда: Таганрог
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
Сообщения: 5796
А теперь без спл простыней попробуй , одновременно читая RM . И придет осознание - что все просто и прозрачно...


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

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

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
Сообщения: 1874
А не проще второй буфер добавить и ничего не копировать ?


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

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


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

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


Обработчик прерываний:
Код:
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
Сообщения: 1075
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
Сообщения: 648
Откуда: Санкт-Петербург
я в работе с gps отказался от DMA. Вернее когда скорость обработки была не важна, я просто заносил в буфер , а потом его парсил. Когда скорость стала важна, стал в обработчике заносить данные в буфер и выставлять флаг начала и конца посылки.


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

Зарегистрирован: 16 окт 2013, 01:27
Сообщения: 1287
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 часов


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

Сейчас этот форум просматривают: kos


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

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

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