{"id":1849,"date":"2023-06-24T15:19:07","date_gmt":"2023-06-24T15:19:07","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=1849"},"modified":"2023-06-26T12:16:00","modified_gmt":"2023-06-26T12:16:00","slug":"working-with-adc-and-stm32-part-5-timer-triggered-with-dma-with-double-buffer","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=1849","title":{"rendered":"Working with ADC and STM32 part 6: Timer triggered with DMA with Double Buffer"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"768\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/AdobeStock_56488870-1024x768.jpeg\" alt=\"\" class=\"wp-image-1850\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/AdobeStock_56488870-1024x768.jpeg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/AdobeStock_56488870-300x225.jpeg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/AdobeStock_56488870-768x576.jpeg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/AdobeStock_56488870-1536x1152.jpeg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/AdobeStock_56488870-2048x1536.jpeg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/AdobeStock_56488870-1150x863.jpeg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/AdobeStock_56488870-750x563.jpeg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/AdobeStock_56488870-400x300.jpeg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/AdobeStock_56488870-250x188.jpeg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\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=858\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=858\" target=\"_blank\">here<\/a>), we saw how to configure the ADC with DMA and timer to trigger it periodically. In this guide, we shall see how to use the double buffer mode to increase the potential processing power of STM32F4.<\/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>Double Buffer mode.<\/li><li>ADC and DMA configuration.<\/li><li>Process the buffers.<\/li><li>Code.<\/li><li>Results.<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Double Buffer Mode:<\/h2>\n\n\n\n<p>A double-buffer stream works as a regular (single buffer) stream with the difference that it has two memory pointers. When the Double buffer mode is enabled, the Circular mode is automatically enabled (CIRC bit in DMA_SxCR is don\u2019t care) and at each end of transaction, the memory pointers are swapped.<\/p>\n\n\n\n<p>In this mode, the DMA controller swaps from one memory target to another at each end of transaction. This allows the software to process one memory area while the second memory area is being filled\/used by the DMA transfer. The double-buffer stream can work in both directions.<\/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=\"500\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/2731094108519682_6b3683f262ea9dec165d2f96b8b49bac-1024x500.jpg\" alt=\"\" class=\"wp-image-1851\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/2731094108519682_6b3683f262ea9dec165d2f96b8b49bac-1024x500.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/2731094108519682_6b3683f262ea9dec165d2f96b8b49bac-300x146.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/2731094108519682_6b3683f262ea9dec165d2f96b8b49bac-768x375.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/2731094108519682_6b3683f262ea9dec165d2f96b8b49bac-1536x750.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/2731094108519682_6b3683f262ea9dec165d2f96b8b49bac-1150x561.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/2731094108519682_6b3683f262ea9dec165d2f96b8b49bac-750x366.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/2731094108519682_6b3683f262ea9dec165d2f96b8b49bac-400x195.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/2731094108519682_6b3683f262ea9dec165d2f96b8b49bac-250x122.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/2731094108519682_6b3683f262ea9dec165d2f96b8b49bac.jpg 1600w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption>source: https:\/\/civilpedia.org\/p\/?t=STM32-DMA-Cheat-Sheet&amp;pid=315<\/figcaption><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. ADC and DMA configuration:<\/h2>\n\n\n\n<p>For detailed ADC configuration, please refer to this guide <a href=\"https:\/\/blog.embeddedexpert.io\/?p=858\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=858\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n\n\n\n<p>We start off by creating new source and header file with name of adc.c and adc.h respectively.<\/p>\n\n\n\n<p>Within the header:<\/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;}\">#ifndef ADC_H_\n#define ADC_H_\n\n#include &quot;stdint.h&quot;\n\nvoid adc_init(void);\nuint8_t buffer_filled();\nvoid print_buffer();\n\n\n#endif \/* ADC_H_ *\/<\/pre><\/div>\n\n\n\n<p>The header file contain the following functions:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>ADC and DMA initializing.<\/li><li>Check if the buffer is filled.<\/li><li>Print the buffer (as buffer process).<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<p>Thats all for the header file.<\/p>\n\n\n\n<p>Within the source file:<\/p>\n\n\n\n<p>Include the 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;adc.h&quot;\n#include &quot;stm32f4xx.h&quot;                  \/\/ Device header\n#include &quot;stdio.h&quot;\n<\/pre><\/div>\n\n\n\n<p>Declare two buffers to hold the adc values:<\/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;}\">uint16_t adc_data1[10];\nuint16_t adc_data2[10];<\/pre><\/div>\n\n\n\n<p>volatile variable to indicate finish of filling the buffer:<\/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;}\">volatile uint8_t finished=0;<\/pre><\/div>\n\n\n\n<p>Within the adc_init function:<\/p>\n\n\n\n<p>Setting PA0 as analog mode:<\/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;}\">\tRCC-&gt;AHB1ENR\t\t|=RCC_AHB1ENR_GPIOAEN;\n\tGPIOA-&gt;MODER\t\t|=GPIO_MODER_MODE0_0|GPIO_MODER_MODE0_1;<\/pre><\/div>\n\n\n\n<p>ADC Configuration with DMA and timer trigger:<\/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;}\">\tRCC-&gt;APB2ENR\t\t|=RCC_APB2ENR_ADC1EN;\n\tADC1-&gt;CR2\t\t\t|=ADC_CR2_DMA|ADC_CR2_DDS;\n\tADC1-&gt;CR2\t\t\t|=ADC_CR2_EXTEN_0;\n\tADC1-&gt;CR2\t\t\t|=ADC_CR2_EXTSEL_1|ADC_CR2_EXTSEL_2;<\/pre><\/div>\n\n\n\n<p>DMA Configuration:<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>The DMA configuration as following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Memory and peripheral size to be half-word (16-bit).<\/li><li>Memory increment mode.<\/li><li>Half and transfer complete interrupt enable.<\/li><li>Double buffer mode.<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"389\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.04.53-PM-1024x389.png\" alt=\"\" class=\"wp-image-1852\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.04.53-PM-1024x389.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.04.53-PM-300x114.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.04.53-PM-768x292.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.04.53-PM-1536x583.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.04.53-PM-2048x778.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.04.53-PM-1150x437.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.04.53-PM-750x285.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.04.53-PM-400x152.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.04.53-PM-250x95.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;}\">\/*DMA related setup*\/\n\tRCC-&gt;AHB1ENR\t\t|=RCC_AHB1ENR_DMA2EN;\n\tDMA2_Stream0-&gt;CR\t&amp;=~DMA_SxCR_EN;\n\twhile(DMA2_Stream0-&gt;CR ==DMA_SxCR_EN){;}\n\t\n\tDMA2_Stream0-&gt;CR\t|=DMA_SxCR_MSIZE_0|DMA_SxCR_PSIZE_0|\n\t\t\tDMA_SxCR_MINC|DMA_SxCR_TCIE|DMA_SxCR_HTIE\n\t\t\t|DMA_SxCR_CIRC|DMA_SxCR_DBM;<\/pre><\/div>\n\n\n\n<p>Set the peripheral address to ADC1-&gt;DR:<\/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;}\">DMA2_Stream0-&gt;PAR\t =(uint32_t)(&amp;(ADC1-&gt;DR));<\/pre><\/div>\n\n\n\n<p>Set memory0 and memory1 address to the two buffer:<\/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;}\">\tDMA2_Stream0-&gt;M0AR \t =(uint32_t )(adc_data1);\n\tDMA2_Stream0-&gt;M1AR \t =(uint32_t )(adc_data2);<\/pre><\/div>\n\n\n\n<p>Set the number of transfers to be size of the buffers (10 in this case):<\/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;}\">DMA2_Stream0-&gt;NDTR\t =10;<\/pre><\/div>\n\n\n\n<p>Enable DMA2_Stream0 interrupt in NVIC:<\/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;}\">NVIC_EnableIRQ(DMA2_Stream0_IRQn);<\/pre><\/div>\n\n\n\n<p>Configure the timer:<\/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\/* Timer related setup*\/\n\tRCC-&gt;APB1ENR\t\t|=RCC_APB1ENR_TIM2EN;\n\tTIM2-&gt;PSC\t\t\t =16000-1;\n\tTIM2-&gt;ARR\t\t\t =10-1;\n\tTIM2-&gt;CR2\t\t\t|=TIM_CR2_MMS_1;<\/pre><\/div>\n\n\n\n<p>Launch the peripheral at this order:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>ADC.<\/li><li>DMA.<\/li><li>Timer.<\/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;}\">\/*Launch the ADC*\/\n\tADC1-&gt;CR2\t\t\t|=ADC_CR2_ADON;\n\t\/*Launch the DMA*\/\n\tDMA2_Stream0-&gt;CR \t|=DMA_SxCR_EN;\n\t\/*Launch the timer*\/\n\tTIM2-&gt;CR1\t\t\t|=TIM_CR1_CEN;<\/pre><\/div>\n\n\n\n<p>For the interrupt handler:<\/p>\n\n\n\n<p>Check the interrupt source:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Half transfer-&gt; Set finished to 1 and clear the relevant flag<\/li><li>Transfer Complete-&gt; Set finished to 1 and clear the relevant flag.<\/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 DMA2_Stream0_IRQHandler(void)\n{\n\n\tif(((DMA2-&gt;LISR)&amp;DMA_LISR_TCIF0))\n\t{\n\t\tfinished=1;\n\t\tDMA2-&gt;LIFCR=DMA_LIFCR_CTCIF0;\n\t}\n\n\tif(((DMA2-&gt;LISR)&amp;DMA_LISR_HTIF0))\n\t{\n\t\tfinished=1;\n\t\tDMA2-&gt;LIFCR=DMA_LIFCR_CHTIF0;\n\t}\n\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Process the buffer:<\/h2>\n\n\n\n<p>Before we process the buffer, we need to check if any buffer is filled by check the finished variable:<\/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;}\">uint8_t buffer_filled()\n{\n\treturn finished;\n}<\/pre><\/div>\n\n\n\n<p>If finished is 1, process the buffer.<\/p>\n\n\n\n<p>To determine which buffer is filled, we need to check the CT (Current Target) bit in the CR register of the DMA as following:<\/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=\"389\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.12.57-PM-1024x389.png\" alt=\"\" class=\"wp-image-1853\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.12.57-PM-1024x389.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.12.57-PM-300x114.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.12.57-PM-768x292.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.12.57-PM-1536x583.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.12.57-PM-2048x778.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.12.57-PM-1150x437.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.12.57-PM-750x285.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.12.57-PM-400x152.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.12.57-PM-250x95.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>CT is 1 -&gt; Buffer1 is filled.<\/li><li>CT is 0 -&gt; Buffer2 is filled.<\/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 print_buffer()\n{\n\n\tfinished=0;\n\n\tif ((DMA2_Stream0-&gt;CR &amp; DMA_SxCR_CT)) \/*If true, adc_data1 is filled *\/\n\t{\n\t\tprintf(&quot;ADC Buffer1 data are:\\r\\n&quot;);\n\t\tfor(int i=0;i&lt;10;i++)\n\t\t{\n\t\t\tprintf(&quot;%d\\t&quot;,adc_data1[i]);\n\t\t}\n\t\tprintf(&quot;\\r\\n&quot;);\n\t}\n\n\telse\n\t{\n\t\tprintf(&quot;ADC Buffer2 data are:\\r\\n&quot;);\n\t\tfor(int i=0;i&lt;10;i++)\n\t\t{\n\t\t\tprintf(&quot;%d\\t&quot;,adc_data2[i]);\n\t\t}\n\t\tprintf(&quot;\\r\\n&quot;);\n\n\t}\n\n}<\/pre><\/div>\n\n\n\n<p>The process is simple which is printing the buffer, in your application, you can do what ever you want like finding the difference between both value, calculate the RMS, etc.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>within main.c:<\/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;uart.h&quot;\n#include &quot;adc.h&quot;\n\n\nint main()\n{\n\n\tuart2_init();\n\tadc_init();\n\n\n\twhile(1)\n\t{\n\t\tif(buffer_filled()) \/*Check if the buffer is filled*\/\n\t\t{\n\t\t\t\/*Process the buffer (print in this case)*\/\n\t\t\tprint_buffer();\n\t\t}\n\t}\n\n\n}\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Hence the entire source 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;}\">\/*\n * adc.c\n *\n *  Created on: Jun 24, 2023\n *      Author: hussamaldean\n *\/\n\n\n#include &quot;adc.h&quot;\n#include &quot;stm32f4xx.h&quot;                  \/\/ Device header\n#include &quot;stdio.h&quot;\n\n\nuint16_t adc_data1[10];\nuint16_t adc_data2[10];\nvolatile uint8_t finished=0;\n\n\nvoid adc_init(void)\n{\n\t\/*ADC related set up*\/\n\tRCC-&gt;AHB1ENR\t\t|=RCC_AHB1ENR_GPIOAEN;\n\tGPIOA-&gt;MODER\t\t|=GPIO_MODER_MODE0_0|GPIO_MODER_MODE0_1;\n\n\tRCC-&gt;APB2ENR\t\t|=RCC_APB2ENR_ADC1EN;\n\tADC1-&gt;CR2\t\t\t|=ADC_CR2_DMA|ADC_CR2_DDS;\n\tADC1-&gt;CR2\t\t\t|=ADC_CR2_EXTEN_0;\n\tADC1-&gt;CR2\t\t\t|=ADC_CR2_EXTSEL_1|ADC_CR2_EXTSEL_2;\n\n\t\/*DMA related setup*\/\n\tRCC-&gt;AHB1ENR\t\t|=RCC_AHB1ENR_DMA2EN;\n\tDMA2_Stream0-&gt;CR\t&amp;=~DMA_SxCR_EN;\n\twhile(DMA2_Stream0-&gt;CR ==DMA_SxCR_EN){;}\n\n\tDMA2_Stream0-&gt;CR\t|=DMA_SxCR_MSIZE_0|DMA_SxCR_PSIZE_0|\n\t\t\tDMA_SxCR_MINC|DMA_SxCR_TCIE|DMA_SxCR_HTIE\n\t\t\t|DMA_SxCR_CIRC|DMA_SxCR_DBM;\n\n\tDMA2_Stream0-&gt;PAR\t =(uint32_t)(&amp;(ADC1-&gt;DR));\n\tDMA2_Stream0-&gt;M0AR \t =(uint32_t )(adc_data1);\n\tDMA2_Stream0-&gt;M1AR \t =(uint32_t )(adc_data2);\n\tDMA2_Stream0-&gt;NDTR\t =10;\n\n\tNVIC_EnableIRQ(DMA2_Stream0_IRQn);\n\n\t\/* Timer related setup*\/\n\tRCC-&gt;APB1ENR\t\t|=RCC_APB1ENR_TIM2EN;\n\tTIM2-&gt;PSC\t\t\t =16000-1;\n\tTIM2-&gt;ARR\t\t\t =10-1;\n\tTIM2-&gt;CR2\t\t\t|=TIM_CR2_MMS_1;\n\t\/*Launch the ADC*\/\n\tADC1-&gt;CR2\t\t\t|=ADC_CR2_ADON;\n\t\/*Launch the DMA*\/\n\tDMA2_Stream0-&gt;CR \t|=DMA_SxCR_EN;\n\t\/*Launch the timer*\/\n\tTIM2-&gt;CR1\t\t\t|=TIM_CR1_CEN;\n}\n\n\nuint8_t buffer_filled()\n{\n\treturn finished;\n}\n\n\nvoid print_buffer()\n{\n\n\tfinished=0;\n\n\tif ((DMA2_Stream0-&gt;CR &amp; DMA_SxCR_CT)) \/*If true, adc_data1 is filled *\/\n\t{\n\t\tprintf(&quot;ADC Buffer1 data are:\\r\\n&quot;);\n\t\tfor(int i=0;i&lt;10;i++)\n\t\t{\n\t\t\tprintf(&quot;%d\\t&quot;,adc_data1[i]);\n\t\t}\n\t\tprintf(&quot;\\r\\n&quot;);\n\t}\n\n\telse\n\t{\n\t\tprintf(&quot;ADC Buffer2 data are:\\r\\n&quot;);\n\t\tfor(int i=0;i&lt;10;i++)\n\t\t{\n\t\t\tprintf(&quot;%d\\t&quot;,adc_data2[i]);\n\t\t}\n\t\tprintf(&quot;\\r\\n&quot;);\n\n\t}\n\n}\n\n\nvoid DMA2_Stream0_IRQHandler(void)\n{\n\n\tif(((DMA2-&gt;LISR)&amp;DMA_LISR_TCIF0))\n\t{\n\t\tfinished=1;\n\t\tDMA2-&gt;LIFCR=DMA_LIFCR_CTCIF0;\n\t}\n\n\tif(((DMA2-&gt;LISR)&amp;DMA_LISR_HTIF0))\n\t{\n\t\tfinished=1;\n\t\tDMA2-&gt;LIFCR=DMA_LIFCR_CHTIF0;\n\t}\n\n}\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>You may download the source code from here:<\/p>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/double_buffer_dma.zip\">double_buffer_dma<\/a><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/double_buffer_dma.zip\" class=\"wp-block-file__button\" download>Download<\/a><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. Results:<\/h2>\n\n\n\n<p>Open serial terminal program and set the baud rate to 115200 and you should get the following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"952\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.16.40-PM-1024x952.png\" alt=\"\" class=\"wp-image-1855\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.16.40-PM-1024x952.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.16.40-PM-300x279.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.16.40-PM-768x714.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.16.40-PM-1150x1070.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.16.40-PM-750x698.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.16.40-PM-400x372.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.16.40-PM-250x233.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-24-at-6.16.40-PM.png 1346w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Happy coding &#x1f60a;&#x1f60a;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the previous guide (here), we saw how to configure the ADC with DMA and timer to trigger it periodically. In this guide, we shall see how to use the double buffer mode to increase the potential processing power of STM32F4. In this guide, we shall cover the following: Double Buffer mode. ADC and DMA [&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-1849","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\/1849"}],"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=1849"}],"version-history":[{"count":2,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1849\/revisions"}],"predecessor-version":[{"id":1857,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1849\/revisions\/1857"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1849"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1849"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1849"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}