{"id":3779,"date":"2025-09-20T08:17:45","date_gmt":"2025-09-20T08:17:45","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=3779"},"modified":"2025-09-20T08:22:10","modified_gmt":"2025-09-20T08:22:10","slug":"emulating-i2c-sensors-part-5-control-rate-of-the-conversion","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=3779","title":{"rendered":"Emulating I2C Sensors Part 5: Control Rate of the Conversion"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"414\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/Untitled-1-2-2-1024x414.jpg\" alt=\"\" class=\"wp-image-3780\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/Untitled-1-2-2-1024x414.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/Untitled-1-2-2-300x121.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/Untitled-1-2-2-768x311.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/Untitled-1-2-2-1150x465.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/Untitled-1-2-2-750x303.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/Untitled-1-2-2-400x162.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/Untitled-1-2-2-250x101.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/Untitled-1-2-2.jpg 1365w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>In this part of the guide, we will extend the emulated sensor by introducing control over the rate of its internal ADC conversions. By adjusting this rate, the slave STM32 can mimic real-world sensors that allow the master to configure sampling frequency, enabling more realistic testing and system validation.<\/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>Why this is important.<\/li>\n\n\n\n<li>Slave configuration.<\/li>\n\n\n\n<li>Slave firmware.<\/li>\n\n\n\n<li>Master firmware.<\/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 this is Important:<\/h2>\n\n\n\n<h4 class=\"wp-block-heading\">1.1. Mimicking Real Sensor Timing<\/h4>\n\n\n\n<p>Real sensors often use internal clocking or timers to schedule ADC conversions at fixed intervals. By using an STM32 timer to control when new ADC values are generated, the emulated sensor reproduces this exact timing behavior, ensuring the master only sees fresh data at the expected rate.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h4 class=\"wp-block-heading\">1.2. Preventing Unrealistic Data Updates<\/h4>\n\n\n\n<p>Without timer control, the slave could update its ADC values every time the master requests them, which is not how real devices work. A timer enforces proper pacing, so the master cannot poll faster than the sensor can realistically respond.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h4 class=\"wp-block-heading\">1.3. Power and Performance Modeling<\/h4>\n\n\n\n<p>In actual sensors, slower timer-driven sampling reduces power consumption, while faster timers increase responsiveness. By tying the conversion rate to a timer, the emulator can simulate both low-power and high-performance modes, which is vital for system-level power and performance testing.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h4 class=\"wp-block-heading\">1.4. Synchronization with Master Requests<\/h4>\n\n\n\n<p>The master device may expect new data only after a fixed conversion interval. A timer ensures that new ADC values are generated consistently and predictably, preventing synchronization issues, buffer overruns, or stale data being read repeatedly.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h4 class=\"wp-block-heading\">1.5. Configurable Test Scenarios<\/h4>\n\n\n\n<p>Since timers on STM32 can be dynamically configured, the emulator can easily switch between different conversion rates by adjusting timer settings. This allows developers to test how the master behaves under different sensor modes (e.g., 1 Hz, 10 Hz, or 1 kHz sampling).<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h4 class=\"wp-block-heading\">1.6. Data Integrity Validation<\/h4>\n\n\n\n<p>By generating ADC values strictly on timer events, it becomes easier to guarantee that data integrity is preserved\u2014one fresh sample per timer period. This aligns with how real sensors guarantee a stable and predictable data flow.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<p>&nbsp;<strong>In summary:<\/strong><br>Using a timer to control ADC conversion rate in the emulated slave makes the behavior much closer to a real-world sensor. It ensures accurate timing, prevents unrealistic data availability, and provides a flexible way to simulate different operating modes for reliable system testing.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th><strong>Aspect<\/strong><\/th><th><strong>Why It Matters<\/strong><\/th><\/tr><\/thead><tbody><tr><td><strong>Mimicking Real Sensors<\/strong><\/td><td>Real sensors rely on internal clocks\/timers to schedule ADC conversions; using STM32 timer makes the emulation realistic.<\/td><\/tr><tr><td><strong>Preventing Unrealistic Updates<\/strong><\/td><td>Stops the slave from generating new data on every master request, ensuring pacing matches real hardware.<\/td><\/tr><tr><td><strong>Power &amp; Performance Modeling<\/strong><\/td><td>Timer-driven sampling allows simulating low-power slow modes vs. high-performance fast modes.<\/td><\/tr><tr><td><strong>Master Synchronization<\/strong><\/td><td>Ensures fresh data is only available at predictable intervals, preventing buffer overruns or stale reads.<\/td><\/tr><tr><td><strong>Configurable Scenarios<\/strong><\/td><td>Timer settings can be changed to test different sensor operating frequencies (e.g., 1 Hz, 10 Hz, 1 kHz).<\/td><\/tr><tr><td><strong>Data Integrity<\/strong><\/td><td>Guarantees exactly one new sample per timer tick, avoiding inconsistent or duplicate data.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. Slave Configuration:<\/h2>\n\n\n\n<p>Open the slave .ioc file from project explorer. Once the i.oc opened, STM32CubeMX configuration tool will appear.<\/p>\n\n\n\n<p>From Analog, select ADC1 and enable IN0, IN1 and IN4. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"655\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-31-04-1024x655.jpg\" alt=\"\" class=\"wp-image-3781\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-31-04-1024x655.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-31-04-300x192.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-31-04-768x491.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-31-04-1536x982.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-31-04-1150x735.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-31-04-750x479.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-31-04-400x256.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-31-04-250x160.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-31-04.jpg 1558w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>These pins are PA0, PA1 and PA4 respectively. These pins are A0, A1 and A2 of Arduino pin headers.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"800\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-34-23-1024x800.jpg\" alt=\"\" class=\"wp-image-3782\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-34-23-1024x800.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-34-23-300x235.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-34-23-768x600.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-34-23-1536x1201.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-34-23-1150x899.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-34-23-750x586.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-34-23-400x313.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-34-23-250x195.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-34-23.jpg 1860w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, configure the ADC as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Resolution to 8 bit.<\/li>\n\n\n\n<li>Scan Conversion to Enabled.<\/li>\n\n\n\n<li>DMA Continuous Requests to Enabled.<\/li>\n\n\n\n<li>Number of conversions to 3.<\/li>\n\n\n\n<li>External trigger to Timer 2 trigger out event.<\/li>\n\n\n\n<li>Rank 1 to CH0, Rank 2 to CH1 and Rank 3 to CH4.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"705\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-35-21-705x1024.jpg\" alt=\"\" class=\"wp-image-3783\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-35-21-705x1024.jpg 705w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-35-21-207x300.jpg 207w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-35-21-768x1115.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-35-21-750x1089.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-35-21-400x581.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-35-21-250x363.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-35-21.jpg 1026w\" sizes=\"(max-width: 705px) 100vw, 705px\" \/><\/figure>\n\n\n\n<p>Next, configure the DMA as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Mode to circular.<\/li>\n\n\n\n<li>Data width to Byte for Peripheral and Memory.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"648\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-40-13-1024x648.jpg\" alt=\"\" class=\"wp-image-3784\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-40-13-1024x648.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-40-13-300x190.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-40-13-768x486.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-40-13-1150x728.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-40-13-750x475.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-40-13-400x253.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-40-13-250x158.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-40-13.jpg 1412w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, from Timers select TIM2:<\/p>\n\n\n\n<p>Configure it as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Clock source to internal.<\/li>\n\n\n\n<li>PSC to 16000-1.<\/li>\n\n\n\n<li>Counter period to 100-1.<\/li>\n\n\n\n<li>Auto-reload preload to Enabled.<\/li>\n\n\n\n<li>Trigger Event selection to Update Event.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"824\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-42-37-1024x824.jpg\" alt=\"\" class=\"wp-image-3785\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-42-37-1024x824.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-42-37-300x242.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-42-37-768x618.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-42-37-1536x1237.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-42-37-1150x926.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-42-37-750x604.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-42-37-400x322.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-42-37-250x201.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/2025-09-20_10-42-37.jpg 1940w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Thats all for the slave configuration. Save the project and the project shall be configured.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Slave Firmware:<\/h2>\n\n\n\n<p>Once the project is configured, main.c will be opened.<\/p>\n\n\n\n<p>In user code begin PV, 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;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">uint8_t ADC_Data[3];<\/pre><\/div>\n\n\n\n<p>This array shall hold the converted ADC data.<\/p>\n\n\n\n<p>We shall nominate ConfigReg1 for rate control<\/p>\n\n\n\n<p>The rate as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>0 -&gt; 100ms<\/li>\n\n\n\n<li>1 -&gt; 50ms<\/li>\n\n\n\n<li>2 -&gt; 10ms<\/li>\n<\/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;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">#define ConfigReg1 0x00  \/*Rate of conversion 0-&gt; 100ms  1-&gt;50ms   2-&gt; 10ms*\/\n\n#define ConfigReg2 0x01\t \/*Interrupt Generation , To be handled later*\/\n\n#define ReadReg1 0x03   \/\/Read ADC Data<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, in <strong>HAL_I2C_SlaveRxCpltCallback<\/strong> function, modify the storage for register as follows:<\/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_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)\n{\n    if (hi2c-&gt;Instance == I2C1)\n    {\n\n            CurrentRegister = RegisterData[0]; \/\/ first byte = register\n\n            if (CurrentRegister == ConfigReg1)\n            {\n                switch ( RegisterData[1])\n                {\n                \tcase 0: __HAL_TIM_SET_AUTORELOAD(&amp;htim2, 100-1);\n                \t\tbreak;\n                \tcase 1: __HAL_TIM_SET_AUTORELOAD(&amp;htim2, 50-1);\n                \t\tbreak;\n                \tcase 2: __HAL_TIM_SET_AUTORELOAD(&amp;htim2, 10-1);\n                \t\tbreak;\n                \tdefault: __HAL_TIM_SET_AUTORELOAD(&amp;htim2, 100-1);\n                \t\tbreak;\n\n                }\n            }\n            else if (CurrentRegister == ConfigReg2)\n            {\n                ConfigReg2Value = RegisterData[1];\n            }\n    }\n\n\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>This function is the&nbsp;<strong>I\u00b2C slave receive complete callback<\/strong>&nbsp;\u2014 it runs whenever the STM32 (acting as an I\u00b2C slave) successfully receives data from the master. Let\u2019s break it down step by step:<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h5 class=\"wp-block-heading\">1. Callback condition<\/h5>\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;}\">if (hi2c-&gt;Instance == I2C1)\n<\/pre><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ensures the callback is only executed if the I\u00b2C peripheral involved is&nbsp;<code>I2C1<\/code>.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h5 class=\"wp-block-heading\">2. Decode the received register address<\/h5>\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;}\">CurrentRegister = RegisterData[0]; \/\/ first byte = register\n<\/pre><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The first byte sent by the master is treated as a&nbsp;<strong>register address<\/strong>&nbsp;(e.g., ConfigReg1, ConfigReg2, etc.).<\/li>\n\n\n\n<li>This tells the slave which register the master is trying to configure.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h5 class=\"wp-block-heading\">3. Handling&nbsp;<code>ConfigReg1<\/code><\/h5>\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;}\">if (CurrentRegister == ConfigReg1)\n{\n    switch (RegisterData[1])\n    {\n        case 0: __HAL_TIM_SET_AUTORELOAD(&amp;htim2, 100-1); break;\n        case 1: __HAL_TIM_SET_AUTORELOAD(&amp;htim2, 50-1);  break;\n        case 2: __HAL_TIM_SET_AUTORELOAD(&amp;htim2, 10-1);  break;\n        default: __HAL_TIM_SET_AUTORELOAD(&amp;htim2, 100-1); break;\n    }\n}\n<\/pre><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>If the master wrote to&nbsp;<code>ConfigReg1<\/code>:\n<ul class=\"wp-block-list\">\n<li>The&nbsp;<strong>second byte<\/strong>&nbsp;(<code>RegisterData[1]<\/code>) is interpreted as a mode or setting.<\/li>\n\n\n\n<li>Depending on the value (0, 1, 2, or other), the code changes the&nbsp;<strong>auto-reload value<\/strong>&nbsp;of&nbsp;<code>TIM2<\/code>.<\/li>\n\n\n\n<li><code>__HAL_TIM_SET_AUTORELOAD<\/code>&nbsp;sets the timer\u2019s ARR register, which controls the&nbsp;<strong>period of the timer interrupt<\/strong>.\n<ul class=\"wp-block-list\">\n<li>Smaller ARR \u2192 faster timer interrupts (higher update rate).<\/li>\n\n\n\n<li>Larger ARR \u2192 slower timer interrupts (lower update rate).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Example:\n<ul class=\"wp-block-list\">\n<li><code>case 0<\/code>&nbsp;\u2192 ARR = 99 \u2192 slower ADC sampling.<\/li>\n\n\n\n<li><code>case 2<\/code>&nbsp;\u2192 ARR = 9 \u2192 much faster ADC sampling.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>In other words,&nbsp;<strong>ConfigReg1 controls the ADC sampling rate through Timer2<\/strong>.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>For the <strong>AL_I2C_AddrCallback<\/strong>, when read request happen, transmit the new ADC value<\/p>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)\n{\n\n\tif(hi2c-&gt;Instance==I2C1)\n\t{\n\n\t\tif(TransferDirection==I2C_DIRECTION_TRANSMIT)\n\t\t{\n\n\t\t\tHAL_I2C_Slave_Seq_Receive_IT(hi2c, RegisterData, 2, I2C_FIRST_FRAME);\n\n\t\t}\n\n\t\telse\n\t\t{\n            if (RegisterData[0] == ReadReg1)   \/\/ &lt;-- prepare fresh data here\n            {\n                SensorData[0] = ADC_Data[0];\n                SensorData[1] = ADC_Data[1];\n                SensorData[2] = ADC_Data[2];\n            }\n\t\t\tHAL_I2C_Slave_Seq_Transmit_IT(hi2c,SensorData, 3, I2C_FIRST_AND_LAST_FRAME);\n\t\t}\n\n\n\t}\n\n}<\/pre><\/div>\n\n\n\n<p>t runs every time the master addresses your STM32 slave (<code>I2C1<\/code>) and indicates whether the master wants to&nbsp;<strong>write<\/strong>(transmit) or&nbsp;<strong>read<\/strong>&nbsp;from the slave.<\/p>\n\n\n\n<p>Let\u2019s go step by step:<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h5 class=\"wp-block-heading\">1. Make sure it\u2019s the right I\u00b2C peripheral<\/h5>\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;}\">if (hi2c-&gt;Instance == I2C1)\n<\/pre><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Only handle events for&nbsp;<code>I2C1<\/code>.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h5 class=\"wp-block-heading\">2. Master \u2192 Slave (Write direction)<\/h5>\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;}\">if (TransferDirection == I2C_DIRECTION_TRANSMIT)\n{\n    HAL_I2C_Slave_Seq_Receive_IT(hi2c, RegisterData, 2, I2C_FIRST_FRAME);\n}\n<\/pre><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The master wants to&nbsp;<strong>send data to the slave<\/strong>.<\/li>\n\n\n\n<li>The slave prepares to receive&nbsp;<strong>2 bytes<\/strong>&nbsp;into&nbsp;<code>RegisterData[]<\/code>:\n<ul class=\"wp-block-list\">\n<li><code>RegisterData[0]<\/code>&nbsp;\u2192 register address (e.g., ConfigReg1, ReadReg1, etc.)<\/li>\n\n\n\n<li><code>RegisterData[1]<\/code>&nbsp;\u2192 value to be written.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Using&nbsp;<code>I2C_FIRST_FRAME<\/code>&nbsp;means this may be part of a longer I\u00b2C transaction.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h5 class=\"wp-block-heading\">3. Master \u2190 Slave (Read direction)<\/h5>\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;}\">else\n{\n    if (RegisterData[0] == ReadReg1)   \/\/ &lt;-- prepare fresh data here\n    {\n        SensorData[0] = ADC_Data[0];\n        SensorData[1] = ADC_Data[1];\n        SensorData[2] = ADC_Data[2];\n    }\n    HAL_I2C_Slave_Seq_Transmit_IT(hi2c, SensorData, 3, I2C_FIRST_AND_LAST_FRAME);\n}\n<\/pre><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The master wants to&nbsp;<strong>read from the slave<\/strong>.<\/li>\n\n\n\n<li>Before sending data, the slave checks if the&nbsp;<strong>last register accessed was&nbsp;<code>ReadReg1<\/code><\/strong>:\n<ul class=\"wp-block-list\">\n<li>If yes, it loads fresh ADC values into&nbsp;<code>SensorData[]<\/code>.<\/li>\n\n\n\n<li>That way, the master always gets&nbsp;<strong>up-to-date sensor data<\/strong>.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Then it starts a&nbsp;<strong>non-blocking transmit<\/strong>&nbsp;of 3 bytes (<code>SensorData[]<\/code>) back to the master.<\/li>\n\n\n\n<li>The flag&nbsp;<code>I2C_FIRST_AND_LAST_FRAME<\/code>&nbsp;means this is both the&nbsp;<strong>start and end<\/strong>&nbsp;of the transfer.<\/li>\n<\/ul>\n\n\n\n<p><\/p>\n\n\n\n<p>Finally, in user code begin 2 in main function:<\/p>\n\n\n\n<p>Simply, start the ADC in DMA mode and start the timer as follows:<\/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, ADC_Data, 3);\n\n  HAL_TIM_Base_Start(&amp;htim2);<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Thats all for the slave configuration. Save the project and run it on your MCU as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"34\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/07\/2025-07-03_17-48-35-1024x34.jpg\" alt=\"\" class=\"wp-image-3598\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/07\/2025-07-03_17-48-35-1024x34.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/07\/2025-07-03_17-48-35-300x10.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/07\/2025-07-03_17-48-35-768x25.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/07\/2025-07-03_17-48-35-1536x51.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/07\/2025-07-03_17-48-35-2048x68.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/07\/2025-07-03_17-48-35-1150x38.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/07\/2025-07-03_17-48-35-750x25.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/07\/2025-07-03_17-48-35-400x13.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/07\/2025-07-03_17-48-35-250x8.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. Master Firmware:<\/h2>\n\n\n\n<p>In main.c file of the master STM32, in user code begin 2 in main function:<\/p>\n\n\n\n<p>Configure the conversion rate to be 10ms by sending q2 as follows:<\/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  SlaveData[0]=0x00;\n  \t  SlaveData[1]=2;\n  \t  HAL_I2C_Master_Transmit(&amp;hi2c1, (0x1D&lt;&lt;1), &amp;SlaveData, 2, 100);<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>In user code begin 3 in while loop:<\/p>\n\n\n\n<p>Read the sensor ADC data as follows:<\/p>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\t  HAL_I2C_Mem_Read(&amp;hi2c1, (0x1D&lt;&lt;1), 0x03, 1, SensorData, 3, 100);\n\t  HAL_Delay(100);<\/pre><\/div>\n\n\n\n<p>That all for the master configuration. Save the project and start a debugging session as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"43\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/07\/image-1024x43.png\" alt=\"\" class=\"wp-image-3600\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/07\/image-1024x43.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/07\/image-300x13.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/07\/image-768x32.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/07\/image-1536x65.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/07\/image-1150x48.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/07\/image-750x31.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/07\/image-400x17.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/07\/image-250x10.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/07\/image.png 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">5. Results:<\/h2>\n\n\n\n<p>Before sending the conversion rate value, the ADC converts the channels each 100ms:<\/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\/09\/RigolDS9.png\" alt=\"\" class=\"wp-image-3786\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/RigolDS9.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/RigolDS9-300x185.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/RigolDS9-768x473.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/RigolDS9-750x461.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/RigolDS9-400x246.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/RigolDS9-250x154.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Once the master has transferred the configuration data, the ADC shall convert the channels each 10ms as shown:<\/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\/09\/RigolDS10.png\" alt=\"\" class=\"wp-image-3787\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/RigolDS10.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/RigolDS10-300x185.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/RigolDS10-768x473.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/RigolDS10-750x461.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/RigolDS10-400x246.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/RigolDS10-250x154.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>By adding SensorData to Live expressions in the debugging session, you should get 3 ADC as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"483\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/ezgif-14d403091b2b1c.gif\" alt=\"\" class=\"wp-image-3742\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Here is a sample from the decoded bus:<\/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\/09\/RigolDS11.png\" alt=\"\" class=\"wp-image-3788\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/RigolDS11.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/RigolDS11-300x185.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/RigolDS11-768x473.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/RigolDS11-750x461.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/RigolDS11-400x246.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/09\/RigolDS11-250x154.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>In next part, we shall introduce interrupt generation to generate high level to inform the master there is new data. Stay tuned.<\/p>\n\n\n\n<p>Happy coding \ud83d\ude09<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this part of the guide, we will extend the emulated sensor by introducing control over the rate of its internal ADC conversions. By adjusting this rate, the slave STM32 can mimic real-world sensors that allow the master to configure sampling frequency, enabling more realistic testing and system validation. In this guide, we shall cover [&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-3779","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\/3779"}],"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=3779"}],"version-history":[{"count":3,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/3779\/revisions"}],"predecessor-version":[{"id":3791,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/3779\/revisions\/3791"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3779"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3779"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3779"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}