{"id":3447,"date":"2025-05-10T13:32:43","date_gmt":"2025-05-10T13:32:43","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=3447"},"modified":"2025-05-10T13:33:00","modified_gmt":"2025-05-10T13:33:00","slug":"stm32-adc-application-part-2-single-conversion-using-interrupt-and-dma","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=3447","title":{"rendered":"STM32 ADC Application Part 2: Single Conversion using interrupt and DMA"},"content":{"rendered":"\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"920\" height=\"368\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/Untitled-1.jpg\" alt=\"\" class=\"wp-image-3450\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/Untitled-1.jpg 920w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/Untitled-1-300x120.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/Untitled-1-768x307.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/Untitled-1-750x300.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/Untitled-1-400x160.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/Untitled-1-250x100.jpg 250w\" sizes=\"(max-width: 920px) 100vw, 920px\" \/><\/figure>\n\n\n\n<p>In this second part of the ADC series on STM32, we explore how to handle single-channel, single-conversion ADC using interrupts and DMA. To enhance efficiency and reduce CPU load, these methods enable automatic data handling upon conversion completion, making them ideal for responsive and real-time applications.<\/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 using interrupt and 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<h2 class=\"wp-block-heading\">1. Why Using Interrupt and DMA:<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Why Use Interrupts and DMA with ADC on STM32?<\/h3>\n\n\n\n<p>In embedded systems, the Analog-to-Digital Converter (ADC) is a crucial peripheral that allows microcontrollers to interact with the analog world\u2014whether it&#8217;s monitoring sensor voltages, reading battery levels, or sampling audio signals. While polling is the simplest method to check for conversion completion, it is often inefficient and unsuitable for time-critical or power-sensitive applications. This is where&nbsp;<strong>interrupts<\/strong>&nbsp;and&nbsp;<strong>Direct Memory Access (DMA)<\/strong>&nbsp;come into play.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h4 class=\"wp-block-heading\">The Limitations of Polling<\/h4>\n\n\n\n<p>In polling mode, the CPU must constantly check a status flag (typically the End Of Conversion bit) to determine when the ADC has completed a conversion. This approach has several drawbacks:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Wastes CPU Cycles<\/strong>: The processor is stuck in a loop doing nothing useful while waiting for the conversion to finish.<\/li>\n\n\n\n<li><strong>Increases Power Consumption<\/strong>: Since the CPU stays active during polling, it consumes more power, which is problematic for battery-powered devices.<\/li>\n\n\n\n<li><strong>Poor Responsiveness<\/strong>: Polling occupies CPU time that could be used for other tasks, reducing the system&#8217;s responsiveness and multitasking capabilities.<\/li>\n\n\n\n<li><strong>Not Scalable<\/strong>: As the number of ADC channels or sampling frequency increases, polling quickly becomes impractical.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h4 class=\"wp-block-heading\">Benefits of Using Interrupts<\/h4>\n\n\n\n<p>With&nbsp;<strong>interrupt-driven ADC<\/strong>, the microcontroller is notified only when a conversion is complete. This offers several advantages:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Non-blocking Operation<\/strong>: The CPU can perform other tasks or enter a low-power mode while the ADC is converting.<\/li>\n\n\n\n<li><strong>Improved Efficiency<\/strong>: The application becomes event-driven, reducing unnecessary CPU usage.<\/li>\n\n\n\n<li><strong>Real-time Response<\/strong>: Suitable for applications that require immediate action after conversion (e.g., threshold detection, digital control loops).<\/li>\n\n\n\n<li><strong>Simpler Code Structure<\/strong>: Interrupt service routines (ISRs) allow clean separation between triggering and handling ADC events.<\/li>\n<\/ul>\n\n\n\n<p>However, in high-speed sampling or continuous conversions, interrupt frequency may become too high, leading to increased context-switching overhead.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h4 class=\"wp-block-heading\">Advantages of Using DMA with ADC<\/h4>\n\n\n\n<p><strong>DMA (Direct Memory Access)<\/strong>&nbsp;takes efficiency a step further by offloading data transfers from the CPU entirely:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Automatic Data Transfer<\/strong>: Conversion results are moved directly from the ADC data register to a memory buffer without CPU intervention.<\/li>\n\n\n\n<li><strong>Ideal for High-Speed Sampling<\/strong>: Perfect for applications such as audio acquisition, waveform analysis, or oscilloscope-like interfaces, where large volumes of data need to be moved rapidly.<\/li>\n\n\n\n<li><strong>Low CPU Overhead<\/strong>: Frees up the processor to handle only post-processing or higher-level logic, not data movement.<\/li>\n\n\n\n<li><strong>Supports Circular Buffering<\/strong>: DMA can be configured in circular mode for continuous acquisition and processing, useful in filters or rolling-average calculations.<\/li>\n\n\n\n<li><strong>Deterministic Timing<\/strong>: Since DMA operations happen in hardware, timing is consistent and not affected by software jitter.<\/li>\n<\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. STM32CubeIDE Setup:<\/h2>\n\n\n\n<p>From the setup of the previous guide from <a href=\"https:\/\/blog.embeddedexpert.io\/?p=3409\" data-type=\"link\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=3409\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n\n\n\n<p>Open.ioc file and STM32CubeMX window shall appear.<\/p>\n\n\n\n<p>From analog section, select NVIC Setting and enable ADC1 and ADC2 interrupts as following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"873\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/2025-05-10_16-14-38-873x1024.jpg\" alt=\"\" class=\"wp-image-3452\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/2025-05-10_16-14-38-873x1024.jpg 873w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/2025-05-10_16-14-38-256x300.jpg 256w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/2025-05-10_16-14-38-768x901.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/2025-05-10_16-14-38-1309x1536.jpg 1309w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/2025-05-10_16-14-38-1150x1349.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/2025-05-10_16-14-38-750x880.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/2025-05-10_16-14-38-400x469.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/2025-05-10_16-14-38-250x293.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/2025-05-10_16-14-38.jpg 1502w\" sizes=\"(max-width: 873px) 100vw, 873px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, from DMA Settings, enable the DMA as following:<\/p>\n\n\n\n<p>Make sure to set the mode to normal not circular.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"903\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/2025-05-10_16-16-17-1024x903.jpg\" alt=\"\" class=\"wp-image-3453\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/2025-05-10_16-16-17-1024x903.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/2025-05-10_16-16-17-300x264.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/2025-05-10_16-16-17-768x677.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/2025-05-10_16-16-17-1150x1014.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/2025-05-10_16-16-17-750x661.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/2025-05-10_16-16-17-400x353.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/2025-05-10_16-16-17-250x220.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/05\/2025-05-10_16-16-17.jpg 1436w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Thats all for the configuration. Save the project and it will 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<h2 class=\"wp-block-heading\">3.1 Interrupt Method:<\/h2>\n\n\n\n<p>In user code begin PV declare extra variable to handle the interrupt 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;}\">volatile uint8_t ADC_Completed=0;<\/pre><\/div>\n\n\n\n<p>This variable shall set to 1 once the ADC conversion is completed and adcConvCmpltCallback is called<\/p>\n\n\n\n<p>In user code begin 2 in main function, start the adc in interrupt mode 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;}\">HAL_ADC_Start_IT(&amp;hadc1);<\/pre><\/div>\n\n\n\n<p>Once the conversion is completed, the <strong>HAL_ADC_ConvCpltCallback<\/strong> function shall be called 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;}\">void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)\n{\n\tif(hadc-&gt;Instance==ADC1)\n\t{\n\t\tADC_Completed=1;\n\t\t\n\t}\n\n}<\/pre><\/div>\n\n\n\n<p>Within the callback function, check if the interrupt source is ADC1 or not. If it is, set ADC_Completed to 1.<\/p>\n\n\n\n<p>In while 1 loop:<\/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;}\">while(ADC_Completed==0);\nADC_Completed=0;\nadcValue = HAL_ADC_GetValue(&amp;hadc1);\nHAL_ADC_Start_IT(&amp;hadc1);<\/pre><\/div>\n\n\n\n<p>Wait until the ADC_Completed is set to 1.<\/p>\n\n\n\n<p>Once it has been set, reset it back to zero, get the ADC value and start the ADC again and loop shall continue like this forever.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3.2 DMA Method:<\/h2>\n\n\n\n<p>In user code begin 2 in main function, start the ADC in DMA mode 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;}\">HAL_ADC_Start_DMA(&amp;hadc1, (uint32_t)&amp;adcValue, 1);<\/pre><\/div>\n\n\n\n<p>The function shall take the following parameters:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>instant to the ADC which is hadc1 in this case.<\/li>\n\n\n\n<li>Address of the variable or array to hold the converted data.<\/li>\n\n\n\n<li>Size of the data which is 1 in this case.<\/li>\n<\/ul>\n\n\n\n<p>Once the conversion is completed, the <strong>HAL_ADC_ConvCpltCallback<\/strong> function shall be called 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;}\">void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)\n{\n\tif(hadc-&gt;Instance==ADC1)\n\t{\n\t\tHAL_ADC_Start_DMA(&amp;hadc1, (uint32_t)&amp;adcValue, 1);\n\t}\n\n}<\/pre><\/div>\n\n\n\n<p>Note that in this case, we don&#8217;t need to set the variable and only start the ADC in DMA once again.<\/p>\n\n\n\n<p>While loop should be empty.<\/p>\n\n\n\n<p>Thats all for the firmware development.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. Results:<\/h2>\n\n\n\n<p>Start a debug session and add adcValue to live expression<\/p>\n\n\n\n<p>When the pot is near the GND wire, you will get zero or near zero value as following:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"40\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/04\/Screenshot-2025-04-24-at-4.41.06\u202fPM-1024x40.png\" alt=\"\" class=\"wp-image-3415\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/04\/Screenshot-2025-04-24-at-4.41.06\u202fPM-1024x40.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/04\/Screenshot-2025-04-24-at-4.41.06\u202fPM-300x12.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/04\/Screenshot-2025-04-24-at-4.41.06\u202fPM-768x30.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/04\/Screenshot-2025-04-24-at-4.41.06\u202fPM-750x30.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/04\/Screenshot-2025-04-24-at-4.41.06\u202fPM-400x16.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/04\/Screenshot-2025-04-24-at-4.41.06\u202fPM-250x10.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/04\/Screenshot-2025-04-24-at-4.41.06\u202fPM.png 1066w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>On the other size of the pot:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"85\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/04\/2025-04-24_16-42-25-1024x85.jpg\" alt=\"\" class=\"wp-image-3416\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/04\/2025-04-24_16-42-25-1024x85.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/04\/2025-04-24_16-42-25-300x25.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/04\/2025-04-24_16-42-25-768x64.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/04\/2025-04-24_16-42-25-750x62.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/04\/2025-04-24_16-42-25-400x33.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/04\/2025-04-24_16-42-25-250x21.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/04\/2025-04-24_16-42-25.jpg 1058w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>We have successfully created ADC driver that uses either DMA or interrupt to get the data.<\/p>\n\n\n\n<p>Stay tuned where we shall cover the continuous mode in all three cases.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Stay tuned.<\/p>\n\n\n\n<p>Happy coding \ud83d\ude09<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this second part of the ADC series on STM32, we explore how to handle single-channel, single-conversion ADC using interrupts and DMA. To enhance efficiency and reduce CPU load, these methods enable automatic data handling upon conversion completion, making them ideal for responsive and real-time applications. 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-3447","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\/3447"}],"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=3447"}],"version-history":[{"count":3,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/3447\/revisions"}],"predecessor-version":[{"id":3455,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/3447\/revisions\/3455"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3447"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3447"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3447"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}