2019-03-26 03:10 PM
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
2019-03-28 12:58 PM
Have you enable the USART1 Receive?
2019-03-29 12:42 AM
Yes, it gets enabled and I verified that it is turned on using the register viewer in the debugger.
2019-04-15 11:47 AM
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?
2019-04-15 04:18 PM
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.
2019-04-15 04:52 PM
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!