cancel
Showing results for 
Search instead for 
Did you mean: 

UART interrupt switch between USART_CR1_PEIE | USART_CR1_RXNEIE and USART_CR1_CMIE

Wleon.1
Associate II

Hi, just want to know if it is possible to switch the interrupt between Character match and Each character received interrupt on the fly without stopping the UART ?

2 REPLIES 2

Which STM32?

Regardless of that, IMO yes.

JW

STM32F7xx:

/**
  * @brief RX interrrupt handler for 7 or 8 bits data word length .
  * @param huart UART handle.
  * @retval None
  */
static void UART_RxISR_8BIT_CC(UART_HandleTypeDef *huart)
{
  uint16_t uhMask = huart->Mask;
  uint16_t  uhdata;
 
  /* Check that a Rx process is ongoing */
  if (huart->RxState == HAL_UART_STATE_BUSY_RX)
  {
    uhdata = (uint16_t) READ_REG(huart->Instance->RDR);
    *huart->pRxBuffPtr = (uint8_t)(uhdata & (uint8_t)uhMask);
    huart->pRxBuffPtr++;
    huart->RxXferCount--;
 
    if (huart->RxXferCount == 0U)
    {
      /* Disable the UART Parity Error Interrupt and RXNE interrupts */
      CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_CMIE));
 
      /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
      CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
 
      /* Rx process is completed, restore huart->RxState to Ready */
      huart->RxState = HAL_UART_STATE_READY;
 
      /* Clear RxISR function pointer */
      huart->RxISR = NULL;
 
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
      /*Call registered Rx complete callback*/
      huart->RxCpltCallback(huart);
#else
      /*Call legacy weak Rx complete callback*/
      HAL_UART_RxCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
    }
  }
  else
  {
    /* Clear RXNE interrupt flag */
    __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
  }
}
 
/**
  * @brief RX interrrupt handler for 9 bits data word length .
  * @note   Function is called under interruption only, once
  *         interruptions have been enabled by HAL_UART_Receive_IT()
  * @param huart UART handle.
  * @retval None
  */
static void UART_RxISR_16BIT_CC(UART_HandleTypeDef *huart)
{
  uint16_t *tmp;
  uint16_t uhMask = huart->Mask;
  uint16_t  uhdata;
 
  /* Check that a Rx process is ongoing */
  if (huart->RxState == HAL_UART_STATE_BUSY_RX)
  {
    uhdata = (uint16_t) READ_REG(huart->Instance->RDR);
    tmp = (uint16_t *) huart->pRxBuffPtr ;
    *tmp = (uint16_t)(uhdata & uhMask);
    huart->pRxBuffPtr += 2U;
    huart->RxXferCount--;
 
    if (huart->RxXferCount == 0U)
    {
      /* Disable the UART Parity Error Interrupt and RXNE interrupt*/
      CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_CMIE));
 
      /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
      CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
 
      /* Rx process is completed, restore huart->RxState to Ready */
      huart->RxState = HAL_UART_STATE_READY;
 
      /* Clear RxISR function pointer */
      huart->RxISR = NULL;
 
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
      /*Call registered Rx complete callback*/
      huart->RxCpltCallback(huart);
#else
      /*Call legacy weak Rx complete callback*/
      HAL_UART_RxCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
    }
  }
  else
  {
    /* Clear RXNE interrupt flag */
    __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
  }
}
 
HAL_StatusTypeDef HAL_UART_Receive_IT_CC(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  /* Check that a Rx process is not already ongoing */
  if (huart->RxState == HAL_UART_STATE_READY)
  {
    if ((pData == NULL) || (Size == 0U))
    {
      return HAL_ERROR;
    }
 
    __HAL_LOCK(huart);
 
    huart->pRxBuffPtr  = pData;
    huart->RxXferSize  = Size;
    huart->RxXferCount = Size;
    huart->RxISR       = NULL;
 
    /* Computation of UART mask to apply to RDR register */
    UART_MASK_COMPUTATION(huart);
 
    huart->ErrorCode = HAL_UART_ERROR_NONE;
    huart->RxState = HAL_UART_STATE_BUSY_RX;
 
    /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
    SET_BIT(huart->Instance->CR3, USART_CR3_EIE);
 
    /* Set the Rx ISR function pointer according to the data word length */
    if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
    {
      huart->RxISR = UART_RxISR_16BIT_CC;
    }
    else
    {
      huart->RxISR = UART_RxISR_8BIT_CC;
    }
 
    __HAL_UNLOCK(huart);
 
    /* Enable the UART Parity Error interrupt and Data Register Not Empty interrupt */
    SET_BIT(huart->Instance->CR1, USART_CR1_CMIE);
 
    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}
 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
static int strCnt = 0;
static char TimeStr[10] = {0};
  if (huart->Instance == UART7){
 
    /* search for GNRMC */
    switch (strCnt){
    case 0:
        if(uartbuf[0] == 'G'){
            strCnt++;
            goto NormalIntend;
        }else{
            strCnt = 0;
            goto CCIntend;
 
        }
        break;
    case 1:
        if(uartbuf[0] == 'N'){
            strCnt++;
            goto NormalIntend;
        }else{
            strCnt = 0;
            goto CCIntend;
 
        }
        break;
    case 2:
        if(uartbuf[0] == 'R'){
            strCnt++;
            goto NormalIntend;
        }else{
            strCnt = 0;
            goto CCIntend;
 
        }
        break;
    case 3:
        if(uartbuf[0] == 'M'){
            strCnt++;
            goto NormalIntend;
        }else{
            strCnt = 0;
            goto CCIntend;
 
        }
        break;
    case 4:
        if(uartbuf[0] == 'C'){
            strCnt++;
            goto NormalIntend;
        }else{
            strCnt = 0;
            goto CCIntend;
 
        }
        break;
    case 5:
    case 6:
    case 7:
    case 8:
    case 9:
    case 10:
    case 11:
    case 12:
    case 13:
        if(strCnt > 5){
            CLEAR_BIT(huart7.Instance->CR1, USART_CR1_CMIE);
            TimeStr[strCnt-6] = uartbuf[0]; 
        }
 
        if(strCnt-6 == 7){
            TimeStr[6] = '\0';
            GPStime = atoi(TimeStr);
            GPSStart = 1;
            strCnt = 0;
            goto CCIntend;
        }
        strCnt++; 
        break;
    default:
        strCnt = 0;
        goto CCIntend;
        break;
    }
 
    
 
    goto NormalIntend;
 
NormalIntend:         
    huart7.Instance->ICR |= 1 << 17;  
    HAL_UART_Receive_IT(&huart7, uartbuf, 1);
    return;
 
CCIntend:   
    huart7.Instance->ICR |= 1 << 17;  
    HAL_UART_Receive_IT_CC(&huart7, uartbuf, 1);
 
    return;
 
 
    }
}

The above code is what I use trying to switch between Character match (CC) and normal interrupt, so if the program detect 'G' it will switch to interrupt each character received. however after the switch the UART seems to not generate any interrupt anymore and overflow flag is set and here is the register:

0693W000001skFEQAY.png I thought we just need to set USART_CR1_CMIE and ADD ? am I missing something ?