cancel
Showing results for 
Search instead for 
Did you mean: 

USART Interrupts in STM32F103C8

markbell9
Associate II
Posted on August 03, 2011 at 13:50

Hello --

We're having difficulity getting USART1 and USART2 interrupts to work.

We can successfully transmit from either USART  but can not receive on either USART via interrupt notification.  Polling the USART for receive shows the data is being correctly received by the USART.

We are concentrating on USART1 for now.    With all USART1 interrupts disabled,  we never enter the USART1 interrupt handler, as expected.

When we enable the RXNE interrupt,  we always enter the USART1 interrupt,  but nothing is connected to the USART1 RX line.   Furthermore, within the ISR handler,  we're testing to see which interrupt occurred ( ORE, RXNE, TXE, TC, CTS, LBD, IDLE ,NE ,PE),  and none are active !!   This is expected as only the RXNE is enabled, but yet something is causing the USART1 handler to get called and we can't figure out what is triggering the interrupt.

Our USART1 initialization is as follows:

    USART_InitStructure.USART_BaudRate = 460800;

    USART_InitStructure.USART_WordLength = USART_WordLength_8b;

    USART_InitStructure.USART_StopBits = USART_StopBits_1;

    USART_InitStructure.USART_Parity = USART_Parity_No;

    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

    USART_InitStructure.USART_HardwareFlowControl =     USART_HardwareFlowControl_None;

    USART_Init(USART1, &USART_InitStructure);

    /* Enable Overrun Error Interrupt */

    USART_ITConfig(USART1, USART_IT_ORE, DISABLE);

    /* Enable USART1 Receive Data Read To Be Read Interrupt */

    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

    /* Disable USART1 Transmit Data Register Empty Interrupt */

    USART_ITConfig(USART1, USART_IT_TXE, DISABLE);

    /* Enable USART1 Transmission Complete Interrupt */

    USART_ITConfig(USART1, USART_IT_TC, DISABLE);

    USART_ITConfig(USART1, USART_IT_CTS, DISABLE);

    USART_ITConfig(USART1, USART_IT_LBD, DISABLE);

    USART_ITConfig(USART1, USART_IT_IDLE, DISABLE);

    USART_ITConfig(USART1, USART_IT_PE, DISABLE);

    USART_ITConfig(USART1, USART_IT_ERR, DISABLE);

    /* Enable USART1 */

    USART_Cmd(USART1, ENABLE);

Our ISR is pretty basic.  For RXNE we have

    //Data available in the Read Register.

    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)

    {

        //Clear pending bit and read the data.

        USART_ClearITPendingBit(USART1, USART_IT_RXNE);

    }

This snipppet is replicated for ORE,TXE,TC,CTS,LBD,IDLE,NE, and PE.

Interrupt initialization is

  /* Enable the USART1 Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

  /* Enable the USART2 Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

Update to original post:

The culprit seems to be

USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;

USART_ClockInit(USART1, &USART_ClockInitStructure);

The ISR does NOT get called if the ClockInit function is commented out,  yet the clock is disabled (as we're not using the USART clock (pins).

Any ideas?

Thanks

Mark

#stm32-usart
4 REPLIES 4
Posted on August 03, 2011 at 17:51

Doesn't reading the data register implicitly clear the RXNE interrupt?

I always look at the status register, for RXNE and the errors (ORE/NE/FE/PE), read the data register, and log the error(s), in the interrupt.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
markbell9
Associate II
Posted on August 03, 2011 at 21:40

Yes, reading the DR will clear the RXNE interrupt.

We want the RXNE interrupt to inform us to to read the DR first, and we can't get the interrupt to work.    Once it interrupts us and we see RXNE set in the Status Register,  we'll read the DR.

Posted on August 04, 2011 at 01:21

Can't say I've had any problems with getting multiple USARTs to work with interrupts, or DMA.

Enable the RCC and GPIO clocks. Enable USART clock(s).

Set up the NVIC priority group, then the interrupts, ideally at unique levels.

Enable the USART before enabling the USART Interrupts, probably not required, but recommended.

The RXNE will not fire if reception errors are pending. You have to read the data register to clear them.

If you fail to service the interrupt(s) pending the Cortex M3 will not run any user space code. It will stick in the interrupt, endlessly tail-chaining. This is particularly important with TXE, which must be disable if no characters are available, and re-enabled when data becomes available.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
aaron
Associate II
Posted on June 28, 2014 at 16:28

The forums just ate a longer and better explained version of this post, but here goes:

I realize that the original author has probably long since moved on, but since I encountered a seemingly identical problem, here is my solution:

Make sure that you do not allow a debugger to read the USART registers.  If the debugger automatically polls the data register, this will clear RXNE and your code will never see it.  In Keil uVision, I can make my USART reads stall out simply by opening the peripheral register viewer (i.e. to look at RXNE), but if I leave it closed, then everything works fine.