cancel
Showing results for 
Search instead for 
Did you mean: 

need very simple UART RXNE and IDLE interrupt example

krishna2
Associate
Posted on September 08, 2015 at 12:25

Hello,

I've used the STD peripheral libraries before and successfully generating interrupts from UART

//snippet 1
void USART1_IRQHandler(void){
char chee;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){
chee = USART_ReceiveData(USART1);
BTrxString[BTrxPointer++] = chee; //used for something else
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET){
strncpy(EXT_BTrxString, BTrxString, 200); //used for something else
USART_ClearITPendingBit(USART1, USART_IT_IDLE);
BTrxPointer = 0; //used for something else
memset(&BTrxString[0], 0, sizeof(BTrxString)); //used for something else
chee = USART_ReceiveData(USART1);
FLAG_BT_TIMEOUT = 1; //used for something else
}
}

I'm having a hard time understanding how to use HAL and the cubeMX.. I am able to send strings on UART

HAL_UART_Transmit_IT(&huart2, (''lol\n''), strlen(''lol\n''));

no problems at all. the problem is I need to get RXNE and IDLE interrupts. interrupts weren't firing from the cubeMX code. while examining the code generated from cubeMX I had to add the following line in thevoid HAL_UART_MspInit(UART_HandleTypeDef* huart) function. interrupt fires. Is that really required? I'am guessing that it should be done by default by cubeMX software.

__HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE);

I've played around cubeMX EXTI interrupt. I used theHAL_GPIO_EXTI_Callback function to react to button presses. works great no problems.

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
HAL_UART_Transmit_IT(&huart2, (''lol\n''), strlen(''lol\n''));
}

Now the question, can I get a simple example as seen in code snippet 1 to generate interrupts. I've tried something like the snippet 3 code. and fcode would'nt jump into

HAL_UART_RxCpltCallback

woldn't do anything Im definitely sure thats wrong. but when I try to send a UART char from teraterm, the interrupt fires and jumps into code snippet 2.

// snippet 2 
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
/* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
/* USER CODE END USART2_IRQn 1 */
}

the code jumps into the

HAL_UART_IRQHandler as well. and into

HAL_UART_IRQHandler and thenUART_Receive_IT

and returnsHAL_BUSY.

// snippet 3 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
char kk = 'p';
if(__HAL_UART_GET_IT(&huart2, UART_IT_RXNE) != RESET){
HAL_UART_Receive(&huart2, &kk, 1, 10);
HAL_UART_Transmit_IT(&huart2, &kk, 1);
HAL_UART_Transmit_IT(&huart2, ('' \n''), strlen('' \n''));
}
if(__HAL_UART_GET_IT(&huart2, UART_IT_IDLE) != RESET){
HAL_UART_Transmit_IT(&huart2, (''rxi\n''), strlen(''rxi\n''));
__HAL_UART_CLEAR_IT(&huart2, UART_CLEAR_IDLEF);
}
}

Could someone show me a simple HAL UART interrupt example.
  • cooCox IDE 1.7.8
  • cubeMX 4.0
  • GNU Tools ARM Embedded2015q2
  • STM32L053R8T6 onNUCLEO-L053R8 board
#cubemx #stm32 #hal #uart
3 REPLIES 3
Posted on September 09, 2015 at 11:44

Hi panduru.krishna,

Refer to the example under STM32Cube_FW_L0_V1.1.0\Projects\STM32L053R8-Nucleo\Examples\UART\UART_TwoBoards_ComIT, it can help you. Also, you have to know that

__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);

is already called in the fucntion HAL_UART_Receive_IT. Refer to

http://www.st.com/st-web-ui/static/active/jp/resource/technical/document/user_manual/DM001058pdf

, where you can find more explanations about how to use the HAL drivers. -Shahrzad-
krishna2
Associate
Posted on September 09, 2015 at 18:18

Thanks shahrzad,

Ive gone through the UM and examples many times, all I understand is to use HAL_UART_Receive_IT in the main code and keep it in a loop. which I see that as not an interrupt. 

I understand HAL_UART_Receive_IT uses interrupts to work away, but as seen in code snippet 1 I see that as an interrupt because I dont have to keep using a receive_IT function.

Thanks.

julienterrier39
Associate II
Posted on September 10, 2015 at 17:46

Hi,

I'am trying to share according to my own experience with how is enable the interrupt with stm32f4. So if I take as example this function (available inUART_TwoBoards_ComIT):

/**
* @brief Receives an amount of data in non blocking mode
* @param huart: pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @param pData: Pointer to data buffer
* @param Size: Amount of data to be received
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
uint32_t tmp = 0;
tmp = huart->State;
if((tmp == HAL_UART_STATE_READY) || (tmp == HAL_UART_STATE_BUSY_TX))
{
if((pData == NULL ) || (Size == 0))
{
return HAL_ERROR;
}
/* Process Locked */
__HAL_LOCK(huart);
huart->pRxBuffPtr = pData;
huart->RxXferSize = Size;
huart->RxXferCount = Size;
huart->ErrorCode = HAL_UART_ERROR_NONE;
/* Check if a transmit process is ongoing or not */
if(huart->State == HAL_UART_STATE_BUSY_TX)
{
huart->State = HAL_UART_STATE_BUSY_TX_RX;
}
else
{
huart->State = HAL_UART_STATE_BUSY_RX;
}
/* Enable the UART Parity Error Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_PE);
/* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
__HAL_UART_ENABLE_IT(huart, UART_IT_ERR);
/* Process Unlocked */
__HAL_UNLOCK(huart);
/* Enable the UART Data Register not empty Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}

Forget it about USART_STATE just focus on how is enable the interrupt. As you see in this function 3 interrupt is enable: -Enable the UART Parity Error Interrupt -Enable the UART Error Interrupt: (Frame error, noise error, overrun error) -Enable the UART Data Register not empty Interrupt Now let's look at how works this interruptionUART_IT_RXNE. with this line we call this macro:

/** @brief Enable the specified UART interrupt.
* @param __HANDLE__: specifies the UART Handle.
* This parameter can be UARTx where x: 1, 2, 3, 4, 5, 6, 7 or 8 to select the USART or
* UART peripheral.
* @param __INTERRUPT__: specifies the UART interrupt source to enable.
* This parameter can be one of the following values:
* @arg UART_IT_CTS: CTS change interrupt
* @arg UART_IT_LBD: LIN Break detection interrupt
* @arg UART_IT_TXE: Transmit Data Register empty interrupt
* @arg UART_IT_TC: Transmission complete interrupt
* @arg UART_IT_RXNE: Receive Data register not empty interrupt
* @arg UART_IT_IDLE: Idle line detection interrupt
* @arg UART_IT_PE: Parity Error interrupt
* @arg UART_IT_ERR: Error interrupt(Frame error, noise error, overrun error)
* @retval None
*/
#define UART_IT_MASK ((uint32_t)0x0000FFFF)
#define __HAL_UART_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((((__INTERRUPT__) >> 28) == 1)? ((__HANDLE__)->Instance->CR1 |= ((__INTERRUPT__) & UART_IT_MASK)): \
(((__INTERRUPT__) >> 28) == 2)? ((__HANDLE__)->Instance->CR2 |= ((__INTERRUPT__) & UART_IT_MASK)): \
((__HANDLE__)->Instance->CR3 |= ((__INTERRUPT__) & UART_IT_MASK)))

And this macro does ==>An USART interrupt is generated whenever ORE=1 or RXNE=1 in the USART_SRregister (with _INTERRUPT_ =UART_IT_RXNE). And RXNE bitis set by hardware when the content of the RDR shift register has been transferredto the USART_DR register. An interrupt is generated if RXNEIE=1 in the USART_CR1register. According to Ref manual 0090 if RXNE = 1 and RXNEIE = 1 an interrupt occur. When an interrupt occur the Nested Vector Interrupt Controller (NVIC) is used to call this function:

/**
* @brief This function handles UART interrupt request.
* @param huart: pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
uint32_t tmp1 = 0, tmp2 = 0;
tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE);
tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE);
/* UART in mode Receiver ---------------------------------------------------*/
if((tmp1 != RESET) && (tmp2 != RESET))
{
UART_Receive_IT(huart);
}

(I hide the other USART interrupt request), After assertedthe flag and the interrupt RXNE, we execute UART_Receive_IT(huart); function:

/**
* @brief Receives an amount of data in non blocking mode
* @param huart: pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL status
*/
static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
uint16_t* tmp;
uint32_t tmp1 = 0;
tmp1 = huart->State;
if((tmp1 == HAL_UART_STATE_BUSY_RX) || (tmp1 == HAL_UART_STATE_BUSY_TX_RX))
{
if(huart->Init.WordLength == UART_WORDLENGTH_9B)
{
tmp = (uint16_t*) huart->pRxBuffPtr;
if(huart->Init.Parity == UART_PARITY_NONE)
{
*tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x01FF);
huart->pRxBuffPtr += 2;
}
else
{
*tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x00FF);
huart->pRxBuffPtr += 1;
}
}
else
{
if(huart->Init.Parity == UART_PARITY_NONE)
{
*huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
}
else
{
*huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
}
}
if(--huart->RxXferCount == 0)
{
__HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);
/* Check if a transmit process is ongoing or not */
if(huart->State == HAL_UART_STATE_BUSY_TX_RX)
{
huart->State = HAL_UART_STATE_BUSY_TX;
}
else
{
/* Disable the UART Parity Error Interrupt */
__HAL_UART_DISABLE_IT(huart, UART_IT_PE);
/* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
__HAL_UART_DISABLE_IT(huart, UART_IT_ERR);
huart->State = HAL_UART_STATE_READY;
}
HAL_UART_RxCpltCallback(huart);
return HAL_OK;
}
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}

One element interested us here: -HAL_UART_RxCpltCallback(huart);

/**
* @brief Rx Transfer completed callbacks.
* @param huart: pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_UART_TxCpltCallback could be implemented in the user file
*/
}

This function as indicated could be implemented in the user/main file according the needs of your application. To finish along of this message I tried to describe how is used the interrupt with the STM32F4 cube driver. If you meet any mistake sorry by advance...