{"id":3693,"date":"2025-08-16T14:37:53","date_gmt":"2025-08-16T14:37:53","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=3693"},"modified":"2025-08-17T12:10:57","modified_gmt":"2025-08-17T12:10:57","slug":"revised-getting-started-with-stm32f103-timer-in-pwm-mode-with-dmarevised","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=3693","title":{"rendered":"[Revised] Getting Started with STM32F103: Timer in PWM Mode with DMA"},"content":{"rendered":"\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"655\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/AdobeStock_495094833-2048x1309-1-1024x655.jpeg\" alt=\"\" class=\"wp-image-1540\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/AdobeStock_495094833-2048x1309-1-1024x655.jpeg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/AdobeStock_495094833-2048x1309-1-300x192.jpeg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/AdobeStock_495094833-2048x1309-1-768x491.jpeg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/AdobeStock_495094833-2048x1309-1-1536x982.jpeg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/AdobeStock_495094833-2048x1309-1-1150x735.jpeg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/AdobeStock_495094833-2048x1309-1-750x479.jpeg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/AdobeStock_495094833-2048x1309-1-400x256.jpeg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/AdobeStock_495094833-2048x1309-1-250x160.jpeg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/AdobeStock_495094833-2048x1309-1.jpeg 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>In the previous guide of PWM (<a rel=\"noreferrer noopener\" href=\"https:\/\/blog.embeddedexpert.io\/?p=1400\" target=\"_blank\">here<\/a>), we saw how to configure the timer to operate in PWM mode and update the duty cycle using for loop.<\/p>\n\n\n\n<p>In this guide, we shall use DMA and set of predefined duty cycle to update two channels of PWM.<\/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\">\n<li>GPIO configuration.<\/li>\n\n\n\n<li>Timer configuration<\/li>\n\n\n\n<li>DMA configuration.<\/li>\n\n\n\n<li>Code.<\/li>\n\n\n\n<li>Results.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">1. GPIO configuration<\/h2>\n\n\n\n<p>From the previous guide, we know that PA0, PA1, PA2 and PA3 are for TIM2_CH1, TIM2_CH2, TIM2_CH3 and TIM2_CH4 respectively:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"736\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/12\/Screenshot-2022-12-14-at-3.49.49-PM-1024x736.png\" alt=\"\" class=\"wp-image-1403\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/12\/Screenshot-2022-12-14-at-3.49.49-PM-1024x736.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/12\/Screenshot-2022-12-14-at-3.49.49-PM-300x216.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/12\/Screenshot-2022-12-14-at-3.49.49-PM-768x552.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/12\/Screenshot-2022-12-14-at-3.49.49-PM-1536x1105.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/12\/Screenshot-2022-12-14-at-3.49.49-PM-2048x1473.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/12\/Screenshot-2022-12-14-at-3.49.49-PM-1150x827.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/12\/Screenshot-2022-12-14-at-3.49.49-PM-750x539.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/12\/Screenshot-2022-12-14-at-3.49.49-PM-400x288.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/12\/Screenshot-2022-12-14-at-3.49.49-PM-250x180.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Hence, we shall configure both pins as alternate output push-pull configuration and output speed to maximum of 50MHz 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;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\tRCC-&gt;APB2ENR|=RCC_APB2ENR_IOPAEN;\n\n\t\/*Configure PA0 as Output Alternate Push\/Pull *\/\n\tGPIOA-&gt;CRL|=GPIO_CRL_MODE0;\n\tGPIOA-&gt;CRL|=(GPIO_CRL_CNF0_1);\n\tGPIOA-&gt;CRL&amp;=~(GPIO_CRL_CNF0_0);\n\n\t\/*Configure PA1 as Output Alternate Push\/Pull *\/\n\tGPIOA-&gt;CRL|=GPIO_CRL_MODE1;\n\tGPIOA-&gt;CRL|=(GPIO_CRL_CNF1_1);\n\tGPIOA-&gt;CRL&amp;=~(GPIO_CRL_CNF1_0);<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Also, we shall not remap the pins of TIM2:<\/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;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\t\/*Don't remap the pin*\/\n\tAFIO-&gt;MAPR&amp;=~AFIO_MAPR_TIM2_REMAP;<\/pre><\/div>\n\n\n\n<p>Thats all for GPIO configuration.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. Timer configuration:<\/h2>\n\n\n\n<p>First enable clock access to TIM2 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;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\t\/*Enable clock access to timer2*\/\n\tRCC-&gt;APB1ENR|=RCC_APB1ENR_TIM2EN;<\/pre><\/div>\n\n\n\n<p>Set the prescaler and ARR to be 0 and 1600 respectively:<\/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;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\tTIM2-&gt;PSC=0;\n\tTIM2-&gt;ARR=1600;<\/pre><\/div>\n\n\n\n<p>Set both pins as PWM using OC1M and OC2M configuration and enable the preload for the channel as follows:<\/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=\"454\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/Screenshot-2023-02-15-at-6.34.27-AM-1024x454.png\" alt=\"\" class=\"wp-image-3694\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/Screenshot-2023-02-15-at-6.34.27-AM-1024x454.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/Screenshot-2023-02-15-at-6.34.27-AM-300x133.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/Screenshot-2023-02-15-at-6.34.27-AM-768x340.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/Screenshot-2023-02-15-at-6.34.27-AM-1536x681.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/Screenshot-2023-02-15-at-6.34.27-AM-1150x510.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/Screenshot-2023-02-15-at-6.34.27-AM-750x332.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/Screenshot-2023-02-15-at-6.34.27-AM-400x177.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/Screenshot-2023-02-15-at-6.34.27-AM-250x111.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/Screenshot-2023-02-15-at-6.34.27-AM.png 1968w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\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;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\tTIM2-&gt;CCMR1|=TIM_CCMR1_OC1M_2|TIM_CCMR1_OC1M_1|TIM_CCMR1_OC2M_2|\n\tTIM_CCMR1_OC2M_1|TIM_CCMR1_OC2PE|TIM_CCMR1_OC1PE;<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>The reason to enable preload for the channel:<\/p>\n\n\n\n<p>When you use&nbsp;<strong>PWM with DMA feeding the CCRx register<\/strong>&nbsp;(compare value), the&nbsp;<strong>preload<\/strong>&nbsp;option becomes important because of&nbsp;<em>when<\/em>&nbsp;the new value takes effect.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Without preload enabled<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>DMA writes directly into\u00a0<code>TIMx_CCRx<\/code>.<\/li>\n\n\n\n<li>As soon as DMA writes, the new duty cycle\u00a0<strong>immediately takes effect<\/strong>, even if the timer is mid-cycle.<\/li>\n\n\n\n<li>This causes\u00a0<strong>jitter, glitches, or distorted SPWM<\/strong>, because the duty can suddenly change in the middle of an active PWM period.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">With preload enabled (<code>TIMx_CCMRx: OCxPE = 1<\/code>)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>DMA writes go into a\u00a0<strong>shadow\/preload register<\/strong>\u00a0instead of the active CCR.<\/li>\n\n\n\n<li>The new value is\u00a0<strong>latched only at the next update event (timer overflow \/ start of new period)<\/strong>.<\/li>\n\n\n\n<li>This guarantees that the duty cycle updates\u00a0<strong>synchronously, once per PWM period<\/strong>, giving a clean sine waveform.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Why it matters for SPWM<\/h3>\n\n\n\n<p>In SPWM you\u2019re streaming&nbsp;<strong>hundreds of samples<\/strong>&nbsp;per sine cycle.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Without preload \u2192 you\u2019ll get sudden mid-period duty jumps (harmonics, noise).<\/li>\n\n\n\n<li>With preload \u2192 each CCR update applies exactly at the start of a PWM cycle, so your sine remains smooth.<\/li>\n<\/ul>\n\n\n\n<p><\/p>\n\n\n\n<p>Enable both channel:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"264\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.36.09-AM-1024x264.png\" alt=\"\" class=\"wp-image-1543\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.36.09-AM-1024x264.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.36.09-AM-300x77.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.36.09-AM-768x198.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.36.09-AM-1536x396.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.36.09-AM-1150x297.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.36.09-AM-750x194.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.36.09-AM-400x103.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.36.09-AM-250x65.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.36.09-AM.png 1968w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\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;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">TIM2-&gt;CCER|=TIM_CCER_CC1E|TIM_CCER_CC2E;<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Set the timer to trigger DMA request each Capture\/Compare is happened.<\/p>\n\n\n\n<p>To do such thing, CC1DE and CC2DE bit should be set in DIER register:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"252\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.38.41-AM-1024x252.png\" alt=\"\" class=\"wp-image-1544\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.38.41-AM-1024x252.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.38.41-AM-300x74.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.38.41-AM-768x189.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.38.41-AM-1536x378.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.38.41-AM-1150x283.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.38.41-AM-750x184.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.38.41-AM-400x98.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.38.41-AM-250x61.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.38.41-AM.png 1968w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\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;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">TIM2-&gt;DIER|=TIM_DIER_CC1DE|TIM_DIER_CC2DE;<\/pre><\/div>\n\n\n\n<p>Note: DON\u2019T ENABLE THE TIMER YET.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. DMA Configuration:<\/h2>\n\n\n\n<p>Since STM32F103 has only 1 DMA, we shall enable clock access to it as following:<\/p>\n\n\n\n<p>Since the DMA is connected to AHB bus, we can enable clock access to it 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;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">RCC-&gt;AHBENR|=RCC_AHBENR_DMA1EN;<\/pre><\/div>\n\n\n\n<p>Then we need to know which DMA channels are responsible for TIM2_CH1 and TIM2_CH2.<\/p>\n\n\n\n<p>From the reference manual, DMA request table, we can find that DMA1_Stream5 and DMA1_Stream7 are responsible for TIM2_CH1 and TIM2_CH2 respectively:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"463\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.42.52-AM-1024x463.png\" alt=\"\" class=\"wp-image-1545\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.42.52-AM-1024x463.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.42.52-AM-300x136.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.42.52-AM-768x347.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.42.52-AM-1536x695.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.42.52-AM-1150x520.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.42.52-AM-750x339.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.42.52-AM-400x181.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.42.52-AM-250x113.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.42.52-AM.png 1968w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Hence, we shall configure both channels with the following parameters:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Memory and peripheral size to 16-bit (half word).<\/li>\n\n\n\n<li>Memory increment mode.<\/li>\n\n\n\n<li>DMA in circular mode.<\/li>\n\n\n\n<li>Direction is read from memory.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"359\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.46.21-AM-1024x359.png\" alt=\"\" class=\"wp-image-1546\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.46.21-AM-1024x359.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.46.21-AM-300x105.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.46.21-AM-768x269.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.46.21-AM-1536x539.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.46.21-AM-1150x403.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.46.21-AM-750x263.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.46.21-AM-400x140.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.46.21-AM-250x88.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-15-at-6.46.21-AM.png 1968w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\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;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">DMA1_Channel5-&gt;CCR=DMA_CCR_MSIZE_0|DMA_CCR_PSIZE_0|\n\t\t\tDMA_CCR_MINC|DMA_CCR_CIRC|DMA_CCR_DIR;<\/pre><\/div>\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;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">DMA1_Channel7-&gt;CCR=DMA_CCR_MSIZE_0|DMA_CCR_PSIZE_0|\n\t\t\tDMA_CCR_MINC|DMA_CCR_CIRC|DMA_CCR_DIR;<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Note: DON\u2019T ENABLE THE CHANNELs YET.<\/p>\n\n\n\n<p>Set the memory address to the array that holds the duty cycle 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;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">#define sample_size 200\n\nuint16_t lookUp1[sample_size] = {\n    \/\/ first half sine (100 samples)\n    0,50,100,151,201,250,300,349,398,446,\n    494,542,589,635,681,726,771,814,857,899,\n    940,981,1020,1058,1095,1131,1166,1200,1233,1264,\n    1294,1323,1351,1377,1402,1426,1448,1468,1488,1505,\n    1522,1536,1550,1561,1572,1580,1587,1593,1597,1599,\n    1600,1599,1597,1593,1587,1580,1572,1561,1550,1536,\n    1522,1505,1488,1468,1448,1426,1402,1377,1351,1323,\n    1294,1264,1233,1200,1166,1131,1095,1058,1020,981,\n    940,899,857,814,771,726,681,635,589,542,\n    494,446,398,349,300,250,201,151,100,50,\n    \/\/ second half zeros (100 samples)\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0\n};\n\nuint16_t lookUp2[sample_size] = {\n    \/\/ first half zeros (100 samples)\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    \/\/ second half sine (100 samples)\n    0,50,100,151,201,250,300,349,398,446,\n    494,542,589,635,681,726,771,814,857,899,\n    940,981,1020,1058,1095,1131,1166,1200,1233,1264,\n    1294,1323,1351,1377,1402,1426,1448,1468,1488,1505,\n    1522,1536,1550,1561,1572,1580,1587,1593,1597,1599,\n    1600,1599,1597,1593,1587,1580,1572,1561,1550,1536,\n    1522,1505,1488,1468,1448,1426,1402,1377,1351,1323,\n    1294,1264,1233,1200,1166,1131,1095,1058,1020,981,\n    940,899,857,814,771,726,681,635,589,542,\n    494,446,398,349,300,250,201,151,100,50\n};\n<\/pre><\/div>\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;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">DMA1_Channel5-&gt;CMAR=(uint32_t)lookUp1;<\/pre><\/div>\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;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">DMA1_Channel7-&gt;CMAR=(uint32_t)lookUp2;<\/pre><\/div>\n\n\n\n<p>Set the peripheral address to CCR1 and CCR2 respectively:<\/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;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">DMA1_Channel5-&gt;CPAR=(uint32_t)(&amp;TIM2-&gt;CCR1);<\/pre><\/div>\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;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">DMA1_Channel7-&gt;CPAR=(uint32_t)(&amp;TIM2-&gt;CCR2);<\/pre><\/div>\n\n\n\n<p>Enable both channels<\/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;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\tDMA1_Channel5-&gt;CCR|=DMA_CCR_EN;\n\tDMA1_Channel7-&gt;CCR|=DMA_CCR_EN;<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Finally, enable 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;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">TIM2-&gt;CR1|=TIM_CR1_CEN;<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">4. Code:<\/h2>\n\n\n\n<p>The entire 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;C&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\n\/*DMA1 Channels\n *\n * Channel5 for TIM2_CH1\n * Channel7 for TIM2_CH2\n *\n * *\/\n\n\n#define sample_size 200\n\nuint16_t lookUp1[sample_size] = {\n    \/\/ first half sine (100 samples)\n    0,50,100,151,201,250,300,349,398,446,\n    494,542,589,635,681,726,771,814,857,899,\n    940,981,1020,1058,1095,1131,1166,1200,1233,1264,\n    1294,1323,1351,1377,1402,1426,1448,1468,1488,1505,\n    1522,1536,1550,1561,1572,1580,1587,1593,1597,1599,\n    1600,1599,1597,1593,1587,1580,1572,1561,1550,1536,\n    1522,1505,1488,1468,1448,1426,1402,1377,1351,1323,\n    1294,1264,1233,1200,1166,1131,1095,1058,1020,981,\n    940,899,857,814,771,726,681,635,589,542,\n    494,446,398,349,300,250,201,151,100,50,\n    \/\/ second half zeros (100 samples)\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0\n};\n\nuint16_t lookUp2[sample_size] = {\n    \/\/ first half zeros (100 samples)\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    0,0,0,0,0,0,0,0,0,0,\n    \/\/ second half sine (100 samples)\n    0,50,100,151,201,250,300,349,398,446,\n    494,542,589,635,681,726,771,814,857,899,\n    940,981,1020,1058,1095,1131,1166,1200,1233,1264,\n    1294,1323,1351,1377,1402,1426,1448,1468,1488,1505,\n    1522,1536,1550,1561,1572,1580,1587,1593,1597,1599,\n    1600,1599,1597,1593,1587,1580,1572,1561,1550,1536,\n    1522,1505,1488,1468,1448,1426,1402,1377,1351,1323,\n    1294,1264,1233,1200,1166,1131,1095,1058,1020,981,\n    940,899,857,814,771,726,681,635,589,542,\n    494,446,398,349,300,250,201,151,100,50\n};\n\n\n\n\n\nint main(void)\n{\n\tRCC-&gt;APB2ENR|=RCC_APB2ENR_IOPAEN;\n\n\t\/*Configure PA0 as Output Alternate Push\/Pull *\/\n\tGPIOA-&gt;CRL|=GPIO_CRL_MODE0;\n\tGPIOA-&gt;CRL|=(GPIO_CRL_CNF0_1);\n\tGPIOA-&gt;CRL&amp;=~(GPIO_CRL_CNF0_0);\n\n\t\/*Configure PA1 as Output Alternate Push\/Pull *\/\n\tGPIOA-&gt;CRL|=GPIO_CRL_MODE1;\n\tGPIOA-&gt;CRL|=(GPIO_CRL_CNF1_1);\n\tGPIOA-&gt;CRL&amp;=~(GPIO_CRL_CNF1_0);\n\n\t\/*Don't remap the pin*\/\n\tAFIO-&gt;MAPR&amp;=~AFIO_MAPR_TIM2_REMAP;\n\n\n\t\/*Enable clock access to timer2*\/\n\tRCC-&gt;APB1ENR|=RCC_APB1ENR_TIM2EN;\n\n\t\/*Configure timer2*\/\n\tTIM2-&gt;PSC=0;\n\tTIM2-&gt;ARR=1600;\n\t\n\tTIM2-&gt;CCMR1|=TIM_CCMR1_OC1M_2|TIM_CCMR1_OC1M_1|TIM_CCMR1_OC2M_2|\n\tTIM_CCMR1_OC2M_1|TIM_CCMR1_OC2PE|TIM_CCMR1_OC1PE;\n\tTIM2-&gt;CCER|=TIM_CCER_CC1E|TIM_CCER_CC2E;\n\n\tTIM2-&gt;DIER|=TIM_DIER_CC1DE|TIM_DIER_CC2DE;\n\n\n\t\/*DMA configuration*\/\n\n\tRCC-&gt;AHBENR|=RCC_AHBENR_DMA1EN;\n\n\tDMA1_Channel5-&gt;CCR=DMA_CCR_MSIZE_0|DMA_CCR_PSIZE_0|\n\t\t\tDMA_CCR_MINC|DMA_CCR_CIRC|DMA_CCR_DIR;\n\n\tDMA1_Channel5-&gt;CNDTR=(uint16_t)sample_size;\n\tDMA1_Channel5-&gt;CMAR=(uint32_t)lookUp1;\n\tDMA1_Channel5-&gt;CPAR=(uint32_t)(&amp;TIM2-&gt;CCR1);\n\n\tDMA1_Channel7-&gt;CCR=DMA_CCR_MSIZE_0|DMA_CCR_PSIZE_0|\n\t\t\tDMA_CCR_MINC|DMA_CCR_CIRC|DMA_CCR_DIR;\n\n\tDMA1_Channel7-&gt;CNDTR=(uint16_t)sample_size;\n\tDMA1_Channel7-&gt;CMAR=(uint32_t)lookUp2;\n\tDMA1_Channel7-&gt;CPAR=(uint32_t)(&amp;TIM2-&gt;CCR2);\n\n\tDMA1_Channel5-&gt;CCR|=DMA_CCR_EN;\n\tDMA1_Channel7-&gt;CCR|=DMA_CCR_EN;\n\n\tTIM2-&gt;CR1|=TIM_CR1_CEN;\n\n\twhile(1)\n\t{\n\n\n\t}\n}\n<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">5. Results:<\/h2>\n\n\n\n<p>Probe both PA0 and PA1 using oscilloscope, you should get the following:<\/p>\n\n\n\n<p>(I used differential probe here)<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"630\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/RigolDS7.png\" alt=\"\" class=\"wp-image-3695\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/RigolDS7.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/RigolDS7-300x185.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/RigolDS7-768x473.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/RigolDS7-750x461.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/RigolDS7-400x246.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/RigolDS7-250x154.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>By applying low pass filter:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"630\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/RigolDS8.png\" alt=\"\" class=\"wp-image-3696\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/RigolDS8.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/RigolDS8-300x185.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/RigolDS8-768x473.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/RigolDS8-750x461.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/RigolDS8-400x246.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/RigolDS8-250x154.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Notice how we are getting almost clean sinewave despite we are using PWM signal? This is the beauty of SPWM.<\/p>\n\n\n\n<p>Happy coding \ud83d\ude09<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the previous guide of PWM (here), we saw how to configure the timer to operate in PWM mode and update the duty cycle using for loop. In this guide, we shall use DMA and set of predefined duty cycle to update two channels of PWM. In this guide, we shall cover the following: 1. [&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-3693","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\/3693"}],"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=3693"}],"version-history":[{"count":2,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/3693\/revisions"}],"predecessor-version":[{"id":3699,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/3693\/revisions\/3699"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3693"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3693"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3693"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}