Понимаю, что тема избитая, перечитал, что нашёл на этом форуме, но увы, не работает как задумано.
Вкратце алгоритм работы такой:
- приём из 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
$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 );
}
}
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 );
}
}
{
#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 );
}
}
Буду благодарен за конструктивные советы.