реклама на сайте
подробности

 
 
> USART2(приём по прерывании RXNE)+USART3(DMA на передачу), STM32F2+FreeRTOS
Volldemar
сообщение Jun 21 2016, 11:28
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 121
Регистрация: 27-04-09
Из: Украина
Пользователь №: 48 342



Прошу помощи у сообщества.
Понимаю, что тема избитая, перечитал, что нашёл на этом форуме, но увы, не работает как задумано.
Вкратце алгоритм работы такой:
- приём из USART2 работает по прерыванию RXNE в массив;
- по прерыванию IDLE определяю, что приём закончен и переключаю на второй массив (что бы первый неспешно обработать, в данной реализации, для отработки алгоритма, просто выдать в USART3);
- накопленный массив выдаю в USART3 по DMA.

И вот тут грабли, выдача происходит рваная:
Код
$GPGGA,111415.00,4952.1238,E,1,11,01.2,120.4,M,26.7,M,SV,00,40,29,15018*79
$GLGSV,231,73,65,152,38,14,040,35*66
$GLGSV,2,2,06,83,720,32*66
$GNGSA,29,32,,,,,,,01.$GNGSA,A,3,83,73,0
                                        $PORZD,A,004.1*39
1A
$PORZD,A,004.1*39
$GPGGA,111417.00,49,M,,*55
$GPRMC,111417.00,A,4912.361,8
$GPGSV,3,28*,00,40,29,1501806,66,10,006,,1,29,38,240,37,18,235,00,37,33,1V,2
,2,06,83,720,32*66
$GNGSALG,32,,,,,,,01.$GNGSA,A,3,83,73,2938
.0*38
0,038,39,84,50,2,A,3,02,06,12,259,01.,M,,*5A
$GPRMC,111418.00,A,4912.3692,N,03152.1238,E,00.00,000.5,210616,,,A*58
$GPGSV,3,1,10,02,54,108,36,06,31,051,33,12,75,081,38,25,61,300,38*7E
$GPGSV,3,2,10,29,38,240,37,32,14,274,31,33,18,235,00,37,33,193,00*7E
$GPGSV,3,3,10,39,33,189,00,40,29,150,00*79
$GLGSV,2,1,06,66,10,006,30,73,65,152,38,75,05,323,01,82,14,040,34*66
$GLGSV,2,2,06,83,70,038,38,84,50,220,31*64
$GNGSA,A,3,02,06,12,25,29,32,,,,,,,01.9,01.2,01.5*19
$GNGSA,A,3,83,73,84,82,66,,,,,,,,01.9,01.2,01.5*1A
$PORZD,A,004.0*38

а теперь код, собственно как это всё у меня реализовано:
Код
//=============================================================================
    if ( USART_GetITStatus ( USART2, USART_IT_IDLE ) == SET )
    {
        DMA_Cmd ( DMA1_Stream3, DISABLE );

        USART_ReceiveData ( USART2 );// сброс PE,FE,NE,ORE,IDLE bits in USART_SR

        if ( BufIDLE.currentBuf == buf1 )
        {
            BufIDLE.currentBuf = buf2;
        }
        else
        {
            BufIDLE.currentBuf = buf1;
        }

        xSemaphoreGiveFromISR ( xSemaphore_usart2IDLE, &xHigherPriorityTaskWoken );
    }

//=============================================================================
    if ( USART_GetITStatus ( USART2, USART_IT_RXNE ) == SET )
    {
        ISRcChar2 = ( uint8_t ) ( ( USART_ReceiveData ( USART2 ) ) & (uint8_t)0xFF );

        if ( BufIDLE.currentBuf == buf1 )
        {
            BufIDLE.buf1 [BufIDLE.buf1_idx++] = ISRcChar2;
        }
        else
        {
            BufIDLE.buf2 [BufIDLE.buf2_idx++] = ISRcChar2;
        }
    }

void DMA1_Stream3_IRQHandler ( void )
{
    portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

    /* Test on DMA Stream Transfer Complete interrupt */
    if ( DMA_GetITStatus ( DMA1_Stream3, DMA_IT_TCIF3 ) == SET )
    {
        /* Clear DMA Stream Transfer Complete interrupt pending bit */
        DMA_ClearITPendingBit ( DMA1_Stream3, DMA_IT_TCIF3 );

        DMA_Cmd ( DMA1_Stream3, DISABLE );

        xSemaphoreGiveFromISR ( xSemaphore_usart3TX, &xHigherPriorityTaskWoken );
    }
}

задача, выдающая в юсарт3:
Код
void EchoTask_usart2 ( void *pvParameters )
{
#define size_local buf_SIZE

    uint8_t *USART2_Buf_local;

    USART2_Buf_local = pvPortMalloc ( size_local );

    uint16_t USART2_Idx_local = 0;

    for(;; )
    {
        xSemaphoreTake ( xSemaphore_usart2IDLE, portMAX_DELAY );

//обнуляем локальный буфер
        memset ( USART2_Buf_local, 0, size_local );
        USART2_Idx_local = 0;

        if ( BufIDLE.currentBuf == buf1 )
        {
            USART2_Idx_local = BufIDLE.buf2_idx;
            memcpy ( USART2_Buf_local, BufIDLE.buf2, USART2_Idx_local );
            memset ( BufIDLE.buf2, 0, buf_SIZE );
            BufIDLE.buf2_idx = 0;
        }
        else
        {
            USART2_Idx_local = BufIDLE.buf1_idx;
            memcpy ( USART2_Buf_local, BufIDLE.buf1, USART2_Idx_local );
            memset ( BufIDLE.buf1, 0, buf_SIZE );
            BufIDLE.buf1_idx = 0;
        }

        xSemaphoreTake ( xSemaphore_usart3TX, portMAX_DELAY );

        DMA1toUSART3TX_Put ( USART2_Buf_local, USART2_Idx_local );
    }
}


Буду благодарен за конструктивные советы.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
esaulenka
сообщение Jul 4 2016, 16:55
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



Почитал-почитал, и ничего не понял.

Я бы сделал:
- буфер FIFO с методами Put(байт) и Get(байт).
- прерывание Usart2_RXNE, которое делает Put()
- прерывание Usart3_TXE, которое делает Get()

Дальше немного магии с разрешением прерывания от уарта3:
- в обработчике Usart3_TXE, если FIFO пустой, TXE выключаем;
- в обработчике Usart2_RXNE всегда включаем TXE

И никаких переливаний из пустого в порож..., простите, я хотел сказать "никаких memcpy".
Ах, да, freertos'а в моём решении тоже нет :-)


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 02:59
Рейтинг@Mail.ru


Страница сгенерированна за 0.01403 секунд с 7
ELECTRONIX ©2004-2016