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