
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:
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