cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 USART synchronous mode receive does not work

Fr4nky
Associate II

Hello,

I am using a STM32L052K6U6 to communicate with an SPI slave using the UART1 synchronous mode (configured with CubeMX, using the LL library).

This is part of the code that receives data:

while(!LL_USART_IsActiveFlag_TXE(USART1));

LL_USART_TransmitData8(USART1, 0);

while(!LL_USART_IsActiveFlag_BUSY(USART1));

while(LL_USART_IsActiveFlag_BUSY(USART1));

uint8_t data_1 = LL_USART_ReceiveData8(USART1);

Probing the bus reveals that the clock generation and data sending works fine and the slave responds with the expected data. The receiver is enabled, but the data is not received by the microcontroller. The receive data register and the RXNE flag stay zero.

Does anyone know what could cause this?

Thanks and Kind Regards

Daniel

5 REPLIES 5
Alex R
Senior

Have you enable the USART1 Receive?

Yes, it gets enabled and ​I verified that it is turned on using the register viewer in the debugger.

Fr4nky
Associate II

I figured out a solution, but I don't know why it works.

There are some writes for initialization (max30003_init gets called once) and then repeated read sequences (max30003_readReg gets called regularly). 

The writing has always worked but receiving data (and the RXNE flag getting set) only works when disabling and then reenabling the USART after the initialization writes. Without it the program gets stuck waiting for RXNE to get set.

With this, the RXNE flag gets set as expected and the received data actually makes it to the receive data regster.

Complete code:

void max30003_init(void)
{
	LL_GPIO_SetOutputPin(ECG_CS_GPIO_Port, ECG_CS_Pin);
 
	LL_USART_Disable(USART1);
	LL_USART_SetTransferBitOrder(USART1, LL_USART_BITORDER_MSBFIRST);
	LL_USART_Enable(USART1);
 
	LL_TIM_EnableCounter(TIM22);
	LL_TIM_CC_EnableChannel(TIM22, LL_TIM_CHANNEL_CH1); //32.7...kHz FCLK
 
	max30003_writeReg(REG_SW_RST,0x000000); //reset
 
	delay_ms(10);
 
	max30003_writeReg(REG_CNFG_GEN, 0x081007);
	max30003_writeReg(REG_CNFG_CAL, 0x720000);
	max30003_writeReg(REG_CNFG_EMUX,0x0B0000);
	max30003_writeReg(REG_CNFG_ECG, 0x805000);
 
	max30003_writeReg(REG_CNFG_RTOR1,0x3fc600);
	max30003_writeReg(REG_SYNCH,0x000000);
 
	//FIXME: receive doesn't work without this!?
	LL_USART_Disable(USART1);
	LL_USART_Enable(USART1);
 
	delay_ms(10);
}
 
uint32_t max30003_readReg(uint8_t reg)
{
	while(LL_USART_IsActiveFlag_BUSY(USART1));
	while(!LL_USART_IsActiveFlag_TXE(USART1));
 
	LL_GPIO_ResetOutputPin(ECG_CS_GPIO_Port, ECG_CS_Pin);
 
	LL_USART_TransmitData8(USART1, ((reg << 1) | READ));
	while(!LL_USART_IsActiveFlag_RXNE(USART1));
	LL_USART_RequestRxDataFlush(USART1); //clear RXNE
 
	LL_USART_TransmitData8(USART1, 0);
	while(!LL_USART_IsActiveFlag_RXNE(USART1));
	uint8_t data_2 = LL_USART_ReceiveData8(USART1);
 
	LL_USART_TransmitData8(USART1, 0);
	while(!LL_USART_IsActiveFlag_RXNE(USART1));
	uint8_t data_1 = LL_USART_ReceiveData8(USART1);
 
	LL_USART_TransmitData8(USART1, 0);
	while(!LL_USART_IsActiveFlag_RXNE(USART1));
	uint8_t data_0 = LL_USART_ReceiveData8(USART1);
 
	LL_GPIO_SetOutputPin(ECG_CS_GPIO_Port, ECG_CS_Pin);
 
	return ((data_2 << 16) | (data_1 << 8) | data_0);
}
 
void max30003_writeReg(uint8_t reg, uint32_t data)
{
	while(LL_USART_IsActiveFlag_BUSY(USART1));
	while(!LL_USART_IsActiveFlag_TXE(USART1));
 
	LL_GPIO_ResetOutputPin(ECG_CS_GPIO_Port, ECG_CS_Pin);
 
	LL_USART_TransmitData8(USART1, ((reg << 1) | WRITE));
	while(!LL_USART_IsActiveFlag_TXE(USART1));
 
	LL_USART_TransmitData8(USART1, (uint8_t)(data >> 16));
	while(!LL_USART_IsActiveFlag_TXE(USART1));
 
	LL_USART_TransmitData8(USART1, (uint8_t)(data >> 8));
	while(!LL_USART_IsActiveFlag_TXE(USART1));
 
	LL_USART_TransmitData8(USART1, (uint8_t)data);
	while(!LL_USART_IsActiveFlag_TC(USART1));
 
	LL_GPIO_SetOutputPin(ECG_CS_GPIO_Port, ECG_CS_Pin);
}

I have no idea why the USART disable pulse is needed. Does anyone have any ideas?

Perhaps you have some pending error state in the UART that needs to be cleared​ before RX works again? ie Overrun, Noise or Framing, etc.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Fr4nky
Associate II

It was indeed the overrun error bit, disabling the overrun detection solved the problem.

I ignored it until now as I thought it was only a status bit that has no influence on the functionality but the reference manual explains it in a note:

"When this bit is set, the RDR register content is not lost but the shift register is overwritten." No new RDR data also means the RXNE flag doesn't get set.

Thanks for the help!