cancel
Showing results for 
Search instead for 
Did you mean: 

stm32 receive data via serial port problem

jki79ros81
Associate II
Posted on October 16, 2008 at 14:44

stm32 receive data via serial port problem

5 REPLIES 5
andy239955_stm1
Associate II
Posted on May 17, 2011 at 12:47

The only operational difference between your code and mine is checking for IDLE, I don't use fwlib so my actual code is quite different.

I believe you must read the status register (the one with RXNE in it) for every data byte. Reading the status clears some hardware bits, if you don't do that then you get overrun errors (which you are ignoring) and no new data.

jki79ros81
Associate II
Posted on May 17, 2011 at 12:47

Greetings to everybody!

My english rather poor.

I have serial communication program which send several command of random byte length..

When program send a command, my stm32 module receive only first 1byte and can not second byte.

I code as follow.

...............

USART_InitStructure.USART_BaudRate = DEFAULT_BAUDRATE;

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_ClockInitStructure.USART_Clock = USART_Clock_Enable;

USART_ClockInitStructure.USART_CPOL = USART_CPOL_High;

USART_ClockInitStructure.USART_CPHA = USART_CPHA_1Edge;

USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;

/* Configure the USART1 */

USART_Init(USARTx, &USART_InitStructure);

USART_ClockInit(USARTx, &USART_ClockInitStructure);

/* Enable the USART Receive interrupt: this interrupt is generated when the

USART1 receive data register is not empty */

USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE);

/* Enable USART1 */

USART_Cmd(USARTx, ENABLE);

................

void USART1_IRQHandler(void)

{

u16 TxCounter = 0;

if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)

{

/* Loop until the end of receive */

while(USART_GetFlagStatus(USART1, USART_FLAG_IDLE) == SET)

{

/* Read one byte from the receive data register */

g_pComBuf[TxCounter ++] = USART_ReceiveData(USART1)& 0x7F;

}

}

}

In STR711, I prorammed as follow and there is not problem as before.

void UART0_IRQHandler(void)

{

u32 vRxCount = ( u32 )g_pComBuf;

UART_ItConfig( UART_PORT, UART_RxBufFull, DISABLE );

while( !( UART_TimeOutIdle & UART_ByteReceive( UART_PORT, (u8*)vRxCount++, UART_TIMEOUT ) ) ) ;

UART_ItConfig( UART_PORT, UART_RxBufFull, ENABLE );

}

I readed stm32 has only one byte FIFO for serial port.

Certainly Must use DMA?

Thank you very much for response

jack

jki79ros81
Associate II
Posted on May 17, 2011 at 12:47

Hello heilveil,

Thank you very much.

I think that reception of command buffer from pc program without using DMA is impossible.

really?

So theses days I use DMA and received first command.

But second command was not received.

void USART1_IRQHandler(void)

{

if(USART_GetFlagStatus(USART1, USART_FLAG_IDLE) == RESET) {

if(USART1->CR3 & USART_DMAReq_Rx ){

g_blReadCommand = TRUE;

USART_ClearFlag(USART1, USART_FLAG_RXNE);

USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);

}

}

.........

}

int main (void)

{

#ifdef DEBUG

debug();

#endif

....................

/* DMA1 Channel5 (triggered by USART1 Rx event) Config */

DMA_DeInit(DMA1_Channel5);

DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;

DMA_InitStructure.DMA_MemoryBaseAddr = (u32)PACKET_DATA;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

DMA_InitStructure.DMA_BufferSize = GD_MAX_PACKET_SIZE;

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA1_Channel5, &DMA_InitStructure);

........

USART_DMACmd(USART1, USART_DMAReq_Rx , ENABLE);

/* Enable DMA1 Channel5 */

DMA_Cmd(DMA1_Channel5, ENABLE);

/* Enable the USART1 Receive Interrupt */

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

while(1) {

if ( g_blReadCommand == TRUE ){

// MakeResponse ();

// SendResponse();

// ReadCommand();

g_blReadCommand = FALSE;

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

}

}

}

I hope your help. happy to you.

st3
Associate II
Posted on May 17, 2011 at 12:47

Quote:

I think that reception of command buffer from pc program without using DMA is impossible.

really?

No - of course not!

You can certainly receive from a PC without DMA - the IAP Bootloader App Note does exactly that!

Of course, you'd have to keep the buffer down to a ''reasonable'' size - but, again, the IAP Bootloader App Note works perfectly well with 1K X/Y-Modem blocks at 115200 baud...

jki79ros81
Associate II
Posted on May 17, 2011 at 12:47

Hello st7,

Thank you very for an idea. You are right, but it seem to be complex.

I finaly implemented an idea by DMA.

void DMA_Channel5_Configuration(void)

{

DMA_InitTypeDef DMA_InitStructure;

/* DMA1 Channel5 (triggered by USART1 Rx event) Config */

DMA_DeInit(DMA1_Channel5);

DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;

DMA_InitStructure.DMA_MemoryBaseAddr = (u32)PACKET_DATA;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

DMA_InitStructure.DMA_BufferSize = GD_MAX_PACKET_SIZE;

.........

DMA_Init(DMA1_Channel5, &DMA_InitStructure);

}

void ReadCommand()

{

............

/* Enable USART1 DMA RX request */

USART_DMACmd(USART1, USART_DMAReq_Rx , ENABLE);

/* Enable USART1 Transmit interrupt */

while(DMA_GetFlagStatus(DMA1_FLAG_TC5) == RESET);

DMA_ClearFlag(DMA1_FLAG_TC5);

g_blReadCommand = TRUE;

}

PC Program is following.

BOOL SendCmdPacket()

{

DWORD w_nSendCnt = 0;

LONG w_nResult = 0;

WORD w_nSize = 0;

w_nSize = GetCommandLength();

//w_nResult = m_ClaSerial.Write(m_Packet, w_nSize + 6, &w_nSendCnt, NULL, GD_COMM_TIMEOUT_FP_NON_DELAY);

w_nResult = SerialWrite(m_Packet, GD_MAX_PACKET_SIZE, &w_nSendCnt, NULL, timeout);

...........

return TRUE;

}

But there is an problem. I can't predict length of command.

When the application send a command as it's length then not reached to statement (g_blReadCommand = TRUE;)

Only by sending buffer of length GD_MAX_PACKET_SIZE, the reading was completed.

If GD_MAX_PACKET_SIZE = 500 and length of a command =16, then unavoidably must send extra empty data as 500-16.

It is not efficient and communication speed very slow.

Please help me.

Thank you.

[ This message was edited by: jki79ros81 on 16-10-2008 18:17 ]