Getting Started with STM32F103: UART Receiver in interrupt mode

In the previous guide (here), we took a look at how to receive a character using polling mode. In this guide, we shall use interrupt to receive the data.

In this guide, we shall cover the following:

  • Enable RX in interrupt mode.
  • Interrupt handler.
  • Code.
  • Demo.

1. Enable RX in interrupt mode:

In order to enable the RX in interrupt mode, we need the following two steps:

  • Enable RXNEIE in Control Register 1 (CR1).
  • Enable UART2 interrupt in NVIC.

To enable the RXNEIE for the UART, we need to set the RXNEIE bit in CR1 to 1:

/*Enable RXNIE interrupt*/
USART2->CR1|=USART_CR1_RXNEIE;

Then enable USART2 interrupt in NVIC:

	/*Enable USART2 interrupt in NVIC*/
	NVIC_EnableIRQ(USART2_IRQn);

Thats all to enable interrupt.

2. Interrupt handler:

Within the interrupt handler, we shall implement the following sequence:

  • Check if the interrupt source is RXNE.
  • If it is, Read the register.
  • Echo back the character.
  • Print new line and return the cursor.
  • Clear the status register.

For the main Interrupt handler, the function as follows:

void USART2_IRQHandler(void)

Within the function:

  • Check if the interrupt source is RXNE as following:
	/*Check the interrupt source*/
	if((USART2->SR&USART_SR_RXNE)) /*Received a character*/
	{

Read the character:

rx_char=USART2->DR; //Read the character

Echo back the character:

uart2_write(rx_char); //echo back the character

Print newline and return the cursor:

/*print new line and return the cursor*/
		uart2_write('\r');
		uart2_write('\n');

Clear the pending flag:

		USART2->SR&=~USART_SR_RXNE;

	}

3. Code:

Hence, the entire code as following:

#include "stm32f1xx.h"



#define Perpher_CLK 8000000
#define Baudrate	115200



static uint16_t compute_uart_bd(uint32_t PeriphClk, uint32_t BaudRate)
{
	return ((PeriphClk + (BaudRate/2U))/BaudRate);
}


static void uart_set_baudrate(USART_TypeDef *USARTx, uint32_t PeriphClk,  uint32_t BaudRate)
{
	USARTx->BRR =  compute_uart_bd(PeriphClk,BaudRate);
}





void uart2_write(char ch)
{
  /*Make sure the transmit data register is empty*/
	while(!(USART2->SR & USART_SR_TXE)){}

  /*Write to transmit data register*/
	USART2->DR	=  (ch & 0xFF);
}





volatile char rx_char;



int main(void)
{

	/*UART2 Pin configures*/

	//enable clock access to GPIOA
	RCC->APB2ENR|=RCC_APB2ENR_IOPAEN;
	//Enable clock access to alternate function
	RCC->APB2ENR|=RCC_APB2ENR_AFIOEN;

	/*Confgiure PA2 as output maximum speed to 50MHz
	 * and alternate output push-pull mode*/
	GPIOA->CRL|=GPIO_CRL_MODE2;

	GPIOA->CRL|=GPIO_CRL_CNF2_1;
	GPIOA->CRL&=~GPIO_CRL_CNF2_0;


	/*Configure PA3 as Input floating*/

	/*Set mode to be input*/
	GPIOA->CRL &=~(GPIO_CRL_MODE3);
	GPIOA->CRL|=GPIO_CRL_CNF3_0;
	GPIOA->CRL&=~GPIO_CRL_CNF3_1;




	/*Don't remap the pins*/
	AFIO->MAPR&=~AFIO_MAPR_USART2_REMAP;


	/*USART2 configuration*/

	//enable clock access to USART2

	RCC->APB1ENR|=RCC_APB1ENR_USART2EN;

	//Transmit Enable
	USART2->CR1 |= USART_CR1_TE;

	//Enable receiver
	USART2->CR1 |= USART_CR1_RE;


	/*Enable RXNIE interrupt*/

	USART2->CR1|=USART_CR1_RXNEIE;

	/*Enable USART2 interrupt in NVIC*/
	NVIC_EnableIRQ(USART2_IRQn);

	/*Set baudrate */
	uart_set_baudrate(USART2,Perpher_CLK,Baudrate);
	//Enable UART
	USART2->CR1 |= USART_CR1_UE;



	while(1)
	{



	}
}


void USART2_IRQHandler(void)
{
	/*Check the interrupt source*/
	if((USART2->SR&USART_SR_RXNE)) /*Received a character*/
	{
		rx_char=USART2->DR; //Read the character
		uart2_write(rx_char); //echo back the character
		/*print new line and return the cursor*/
		uart2_write('\r');
		uart2_write('\n');
		/*Clear the pending RXNE flag*/
		USART2->SR&=~USART_SR_RXNE;

	}

}

4. Demo:

Open you favourite serial terminal and set the buadrate to be 115200 and send any character and you should receive the same sent character:

Happy coding 🙂

Add Comment

Your email address will not be published. Required fields are marked *