{"id":1509,"date":"2023-02-01T04:26:55","date_gmt":"2023-02-01T04:26:55","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=1509"},"modified":"2023-02-01T04:26:58","modified_gmt":"2023-02-01T04:26:58","slug":"getting-started-with-stm32f103-uart-receiver-with-dma-and-idle","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=1509","title":{"rendered":"Getting Started with STM32F103: UART Receiver with DMA and IDLE"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"724\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/AdobeStock_316544570-1-2048x1448-1-1024x724.jpeg\" alt=\"\" class=\"wp-image-1510\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/AdobeStock_316544570-1-2048x1448-1-1024x724.jpeg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/AdobeStock_316544570-1-2048x1448-1-300x212.jpeg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/AdobeStock_316544570-1-2048x1448-1-768x543.jpeg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/AdobeStock_316544570-1-2048x1448-1-1536x1086.jpeg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/AdobeStock_316544570-1-2048x1448-1-1150x813.jpeg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/AdobeStock_316544570-1-2048x1448-1-750x530.jpeg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/AdobeStock_316544570-1-2048x1448-1-400x283.jpeg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/AdobeStock_316544570-1-2048x1448-1-250x177.jpeg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/AdobeStock_316544570-1-2048x1448-1.jpeg 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n\n<p>In the previous guide (<a href=\"https:\/\/blog.embeddedexpert.io\/?p=1504\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=1504\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>), we took a look how to configure the UART to transmit and receive data to\/from PC using DMA. The limitation that we shall wait until the buffer is filled before we print the the received characters. In this guide, we shall use IDLE Line interrupt to receive unknown length of characters.<\/p>\n\n\n\n<p>In this guide, we shall cover the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>What is IDLE line.<\/li><li>Configure UART for IDLE interrupt.<\/li><li>Support functions.<\/li><li>Code.<\/li><li>Demo.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">1. What is IDLE Line:<\/h2>\n\n\n\n<p>The use of IDLE is mostly related to&nbsp;<em>synchronous<\/em>&nbsp;communications (although you could use this concepts in asynchronous mode as well).<\/p>\n\n\n\n<p>Because there is a continuous bitstream flowing on the line in synchronous mode, there is no way to send&nbsp;<em>nothing<\/em>&nbsp;\u2013 To be able to do that, the IDLE pattern (normally all ones) is often used. It simply means there is no data on the line.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. Configure UART for IDLE interrupt:<\/h2>\n\n\n\n<p>In order to enable IDLE line interrupt for UART, we need to set the IDLEIE bit in CR1:<\/p>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"320\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-01-at-7.18.44-AM-1024x320.png\" alt=\"\" class=\"wp-image-1511\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-01-at-7.18.44-AM-1024x320.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-01-at-7.18.44-AM-300x94.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-01-at-7.18.44-AM-768x240.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-01-at-7.18.44-AM-1536x480.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-01-at-7.18.44-AM-1150x360.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-01-at-7.18.44-AM-750x235.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-01-at-7.18.44-AM-400x125.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-01-at-7.18.44-AM-250x78.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-01-at-7.18.44-AM.png 1982w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">USART2-&gt;CR1|=USART_CR1_IDLEIE;<\/pre><\/div>\n\n\n\n<p>Then enable USART2 interrupt in the NVIC as following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\t\/*Enable USART2 interrupt in NVIC*\/\n\tNVIC_EnableIRQ(USART2_IRQn);<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>For the interrupt handler:<\/p>\n\n\n\n<p>The following is performed:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Check if the source is the IDLE line.<\/li><li>If it is, set idle variable to 1<\/li><li>Clear the flag by reading the DR register.<\/li><\/ul>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">void USART2_IRQHandler(void)\n{\n\tif (USART2-&gt;SR &amp; USART_SR_IDLE)\n\t\t{\n\n\t\t\tidle=1;\n\t\t\t\/*Clearing sequence:\n\t\t\t * Read the SR register (Already done in if condition)\n\t\t\t * Read the DR register\n\t\t\t * *\/\n\t\t\t(void)USART2-&gt;DR;\n\t\t}\n}\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Support Function:<\/h2>\n\n\n\n<p>The support function is reseting the buffer. The following is used to reset the buffer:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Disable the DMA.<\/li><li>Set the buffer to NULL using memset.<\/li><li>Reload the buffer to the DMA.<\/li><li>Enable the DMA again.<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">void reset_buffer()\n{\n\t\/*Disable DMA*\/\n\tDMA1_Channel6-&gt;CCR&amp;=~DMA_CCR_EN;\n\twhile((DMA1_Channel6-&gt;CCR) &amp;DMA_CCR_EN);\n\tmemset(rc_data, 0, rc_data_size);\n\tDMA1_Channel6-&gt;CNDTR=rc_data_size;\n\tDMA1_Channel6-&gt;CCR|=DMA_CCR_EN;\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. Code:<\/h2>\n\n\n\n<p>The code as following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">#include &quot;stm32f1xx.h&quot;\n#include &quot;stdio.h&quot;\n#include &quot;string.h&quot;\n\n\n#define Perpher_CLK 8000000\n#define Baudrate\t115200\n\n\n\nstatic uint16_t compute_uart_bd(uint32_t PeriphClk, uint32_t BaudRate)\n{\n\treturn ((PeriphClk + (BaudRate\/2U))\/BaudRate);\n}\n\n\nstatic void uart_set_baudrate(USART_TypeDef *USARTx, uint32_t PeriphClk,  uint32_t BaudRate)\n{\n\tUSARTx-&gt;BRR =  compute_uart_bd(PeriphClk,BaudRate);\n}\n\n\n\n\n\nvoid uart2_write(int ch)\n{\n  \/*Make sure the transmit data register is empty*\/\n\twhile(!(USART2-&gt;SR &amp; USART_SR_TXE)){}\n\n  \/*Write to transmit data register*\/\n\tUSART2-&gt;DR\t=  (ch &amp; 0xFF);\n}\n\n\/*Retargeting printf*\/\nint __io_putchar(int ch){uart2_write(ch); return ch;}\n\n\n#define rc_data_size 20\nuint8_t rc_data[rc_data_size];\n\nvolatile uint8_t done=0,idle=0;\n\n\n\nvoid reset_buffer();\n\n\nint main(void)\n{\n\n\t\/*UART2 Pin configures*\/\n\n\t\/\/enable clock access to GPIOA\n\tRCC-&gt;APB2ENR|=RCC_APB2ENR_IOPAEN;\n\t\/\/Enable clock access to alternate function\n\tRCC-&gt;APB2ENR|=RCC_APB2ENR_AFIOEN;\n\n\t\/*Confgiure PA2 as output maximum speed to 50MHz\n\t * and alternate output push-pull mode*\/\n\tGPIOA-&gt;CRL|=GPIO_CRL_MODE2;\n\n\tGPIOA-&gt;CRL|=GPIO_CRL_CNF2_1;\n\tGPIOA-&gt;CRL&amp;=~GPIO_CRL_CNF2_0;\n\n\n\t\/*Configure PA3 as Input floating*\/\n\n\t\/*Set mode to be input*\/\n\tGPIOA-&gt;CRL &amp;=~(GPIO_CRL_MODE3);\n\tGPIOA-&gt;CRL|=GPIO_CRL_CNF3_0;\n\tGPIOA-&gt;CRL&amp;=~GPIO_CRL_CNF3_1;\n\n\n\n\n\t\/*Don't remap the pins*\/\n\tAFIO-&gt;MAPR&amp;=~AFIO_MAPR_USART2_REMAP;\n\n\n\t\/*USART2 configuration*\/\n\n\t\/\/enable clock access to USART2\n\n\tRCC-&gt;APB1ENR|=RCC_APB1ENR_USART2EN;\n\n\t\/\/Transmit Enable\n\tUSART2-&gt;CR1 |= USART_CR1_TE;\n\n\t\/\/Enable receiver\n\tUSART2-&gt;CR1 |= USART_CR1_RE;\n\n\t\/*Enable IDLE Line interrupt*\/\n\n\tUSART2-&gt;CR1|=USART_CR1_IDLEIE;\n\n\t\/*Enable USART2 interrupt in NVIC*\/\n\tNVIC_EnableIRQ(USART2_IRQn);\n\n\t\/*Enable DMA for receiver*\/\n\tUSART2-&gt;CR3|=USART_CR3_DMAR;\n\n\t\/*Set baudrate *\/\n\tuart_set_baudrate(USART2,Perpher_CLK,Baudrate);\n\n\t\/*DMA configuration*\/\n\n\tRCC-&gt;AHBENR|=RCC_AHBENR_DMA1EN;\n\n\tDMA1_Channel6-&gt;CCR|=DMA_CCR_MINC|DMA_CCR_CIRC|DMA_CCR_TCIE;\n\n\tNVIC_EnableIRQ(DMA1_Channel6_IRQn);\n\n\t\/*Set the peripheral address to be USART2-&gt;DR*\/\n\tDMA1_Channel6-&gt;CPAR=(uint32_t)&amp;USART2-&gt;DR;\n\n\tDMA1_Channel6-&gt;CMAR=(uint32_t)rc_data;\n\n\tDMA1_Channel6-&gt;CNDTR=rc_data_size;\n\n\tDMA1_Channel6-&gt;CCR|=DMA_CCR_EN;\n\n\n\t\/\/Enable UART\n\tUSART2-&gt;CR1 |= USART_CR1_UE;\n\n\n\n\twhile(1)\n\t{\n\t\twhile(idle==0);\n\t\tprintf(&quot;Received data:\\&quot;%s\\&quot;\\r\\n&quot;,rc_data);\n\t\treset_buffer();\n\t\tidle=0;\n\n\n\t}\n}\n\n\nvoid reset_buffer()\n{\n\t\/*Disable DMA*\/\n\tDMA1_Channel6-&gt;CCR&amp;=~DMA_CCR_EN;\n\twhile((DMA1_Channel6-&gt;CCR) &amp;DMA_CCR_EN);\n\tmemset(rc_data, 0, rc_data_size);\n\tDMA1_Channel6-&gt;CNDTR=rc_data_size;\n\tDMA1_Channel6-&gt;CCR|=DMA_CCR_EN;\n}\n\nvoid DMA1_Channel6_IRQHandler(void)\n{\n\tif(DMA1-&gt;ISR &amp;DMA_ISR_TCIF6)\n\t{\n\t\tdone=1;\n\t\tDMA1-&gt;IFCR=DMA_IFCR_CTCIF6;\n\t}\n\n}\n\n\/*USART2 interrupt handler*\/\n\nvoid USART2_IRQHandler(void)\n{\n\tif (USART2-&gt;SR &amp; USART_SR_IDLE)\n\t\t{\n\n\t\t\tidle=1;\n\t\t\t\/*Clearing sequence:\n\t\t\t * Read the SR register (Already done in if condition)\n\t\t\t * Read the DR register\n\t\t\t * *\/\n\t\t\t(void)USART2-&gt;DR;\n\t\t}\n}\n\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. Demo:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"IDLE interrupt with DMA in STM32L053\" width=\"1170\" height=\"878\" src=\"https:\/\/www.youtube.com\/embed\/mS7swQjWRF4?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Happy coding \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the previous guide (here), we took a look how to configure the UART to transmit and receive data to\/from PC using DMA. The limitation that we shall wait until the buffer is filled before we print the the received characters. In this guide, we shall use IDLE Line interrupt to receive unknown length of [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,11,12],"tags":[],"class_list":["post-1509","post","type-post","status-publish","format-standard","hentry","category-embedded-systems","category-peripheral-drivers","category-stm32"],"_links":{"self":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1509"}],"collection":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1509"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1509\/revisions"}],"predecessor-version":[{"id":1512,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1509\/revisions\/1512"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1509"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1509"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1509"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}