{"id":3096,"date":"2024-12-22T04:21:04","date_gmt":"2024-12-22T04:21:04","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=3096"},"modified":"2024-12-22T04:21:06","modified_gmt":"2024-12-22T04:21:06","slug":"getting-started-with-stm32h5-arm-cortex-m33-timer-in-pwm-mode-with-dma","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=3096","title":{"rendered":"Getting Started with STM32H5 ARM Cortex M33: Timer in PWM Mode with DMA"},"content":{"rendered":"<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"725\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/STM32-u5-1-1-2-1024x725.webp\" alt=\"\" class=\"wp-image-3097\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/STM32-u5-1-1-2-1024x725.webp 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/STM32-u5-1-1-2-300x212.webp 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/STM32-u5-1-1-2-768x544.webp 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/STM32-u5-1-1-2-750x531.webp 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/STM32-u5-1-1-2-400x283.webp 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/STM32-u5-1-1-2-250x177.webp 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/STM32-u5-1-1-2.webp 1141w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n<p><\/p>\n\n\n\n<p>In this guide, we shall use the DMA to update the duty cycle of the PWM to generate custom waveform like sinewave etc and the benefits of such approach.<\/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>Why update PWM duty cycle using DMA.<\/li>\n\n\n\n<li>STM32CubeMX setup.<\/li>\n\n\n\n<li>Firmware development.<\/li>\n\n\n\n<li>Results.<\/li>\n<\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Why Update PWM Duty Cycle using DMA:<\/h2>\n\n\n\n<p>Using DMA (Direct Memory Access) to update PWM (Pulse Width Modulation) in STM32H5 allows efficient transfer of data to a timer&#8217;s capture\/compare registers without CPU intervention. This approach is particularly useful for applications requiring frequent or precise updates, such as motor control, waveform generation, or advanced lighting systems.<\/p>\n\n\n\n<p>Here\u2019s the theoretical explanation:<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>1. PWM Overview<\/strong><\/h3>\n\n\n\n<p>PWM is generated using the timers in STM32, where the duty cycle and frequency are controlled by the values set in the timer\u2019s&nbsp;<strong>ARR<\/strong>&nbsp;(Auto-Reload Register) and&nbsp;<strong>CCR<\/strong>&nbsp;(Capture\/Compare Register). The&nbsp;<strong>CCR<\/strong>&nbsp;value determines the duty cycle, and changing it modifies the output waveform.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>2. DMA Overview<\/strong><\/h3>\n\n\n\n<p>DMA allows peripherals like timers to access memory directly, bypassing the CPU. This reduces CPU load and ensures data transfer happens quickly and deterministically.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>3. Updating PWM Using DMA<\/strong><\/h3>\n\n\n\n<p>The basic idea is to configure the DMA to transfer a buffer of duty cycle values to the timer&#8217;s&nbsp;<strong>CCR<\/strong>&nbsp;register, synchronized with the timer\u2019s update event.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Key Steps<\/strong><\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Timer Configuration<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Configure the timer for PWM output.<\/li>\n\n\n\n<li>Enable the DMA request for the timer update event. This ensures the DMA is triggered periodically.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>DMA Configuration<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Set the memory source (e.g., an array of duty cycle values).<\/li>\n\n\n\n<li>Set the peripheral destination (the\u00a0<strong>CCR<\/strong>\u00a0register of the timer).<\/li>\n\n\n\n<li>Configure the DMA transfer mode:\n<ul class=\"wp-block-list\">\n<li><strong>Circular Mode<\/strong>: Repeatedly cycle through the duty cycle array.<\/li>\n\n\n\n<li><strong>Normal Mode<\/strong>: Transfer data once, then stop.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Set the data size (16-bit or 32-bit, depending on the timer&#8217;s register size).<\/li>\n\n\n\n<li>Enable transfer complete interrupts if needed for additional logic.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Trigger Synchronization<\/strong>:\n<ul class=\"wp-block-list\">\n<li>The DMA is triggered by the timer\u2019s update event, ensuring the\u00a0<strong>CCR<\/strong>\u00a0is updated in sync with the PWM period.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>4. Benefits of Using DMA for PWM Updates<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>CPU Offloading<\/strong>: The CPU doesn\u2019t need to manually update the\u00a0<strong>CCR<\/strong>\u00a0register.<\/li>\n\n\n\n<li><strong>Precision<\/strong>: Updates occur at consistent intervals, avoiding jitter.<\/li>\n\n\n\n<li><strong>Scalability<\/strong>: Multiple channels or arrays can be updated simultaneously using different DMA streams.<\/li>\n\n\n\n<li><strong>Power Efficiency<\/strong>: Reduces CPU activity, saving power in embedded systems.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>5. Use Case Example<\/strong><\/h3>\n\n\n\n<p>If you\u2019re generating a waveform:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Create an array with pre-calculated duty cycle values representing the waveform (e.g., sine wave).<\/li>\n\n\n\n<li>Use DMA to transfer these values to the timer\u2019s\u00a0<strong>CCR<\/strong>\u00a0register.<\/li>\n\n\n\n<li>The timer&#8217;s update event triggers the DMA transfer, ensuring the PWM signal represents the desired waveform.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>6. Timer and DMA Interaction<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>DMA Request<\/strong>: The timer generates a DMA request signal on every update event (or other configured events like capture\/compare match).<\/li>\n\n\n\n<li><strong>DMA Transfer<\/strong>: On receiving the request, the DMA transfers the next value from memory to the timer\u2019s\u00a0<strong>CCR<\/strong>register.<\/li>\n\n\n\n<li><strong>PWM Output<\/strong>: The timer updates the PWM output at the next cycle based on the new\u00a0<strong>CCR<\/strong>\u00a0value.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>7. Practical Considerations<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Buffer Size<\/strong>: Ensure the buffer contains enough data for your application.<\/li>\n\n\n\n<li><strong>DMA Priority<\/strong>: Set appropriate priority to avoid conflicts with other peripherals.<\/li>\n\n\n\n<li><strong>Synchronization<\/strong>: Ensure the timer\u2019s period matches the data update rate for smooth operation.<\/li>\n\n\n\n<li><strong>Cache Management<\/strong>: For STM32H5, ensure proper handling of cached data when using DMA. Mark the buffer as non-cacheable or use cache maintenance functions to ensure DMA accesses the correct data.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">2. STM32CubeMX Setup:<\/h2>\n\n\n\n<p>We start off by creating new project with name of PWM_DMA. For how to create project using STM32CubeIDE, please refer to this guide\u00a0<a href=\"https:\/\/blog.embeddedexpert.io\/?p=2789\">here<\/a>.<\/p>\n\n\n\n<p>Since STM32H563Zi Nucleo-144 has arduino pinout, we can use that.<\/p>\n\n\n\n<p>From the user guide of STM32H563ZI Nucleo-144 we can find that A0 of Arduino pin is connected to PA6 as following:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"973\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-41-44-1024x973.jpg\" alt=\"\" class=\"wp-image-3068\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-41-44-1024x973.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-41-44-300x285.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-41-44-768x730.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-41-44-1536x1459.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-41-44-1150x1093.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-41-44-750x713.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-41-44-400x380.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-41-44-250x238.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-41-44.jpg 1922w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>From STM32CubeIDE enable PA6 as TIM3_CH1 as following:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"465\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-44-18-1024x465.jpg\" alt=\"\" class=\"wp-image-3070\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-44-18-1024x465.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-44-18-300x136.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-44-18-768x349.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-44-18-1536x698.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-44-18-2048x931.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-44-18-1150x523.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-44-18-750x341.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-44-18-400x182.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-44-18-250x114.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, from timers section, enable TIM3 as following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Set the clock source to be internal.<\/li>\n\n\n\n<li>Enable Channel 1 to be in PWM mode as following:<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"910\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-45-49-910x1024.jpg\" alt=\"\" class=\"wp-image-3071\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-45-49-910x1024.jpg 910w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-45-49-266x300.jpg 266w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-45-49-768x865.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-45-49-1364x1536.jpg 1364w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-45-49-1150x1295.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-45-49-750x844.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-45-49-400x450.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-45-49-250x281.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-06_06-45-49.jpg 1702w\" sizes=\"(max-width: 910px) 100vw, 910px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, set the parameters of the timer as following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Set the prescaler to 32-1 This will give us 1MHz (According to your application).<\/li>\n\n\n\n<li>Set the ARR to 1600, this will reduce the frequency of the PWM to 625Hz (According to your application).<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"988\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-22_07-03-52-988x1024.jpg\" alt=\"\" class=\"wp-image-3098\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-22_07-03-52-988x1024.jpg 988w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-22_07-03-52-289x300.jpg 289w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-22_07-03-52-768x796.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-22_07-03-52-1482x1536.jpg 1482w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-22_07-03-52-1150x1192.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-22_07-03-52-750x778.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-22_07-03-52-400x415.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-22_07-03-52-250x259.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-22_07-03-52.jpg 1742w\" sizes=\"(max-width: 988px) 100vw, 988px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, in GPDMA1, enable Ch0 in standard request mode as following:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"914\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/2024-11-27_19-45-48-1024x914.jpg\" alt=\"\" class=\"wp-image-3049\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/2024-11-27_19-45-48-1024x914.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/2024-11-27_19-45-48-300x268.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/2024-11-27_19-45-48-768x685.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/2024-11-27_19-45-48-1536x1371.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/2024-11-27_19-45-48-1150x1026.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/2024-11-27_19-45-48-750x669.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/2024-11-27_19-45-48-400x357.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/2024-11-27_19-45-48-250x223.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/2024-11-27_19-45-48.jpg 1598w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Next configure the DMA as following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Circular Mode to Enable.<\/li>\n\n\n\n<li>Request is TIM3_CH1.<\/li>\n\n\n\n<li>Set the direction to be Memory to Peripheral.<\/li>\n\n\n\n<li>From Data source, set the address increment to enabled and data width to half-word.<\/li>\n\n\n\n<li>From Destination data, set the data width to half word and make sure address increment is disabled.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"985\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-22_07-06-13-985x1024.jpg\" alt=\"\" class=\"wp-image-3099\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-22_07-06-13-985x1024.jpg 985w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-22_07-06-13-289x300.jpg 289w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-22_07-06-13-768x798.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-22_07-06-13-1477x1536.jpg 1477w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-22_07-06-13-1150x1196.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-22_07-06-13-750x780.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-22_07-06-13-400x416.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-22_07-06-13-250x260.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/2024-12-22_07-06-13.jpg 1818w\" sizes=\"(max-width: 985px) 100vw, 985px\" \/><\/figure>\n\n\n\n<p>Thats all for the STM32CubeMX configuration.<\/p>\n\n\n\n<p>Save the project and this shall generate the project.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Firmware Development:<\/h2>\n\n\n\n<p>Once the project has been generated, main.c shall be opened.<\/p>\n\n\n\n<p>In main.c, in user begin PV (private variables), declare the following array:<\/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;}\">#define sample_size\t\t220\n\n\nuint16_t lookUp1[sample_size] = {0,50 ,100 ,151 ,201 ,250 ,300 ,349 ,398 ,446 ,494 ,542 ,589 ,635 ,681\n\t,726 ,771 ,814 ,857 ,899 ,940 ,981 ,1020 ,1058 ,1095 ,1131 ,1166 ,1200 ,1233 ,1264\n\t,1294 ,1323 ,1351 ,1377 ,1402 ,1426 ,1448 ,1468 ,1488 ,1505 ,1522 ,1536 ,1550 ,1561\n\t,1572 ,1580 ,1587 ,1593 ,1597 ,1599 ,1600 ,1599 ,1597 ,1593 ,1587 ,1580 ,1572 ,1561\n\t,1550 ,1536 ,1522 ,1505 ,1488 ,1468 ,1448 ,1426 ,1402 ,1377 ,1351 ,1323 ,1294 ,1264\n\t,1233 ,1200 ,1166 ,1131 ,1095 ,1058 ,1020 ,981 ,940 ,899 ,857 ,814 ,771 ,726 ,681 ,635\n\t,589 ,542 ,494 ,446 ,398 ,349 ,300 ,250 ,201 ,151 ,100 ,50,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0\n\t,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0\n\t,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0\n\t,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 };\n<\/pre><\/div>\n\n\n\n<p>This is an example array, it will depend on your application.<\/p>\n\n\n\n<p>In user code begin 2 of the main function, we shall start the timer in PWM mode with DMA 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;}\">HAL_TIM_PWM_Start_DMA(&amp;htim3, TIM_CHANNEL_1, (uint32_t)&amp;lookUp1, sizeof(lookUp1));<\/pre><\/div>\n\n\n\n<p>The function, <strong>HAL_TIM_PWM_Start_DMA<\/strong> takes the following parameters:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Handletypedef for the timer which is timer 3 (htim3) in this case.<\/li>\n\n\n\n<li>Timer channel which is channel 1 (TIM_CHANNEL_1).<\/li>\n\n\n\n<li>Array which hold the duty cycle array.<\/li>\n\n\n\n<li>Size of the array.<\/li>\n<\/ul>\n\n\n\n<p>hats all for the firmware development.<\/p>\n\n\n\n<p>Save the project, build it and run it on your STM32H563Zi board.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/07\/2024-07-12_15-03-3.jpg\" alt=\"\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">4. Results:<\/h2>\n\n\n\n<p>By probing PA6 with either oscilloscope or logic analyzer, you should get the following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"480\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/DS1Z_QuickPrint1.png\" alt=\"\" class=\"wp-image-3100\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/DS1Z_QuickPrint1.png 800w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/DS1Z_QuickPrint1-300x180.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/DS1Z_QuickPrint1-768x461.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/DS1Z_QuickPrint1-750x450.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/DS1Z_QuickPrint1-400x240.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/12\/DS1Z_QuickPrint1-250x150.png 250w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/figure>\n\n\n\n<p>Note: If you are using logic analyzer, it will appear slightly different.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Happy coding \ud83d\ude09<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this guide, we shall use the DMA to update the duty cycle of the PWM to generate custom waveform like sinewave etc and the benefits of such approach. In this guide, we shall cover the following: 1. Why Update PWM Duty Cycle using DMA: Using DMA (Direct Memory Access) to update PWM (Pulse Width [&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-3096","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\/3096"}],"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=3096"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/3096\/revisions"}],"predecessor-version":[{"id":3101,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/3096\/revisions\/3101"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3096"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3096"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3096"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}