2020-07-24 10:35 AM
Hi,
Board details : NUCLEO64 - G071RBTX
I am trying to understand Receive timeout interrupt for implementation of Modbus RTU using USART2. As a start, to check the receive timeout interrupt, i want to check with a 2 seconds timeout interrupt. So configured the RTOR register accordingly below (Please guide if i configured wrong)
===
USART2 CONFIGURATIONS:
BAUD=19200
All other bits at default
===
Steps I used additionally after code generation (HAL) Below steps are written after HAL configures the USART2.
Calculation for RTOR = (2000000/ 0.520833). I refered the calculation from here
static void MX_USART2_UART_Init(void)
{
/* USER CODE BEGIN USART2_Init 0 */
/* USER CODE END USART2_Init 0 */
/* USER CODE BEGIN USART2_Init 1 */
/* USER CODE END USART2_Init 1 */
huart2.Instance = USART2;
huart2.Init.BaudRate = 19200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART2_Init 2 */
//By default Receive interrupt is not enabled
//Enable Receive interrupt and receive timeout of USART2
USART2->CR1 |=(1<<26U) | (1<<5U);
USART2->CR2 |=(1<<23U); //RECEIVER TIMEOUT ENABLE
USART2->RTOR=3840002u;
/* USER CODE END USART2_Init 2 */
}
Finally in USART2 IRQ handler below is the code:
One more thing in the IRQ handler, i checked with each bit. Is this the correct method?
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
if((USART2->ISR && 32u))
{
unsigned char test=USART2->RDR;
//USART2->ICR |=(1<<11u); //CLEAR RTOF BIT
}
else if ((USART2->ISR && 2048u))
{
//ENTERED RTOF
unsigned char tester;
tester=0u;
USART2->ICR |=(1<<11u); //CLEAR RTOF BIT
}
/* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
/* USER CODE END USART2_IRQn 1 */
}
Interrupt does not occur after about 2 seconds. Please guide me.
Solved! Go to Solution.
2020-07-24 01:20 PM
Are you sure this is correct?
if((USART2->ISR && 32u))
{
//...//
}
else if ((USART2->ISR && 2048u))
{
}
Maybe that's what you meant
if((USART2->ISR & 32u))
{
//...//
}
else if ((USART2->ISR & 2048u))
{
}
This is my procedure for continuously receiving a sequence of characters.
static uint8_t _RxChar;
static void _receiveAgain(UART_HandleTypeDef *uart_ptr);
/// initialization
void begin (UART_HandleTypeDef *uart_ptr)
{
//.....//
// 1st time
_receiveAgain(uart_ptr);
}
/// override `HAL_UART_RxCpltCallback`
extern "C" void HAL_UART_RxCpltCallback(UART_HandleTypeDef *uart_ptr)
{
assert(uart_ptr);
// isr code here...
// the received character is in `_RxChar`
_receiveAgain(uart_ptr);
}
/// override `HAL_UART_TxCpltCallback`
extern "C" void HAL_UART_ErrorCallback(UART_HandleTypeDef * uart_ptr)
{
assert(uart_ptr);
auto err = HAL_UART_GetError(uart_ptr);
if (err & (HAL_UART_ERROR_ORE | HAL_UART_ERROR_FE | HAL_UART_ERROR_NE | HAL_UART_ERROR_PE))
{
__HAL_UART_CLEAR_FLAG(uart_ptr, UART_IT_ERR);
//
// isr code here...
//
_receiveAgain(uart_ptr); // receive again
}
}
static void _receiveAgain(UART_HandleTypeDef *uart_ptr)
{
assert(uart_ptr);
uart_ptr->pRxBuffPtr = &_RxChar;
uart_ptr->RxXferSize = 1;
uart_ptr->RxXferCount = 1;
uart_ptr->ErrorCode = HAL_UART_ERROR_NONE;
// Check if a transmit process is ongoing or not
if (uart_ptr->RxState == HAL_UART_STATE_BUSY_TX) uart_ptr->RxState = HAL_UART_STATE_BUSY_TX_RX;
else uart_ptr->RxState = HAL_UART_STATE_BUSY_RX;
__HAL_UNLOCK(uart_ptr);
__HAL_UART_ENABLE_IT(uart_ptr, UART_IT_PE);
__HAL_UART_ENABLE_IT(uart_ptr, UART_IT_ERR);
__HAL_UART_ENABLE_IT(uart_ptr, UART_IT_RXNE);
}
2020-07-24 11:24 AM
RTO interrupt occurs only after at least one byte is received. If no data has been received during specified time, this interrupt won't trigger.
Usually you want to use RTO interrupt together with DMA.
RXNE interrupt lets you to receive and handle incoming data as soon as possible.
On the opposite, the purpose of RTO is to delay handling of the data until RX ends.
And DMA stores received data with minimal latency. Meanwhile the CPU is free for other tasks.
So you don't need RXNE and RTO interrupts together, unless you want something more complicated.
-- pa
2020-07-24 01:20 PM
Are you sure this is correct?
if((USART2->ISR && 32u))
{
//...//
}
else if ((USART2->ISR && 2048u))
{
}
Maybe that's what you meant
if((USART2->ISR & 32u))
{
//...//
}
else if ((USART2->ISR & 2048u))
{
}
This is my procedure for continuously receiving a sequence of characters.
static uint8_t _RxChar;
static void _receiveAgain(UART_HandleTypeDef *uart_ptr);
/// initialization
void begin (UART_HandleTypeDef *uart_ptr)
{
//.....//
// 1st time
_receiveAgain(uart_ptr);
}
/// override `HAL_UART_RxCpltCallback`
extern "C" void HAL_UART_RxCpltCallback(UART_HandleTypeDef *uart_ptr)
{
assert(uart_ptr);
// isr code here...
// the received character is in `_RxChar`
_receiveAgain(uart_ptr);
}
/// override `HAL_UART_TxCpltCallback`
extern "C" void HAL_UART_ErrorCallback(UART_HandleTypeDef * uart_ptr)
{
assert(uart_ptr);
auto err = HAL_UART_GetError(uart_ptr);
if (err & (HAL_UART_ERROR_ORE | HAL_UART_ERROR_FE | HAL_UART_ERROR_NE | HAL_UART_ERROR_PE))
{
__HAL_UART_CLEAR_FLAG(uart_ptr, UART_IT_ERR);
//
// isr code here...
//
_receiveAgain(uart_ptr); // receive again
}
}
static void _receiveAgain(UART_HandleTypeDef *uart_ptr)
{
assert(uart_ptr);
uart_ptr->pRxBuffPtr = &_RxChar;
uart_ptr->RxXferSize = 1;
uart_ptr->RxXferCount = 1;
uart_ptr->ErrorCode = HAL_UART_ERROR_NONE;
// Check if a transmit process is ongoing or not
if (uart_ptr->RxState == HAL_UART_STATE_BUSY_TX) uart_ptr->RxState = HAL_UART_STATE_BUSY_TX_RX;
else uart_ptr->RxState = HAL_UART_STATE_BUSY_RX;
__HAL_UNLOCK(uart_ptr);
__HAL_UART_ENABLE_IT(uart_ptr, UART_IT_PE);
__HAL_UART_ENABLE_IT(uart_ptr, UART_IT_ERR);
__HAL_UART_ENABLE_IT(uart_ptr, UART_IT_RXNE);
}
2020-07-24 01:43 PM
I hope I was useful