{"id":1189,"date":"2022-09-04T14:30:06","date_gmt":"2022-09-04T14:30:06","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=1189"},"modified":"2022-09-04T14:30:10","modified_gmt":"2022-09-04T14:30:10","slug":"getting-started-with-stm32l053-uart-full-duplex-in-dma-mode-with-idle-line-detection","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=1189","title":{"rendered":"Getting started with STM32L053: UART Full duplex in DMA Mode with IDLE Line Detection"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/www.st.com\/content\/dam\/arm-cortex-m\/M0-Corenew.jpg\" alt=\"\" \/><\/figure><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>In the previous guide (<a rel=\"noreferrer noopener\" href=\"https:\/\/blog.embeddedexpert.io\/?p=1182\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=1182\" target=\"_blank\">here<\/a>), we saw how to configure the UART in full duplex mode with DMA. However, the application need to know the number of transfer in advanced in order to receive data. Using IDLE line, the application doesn&#8217;t need to know number of character to be received in advanced. <\/p>\n\n\n\n<p><\/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>Configure UART for IDLE interrupt.<\/li><li>Code.<\/li><li>Demo.<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Configure UART for IDLE interrupt:<\/h2>\n\n\n\n<p>To add IDLE line interrupt as simple as enabling it in CR1 (Control Register 1) and enable USART2 interrupt in NVIC<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"271\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/Screen-Shot-2022-09-04-at-5.18.51-PM-1024x271.png\" alt=\"\" class=\"wp-image-1190\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/Screen-Shot-2022-09-04-at-5.18.51-PM-1024x271.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/Screen-Shot-2022-09-04-at-5.18.51-PM-300x79.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/Screen-Shot-2022-09-04-at-5.18.51-PM-768x203.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/Screen-Shot-2022-09-04-at-5.18.51-PM-1536x406.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/Screen-Shot-2022-09-04-at-5.18.51-PM-2048x541.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/Screen-Shot-2022-09-04-at-5.18.51-PM-1150x304.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/Screen-Shot-2022-09-04-at-5.18.51-PM-750x198.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/Screen-Shot-2022-09-04-at-5.18.51-PM-400x106.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/Screen-Shot-2022-09-04-at-5.18.51-PM-250x66.png 250w\" 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;}\">\t\/*Enable IDLE Line Interrupt *\/\n\tUSART2-&gt;CR1|=USART_CR1_IDLEIE;\n\tNVIC_EnableIRQ(USART2_IRQn);<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>For interrupt handler:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Stop the DMA (optional).<\/li><li>Check if the source is IDLE line.<\/li><li>Set the received to 1.<\/li><li>Clear the pending IDLE line interrupt flag<\/li><\/ul>\n\n\n\n<p><\/p>\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;}\">\nvoid USART2_IRQHandler()\n\t{\n\tif(USART2-&gt;ISR &amp; USART_ISR_IDLE)\n\t\t{\n\t\t\tstop_dma();\n\t\t\treceived=1;\n\t\t\tUSART2-&gt;ICR|=USART_ICR_IDLECF;\n\t\t}\n\n\t}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>In while loop:<\/p>\n\n\n\n<p>Check if the received is set to 1 and print the received data using DMA also:<\/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\tif(received==1)\n\t\t\t{\n\t\t\t\tlength=sprintf(data_tx,&quot;Received data\\&quot; %s \\&quot;\\r\\n&quot;,data_rx);\n\t\t\t\tuart_transmit_dma(data_tx,length);\n\t\t\t\twhile(inprogress==1);\n\t\t\t\tinprogress=0;\n\t\t\t\treceived=0;\n\t\t\t\tflush_buffer();\n\t\t\t\tlunch_dma();\n\t\t\t}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. Code:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>Hence, the entire code is 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;stm32l0xx.h&quot;\n#include &quot;stdio.h&quot;\n#include &quot;delay.h&quot;\n#include &quot;string.h&quot;\n#define SYS_FREQ\t\t2097000\n#define APB1_CLK\t\tSYS_FREQ\n\n#define UART_BAUDRATE\t115200\n\nvolatile uint8_t received=0, inprogress=0,full=0;\n\n#define buffer_size 1024\nchar data_tx[buffer_size];\nchar data_rx[buffer_size];\nuint16_t length;\n\n\n\n\n#define DMA_CSELR  (*(volatile unsigned int *)(0x400200a8))\n\n\nvoid stop_dma();\nvoid lunch_dma();\nvoid flush_buffer();\n\nstatic uint16_t compute_uart_bd(uint32_t PeriphClk, uint32_t BaudRate)\n{\n\treturn ((PeriphClk  +  (BaudRate\/2U))\/BaudRate);\n}\n\n\n\n\n\n\nvoid uart_transmit_dma(char *message, uint16_t len)\n\t{\n\n\t\tif(inprogress==0)\n\t\t{\n\t\t\t\/*DMA1 Channel 7 is for USART_TX*\/\n\t\t\tDMA1_Channel7-&gt;CCR &amp;=~DMA_CCR_EN;\n\n\t\t\twhile((DMA1_Channel7-&gt;CCR &amp;DMA_CCR_EN));\n\t\t\tDMA1_Channel7-&gt;CCR|=DMA_CCR_MINC|DMA_CCR_DIR|DMA_CCR_TCIE;\n\t\t\tNVIC_EnableIRQ(DMA1_Channel4_5_6_7_IRQn);\n\t\t\tDMA1_Channel7-&gt;CPAR=(uint32_t)(&amp;USART2-&gt;TDR);\n\t\t\tDMA_CSELR|=(0x04&lt;&lt;24);\n\t\t\tDMA1-&gt;IFCR|=DMA_IFCR_CTCIF7;\n\t\t\tDMA1_Channel7-&gt;CMAR=(uint32_t)message;\n\t\t\tDMA1_Channel7-&gt;CNDTR=(uint16_t)len;\n\t\t\tDMA1_Channel7-&gt;CCR|=DMA_CCR_EN;\n\t\t\tinprogress=1;\n\t\t}\n\t\telse return;\n\t}\n\n\n\n\nint main(void)\n{\n\tsystick_init(2097000);\n\t\/*Enable clock access to GPIOA*\/\n\tRCC-&gt;IOPENR |= RCC_IOPENR_GPIOAEN;\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODE2_1;\n\tGPIOA-&gt;MODER&amp;=~GPIO_MODER_MODE2_0;\n\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODE3_1;\n\tGPIOA-&gt;MODER&amp;=~GPIO_MODER_MODE3_0;\n\n\t#define AF04 0x04\n\tGPIOA-&gt;AFR[0]|=(AF04&lt;&lt;8);\n\tGPIOA-&gt;AFR[0]|=(AF04&lt;&lt;12);\n\n\n\tRCC-&gt;APB1ENR |= RCC_APB1ENR_USART2EN;\n\tUSART2-&gt;BRR=compute_uart_bd(APB1_CLK,UART_BAUDRATE);\n\t\/*Configure transfer direction*\/\n\tUSART2-&gt;CR1 = USART_CR1_TE|USART_CR1_RE;\n\t\/*Enable IDLE Line Interrupt *\/\n\tUSART2-&gt;CR1|=USART_CR1_IDLEIE;\n\tNVIC_EnableIRQ(USART2_IRQn);\n\t\/*Enable DMA TX for UART*\/\n\tUSART2-&gt;CR3|=USART_CR3_DMAT|USART_CR3_DMAR;\n\t\/*Enable Clock access to DMA1*\/\n\tRCC-&gt;AHBENR|=RCC_AHBENR_DMA1EN;\n\t\/*Launch DMA*\/\n\tlunch_dma();\n\t\/*Enable uart module*\/\n\tUSART2-&gt;CR1 |= USART_CR1_UE;\n\n\n\tlength=sprintf(data_tx,&quot;Hello from UART DMA\\r\\n&quot;);\n\tuart_transmit_dma(data_tx,length);\n\twhile(inprogress==1);\n\tinprogress=0;\n\n\n\twhile(1)\n\t{\n\t\tif(received==1)\n\t\t\t{\n\t\t\t\tlength=sprintf(data_tx,&quot;Received data\\&quot; %s \\&quot;\\r\\n&quot;,data_rx);\n\t\t\t\tuart_transmit_dma(data_tx,length);\n\t\t\t\twhile(inprogress==1);\n\t\t\t\tinprogress=0;\n\t\t\t\treceived=0;\n\t\t\t\tflush_buffer();\n\t\t\t\tlunch_dma();\n\t\t\t}\n\t\tif(full==1)\n\t\t\t{\n\t\t\t\tlength=sprintf(data_tx,&quot;full buffer data\\&quot; %s \\&quot;\\r\\n&quot;,data_rx);\n\t\t\t\tuart_transmit_dma(data_tx,length);\n\t\t\t\twhile(inprogress==1);\n\t\t\t\tinprogress=0;\n\t\t\t\tfull=0;\n\t\t\t}\n\n\n\t}\n\n}\n\n\n\n\n\nvoid stop_dma()\n\t{\n\t\tDMA1_Channel6-&gt;CCR&amp;=~DMA_CCR_EN;\n\t}\n\nvoid flush_buffer()\n\t{\n\tmemset(data_rx,'\\0',buffer_size);\n\n\t}\n\nvoid lunch_dma()\n\t{\n\t\t\/*Configure DMA1_Channel6 for USART2_RX*\/\n\t\tDMA1_Channel6-&gt;CCR&amp;=~DMA_CCR_EN;\n\t\twhile((DMA1_Channel6-&gt;CCR &amp;DMA_CCR_EN));\n\t\tDMA1_Channel6-&gt;CCR|=DMA_CCR_MINC|DMA_CCR_CIRC|DMA_CCR_TCIE;\n\t\tNVIC_EnableIRQ(DMA1_Channel4_5_6_7_IRQn);\n\t\tDMA1_Channel6-&gt;CPAR=(uint32_t)(&amp;USART2-&gt;RDR);\n\t\tDMA_CSELR|=(0x04&lt;&lt;20);\n\t\tDMA1_Channel6-&gt;CMAR=(uint32_t)data_rx;\n\t\tDMA1_Channel6-&gt;CNDTR=buffer_size;\n\t\tDMA1_Channel6-&gt;CCR|=DMA_CCR_EN;\n\t}\n\n\nvoid DMA1_Channel4_7_IRQHandler(void)\n\t{\n\n\t\tif(DMA1-&gt;ISR &amp; DMA_ISR_TCIF7)\n\t\t\t{\n\t\t\t\tinprogress=0;\n\t\t\t\tDMA1-&gt;IFCR|=DMA_IFCR_CTCIF7;\n\t\t\t}\n\t\tif(DMA1-&gt;ISR &amp; DMA_ISR_TCIF6)\n\t\t\t{\n\t\t\t\tfull=1;\n\t\t\t\tDMA1-&gt;IFCR|=DMA_IFCR_CTCIF6;\n\t\t\t}\n\n\t}\n\n\nvoid USART2_IRQHandler()\n\t{\n\tif(USART2-&gt;ISR &amp; USART_ISR_IDLE)\n\t\t{\n\t\t\tstop_dma();\n\t\t\treceived=1;\n\t\t\tUSART2-&gt;ICR|=USART_ICR_IDLECF;\n\t\t}\n\n\t}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. 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\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<p>Happy coding \ud83d\ude42<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the previous guide (here), we saw how to configure the UART in full duplex mode with DMA. However, the application need to know the number of transfer in advanced in order to receive data. Using IDLE line, the application doesn&#8217;t need to know number of character to be received in advanced. In this guide, [&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-1189","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\/1189"}],"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=1189"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1189\/revisions"}],"predecessor-version":[{"id":1191,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1189\/revisions\/1191"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1189"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1189"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1189"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}