{"id":4197,"date":"2026-01-29T08:15:46","date_gmt":"2026-01-29T08:15:46","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=4197"},"modified":"2026-01-29T08:15:48","modified_gmt":"2026-01-29T08:15:48","slug":"modbus-sensor-emulation-part-3-master-request-to-read","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=4197","title":{"rendered":"Modbus Sensor Emulation Part 3: Master Request to Read"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"683\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/ChatGPT-Image-Jan-6-2026-at-09_38_15-AM-2-1024x683.png\" alt=\"\" class=\"wp-image-4198\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/ChatGPT-Image-Jan-6-2026-at-09_38_15-AM-2-1024x683.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/ChatGPT-Image-Jan-6-2026-at-09_38_15-AM-2-300x200.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/ChatGPT-Image-Jan-6-2026-at-09_38_15-AM-2-768x512.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/ChatGPT-Image-Jan-6-2026-at-09_38_15-AM-2-1150x767.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/ChatGPT-Image-Jan-6-2026-at-09_38_15-AM-2-750x500.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/ChatGPT-Image-Jan-6-2026-at-09_38_15-AM-2-400x267.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/ChatGPT-Image-Jan-6-2026-at-09_38_15-AM-2-250x167.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/ChatGPT-Image-Jan-6-2026-at-09_38_15-AM-2.png 1536w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Part 3 of the guide moves beyond basic link verification and introduces practical Modbus RTU transactions in which the master issues read requests to the STM32-based slave. This section focuses on implementing and validating standard read function codes, register addressing, and response formatting so the emulated sensor can return meaningful data in a fully protocol-compliant manner which will be covered next.<\/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>Master Request to Read.<\/li>\n\n\n\n<li>Firmware Development.<\/li>\n\n\n\n<li>Testing and Results.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">1. Master Request to Read:<\/h2>\n\n\n\n<p>When the master request to read data, the data frame as following:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"697\" height=\"192\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/07\/stm_4.webp\" alt=\"\" class=\"wp-image-2656\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/07\/stm_4.webp 697w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/07\/stm_4-300x83.webp 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/07\/stm_4-400x110.webp 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/07\/stm_4-250x69.webp 250w\" sizes=\"(max-width: 697px) 100vw, 697px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>First byte is the address of the slave.<\/li>\n\n\n\n<li>Second byte is the function code.<\/li>\n\n\n\n<li>Third and fourth bytes are the register address high and low byte respectively.<\/li>\n\n\n\n<li>Fifth and sixth bytes are the number of points high and low byte respectively.<\/li>\n\n\n\n<li>The fifth and last are the CRC ow and high byte respectively.<\/li>\n<\/ul>\n\n\n\n<p>This is the typical frame for master request to read from slave.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. Firmware Development:<\/h2>\n\n\n\n<p>First, we shall create header and source file for crc calculation.<\/p>\n\n\n\n<p>Create header and and source file with name of modbus_crc.h and modbus_crc.c respectively as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"881\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/2026-01-29_10-47-46-1024x881.jpg\" alt=\"\" class=\"wp-image-4201\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/2026-01-29_10-47-46-1024x881.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/2026-01-29_10-47-46-300x258.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/2026-01-29_10-47-46-768x661.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/2026-01-29_10-47-46-750x646.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/2026-01-29_10-47-46-400x344.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/2026-01-29_10-47-46-250x215.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/2026-01-29_10-47-46.jpg 1034w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>In modbus_crc.h file, within headerfile guard, declare the following function:<\/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;}\">uint16_t crc16(uint8_t *buffer, uint16_t buffer_length);<\/pre><\/div>\n\n\n\n<p>This function shall calculate the CRC value on the fly.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Hence, the entire header file 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;}\">#ifndef INC_MODBUS_CRC_H_\n#define INC_MODBUS_CRC_H_\n\nuint16_t crc16(uint8_t *buffer, uint16_t buffer_length);\n\n#endif \/* INC_MODBUS_CRC_H_ *\/<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, in modbus_crc, include the following header files:<\/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;stdint.h&quot;\n#include &quot;modbus_crc.h&quot;<\/pre><\/div>\n\n\n\n<p>Declare the following crc high table:<\/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;}\">static const uint8_t table_crc_hi[] = {\n    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,\n    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,\n    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,\n    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,\n    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,\n    0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,\n    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,\n    0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,\n    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,\n    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,\n    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,\n    0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,\n    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,\n    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,\n    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,\n    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,\n    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,\n    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,\n    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,\n    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,\n    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,\n    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,\n    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,\n    0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,\n    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,\n    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40\n};<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>For the low:<\/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;}\">static const uint8_t table_crc_lo[] = {\n    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,\n    0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,\n    0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,\n    0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,\n    0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,\n    0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,\n    0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,\n    0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,\n    0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,\n    0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,\n    0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,\n    0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,\n    0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,\n    0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,\n    0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,\n    0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,\n    0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,\n    0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,\n    0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,\n    0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,\n    0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,\n    0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,\n    0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,\n    0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,\n    0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,\n    0x43, 0x83, 0x41, 0x81, 0x80, 0x40\n};<\/pre><\/div>\n\n\n\n<p>Next, the function shall calculate the crc value 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;}\">uint16_t crc16(uint8_t *buffer, uint16_t buffer_length)\n{\n    uint8_t crc_hi = 0xFF; \/* high CRC byte initialized *\/\n    uint8_t crc_lo = 0xFF; \/* low CRC byte initialized *\/\n    unsigned int i; \/* will index into CRC lookup *\/\n\n    \/* pass through message buffer *\/\n    while (buffer_length--) {\n        i = crc_lo ^ *buffer++; \/* calculate the CRC  *\/\n        crc_lo = crc_hi ^ table_crc_hi[i];\n        crc_hi = table_crc_lo[i];\n    }\n\n    return (crc_hi &lt;&lt; 8 | crc_lo);\n}<\/pre><\/div>\n\n\n\n<p>This function computes a&nbsp;<strong>16-bit Modbus CRC (CRC-16\/IBM)<\/strong>&nbsp;over a byte buffer, which is mandatory for Modbus RTU frames to detect transmission errors.<\/p>\n\n\n\n<p>Here is what each part does:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Function Purpose<\/strong><\/h3>\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;}\">uint16_t crc16(uint8_t *buffer, uint16_t buffer_length)\n<\/pre><\/div>\n\n\n\n<p>Takes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>buffer<\/code>\u00a0\u2192 pointer to the data bytes<\/li>\n\n\n\n<li><code>buffer_length<\/code>\u00a0\u2192 number of bytes to process<\/li>\n<\/ul>\n\n\n\n<p>Returns:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The final 16-bit CRC value appended to Modbus frames.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>CRC Initialization<\/strong><\/h3>\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 crc_hi = 0xFF;\nuint8_t crc_lo = 0xFF;\n<\/pre><\/div>\n\n\n\n<p>Modbus RTU specifies that the CRC register starts at&nbsp;<strong>0xFFFF<\/strong>, so both high and low bytes are initialized to&nbsp;<code>0xFF<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Processing Each Byte<\/strong><\/h3>\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 (buffer_length--) {\n<\/pre><\/div>\n\n\n\n<p>Iterates through every byte in the message.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Index Calculation<\/strong><\/h3>\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;}\">i = crc_lo ^ *buffer++;\n<\/pre><\/div>\n\n\n\n<p>The incoming data byte is XORed with the current&nbsp;<strong>low CRC byte<\/strong>.<br>The result forms an index into the lookup tables.<\/p>\n\n\n\n<p>This avoids doing slow bit-by-bit polynomial calculations.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Lookup Table Update<\/strong><\/h3>\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;}\">crc_lo = crc_hi ^ table_crc_hi[i];\ncrc_hi = table_crc_lo[i];\n<\/pre><\/div>\n\n\n\n<p>Two precomputed tables are used:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>table_crc_hi[]<\/code><\/li>\n\n\n\n<li><code>table_crc_lo[]<\/code><\/li>\n<\/ul>\n\n\n\n<p>They contain the pre-calculated CRC effects for all 256 possible byte values.<\/p>\n\n\n\n<p>The new CRC:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>crc_lo<\/code>\u00a0becomes the old high byte XORed with a lookup value.<\/li>\n\n\n\n<li><code>crc_hi<\/code>\u00a0becomes the corresponding lookup value.<\/li>\n<\/ul>\n\n\n\n<p>This updates the CRC register for the processed byte.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Final Return Value<\/strong><\/h3>\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;}\">return (crc_hi &lt;&lt; 8 | crc_lo);\n<\/pre><\/div>\n\n\n\n<p>Combines the two bytes into a 16-bit result:<\/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;}\">CRC = (high_byte &lt;&lt; 8) | low_byte\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Summary<\/strong><\/h3>\n\n\n\n<p>This is a&nbsp;<strong>table-driven Modbus CRC-16 implementation<\/strong>&nbsp;that:<\/p>\n\n\n\n<p>\u2714 Starts with\u00a0<code>0xFFFF<\/code><br>\u2714 Processes each byte using XOR + lookup tables<br>\u2714 Produces the standard Modbus CRC<br>\u2714 Runs much faster than bitwise CRC algorithm.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, create new header and source file with name of modbus.h and modbus.h respectively as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1014\" height=\"872\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/2026-01-29_11-00-39.jpg\" alt=\"\" class=\"wp-image-4202\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/2026-01-29_11-00-39.jpg 1014w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/2026-01-29_11-00-39-300x258.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/2026-01-29_11-00-39-768x660.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/2026-01-29_11-00-39-750x645.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/2026-01-29_11-00-39-400x344.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/2026-01-29_11-00-39-250x215.jpg 250w\" sizes=\"(max-width: 1014px) 100vw, 1014px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>In the header file, we start by including the following header files:<\/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;main.h&quot;\n\n#include &quot;stdint.h&quot;<\/pre><\/div>\n\n\n\n<p>Next, declare a data structure to hold the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Slave address.<\/li>\n\n\n\n<li>Function code.<\/li>\n\n\n\n<li>Register address.<\/li>\n\n\n\n<li>Number of points.<\/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;}\">typedef struct\n{\n\tuint8_t Slave_Address;\n\tuint8_t Function_Code;\n\tuint16_t Register_Address;\n\tuint16_t Number_of_Data;\n\n}modbusTypedefStruct;<\/pre><\/div>\n\n\n\n<p>Next, the function that send the master request to read frame 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 Modbus_ReadRequest(modbusTypedefStruct * ModbusFrame);<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Hence, the entire header file 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;}\">#ifndef INC_MODBUS_H_\n#define INC_MODBUS_H_\n\n#include &quot;main.h&quot;\n\n#include &quot;stdint.h&quot;\n\ntypedef struct\n{\n\tuint8_t Slave_Address;\n\tuint8_t Function_Code;\n\tuint16_t Register_Address;\n\tuint16_t Number_of_Data;\n\n}modbusTypedefStruct;\n\nvoid Modbus_ReadRequest(modbusTypedefStruct * ModbusFrame);\n\n\n#endif \/* INC_MODBUS_H_ *\/<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, in modbus.c file, we start by including the following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">#include &lt;modbus.h&gt;\n\n#include &quot;modbus_crc.h&quot;<\/pre><\/div>\n\n\n\n<p>Next, declare the serial instant that shall be used, USART1 in this case:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">extern UART_HandleTypeDef huart1;<\/pre><\/div>\n\n\n\n<p>Note: It needed to be defined as external since it has been declared in the main.c file.<\/p>\n\n\n\n<p>Next, the function that will send the frame 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 Modbus_ReadRequest(modbusTypedefStruct * ModbusFrame)\n{\n\tuint8_t address\t=\tModbusFrame-&gt;Slave_Address;\n\n\tuint8_t FunCode\t=\tModbusFrame-&gt;Function_Code;\n\n\tuint16_t regAdd= \tModbusFrame-&gt;Register_Address;\n\n\tuint16_t numData=\tModbusFrame-&gt;Number_of_Data;\n\n\tuint8_t buffer[8];\n\n\n\tbuffer[0]=address;\n\n\tbuffer[1]=FunCode;\n\n\tbuffer[2]=(regAdd&gt;&gt;8)&amp;0xFF;\n\n\tbuffer[3]=(regAdd)&amp;0xFF;\n\n\tbuffer[4]= (numData&gt;&gt;8)&amp;0xFF;\n\n\tbuffer[5]= (numData)&amp;0xFF;\n\n\tuint16_t tmp_crc=crc16(buffer,6);\n\n\tbuffer[6]=tmp_crc&amp;0xFF;\n\tbuffer[7]=(tmp_crc&gt;&gt;8)&amp;0xFF;\n\n\tHAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);\n\n\tHAL_UART_Transmit(&amp;huart1, buffer, 8, 100);\n\n\tHAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>This function builds and transmits a&nbsp;<strong>Modbus RTU read request frame<\/strong>&nbsp;from a master to a slave over UART using RS-485.<\/p>\n\n\n\n<p>It extracts the slave address, function code, register address, and number of registers from the&nbsp;<code>ModbusFrame<\/code>&nbsp;structure, then places them into an 8-byte buffer following the Modbus RTU format. A CRC-16 is calculated over the first six bytes and appended in&nbsp;<strong>low-byte-first order<\/strong>, as required by Modbus. Before transmission, GPIOA pin 0 is set high to enable the RS-485 driver (transmit mode), the frame is sent using&nbsp;<code>HAL_UART_Transmit<\/code>, and the pin is cleared afterward to return the transceiver to receive mode.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Hence, the source file 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;}\">#include &lt;modbus.h&gt;\n\n#include &quot;modbus_crc.h&quot;\n\nextern UART_HandleTypeDef huart1;\n\n\nvoid Modbus_ReadRequest(modbusTypedefStruct * ModbusFrame)\n{\n\tuint8_t address\t=\tModbusFrame-&gt;Slave_Address;\n\n\tuint8_t FunCode\t=\tModbusFrame-&gt;Function_Code;\n\n\tuint16_t regAdd= \tModbusFrame-&gt;Register_Address;\n\n\tuint16_t numData=\tModbusFrame-&gt;Number_of_Data;\n\n\tuint8_t buffer[8];\n\n\n\tbuffer[0]=address;\n\n\tbuffer[1]=FunCode;\n\n\tbuffer[2]=(regAdd&gt;&gt;8)&amp;0xFF;\n\n\tbuffer[3]=(regAdd)&amp;0xFF;\n\n\tbuffer[4]= (numData&gt;&gt;8)&amp;0xFF;\n\n\tbuffer[5]= (numData)&amp;0xFF;\n\n\tuint16_t tmp_crc=crc16(buffer,6);\n\n\tbuffer[6]=tmp_crc&amp;0xFF;\n\tbuffer[7]=(tmp_crc&gt;&gt;8)&amp;0xFF;\n\n\tHAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);\n\n\tHAL_UART_Transmit(&amp;huart1, buffer, 8, 100);\n\n\tHAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);\n}\n<\/pre><\/div>\n\n\n\n<p>Thats all for the firmware.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Testing and Results:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>In main.c, we shall start by including the following header file:<\/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;modbus.h&quot;<\/pre><\/div>\n\n\n\n<p>Next, declare the data structure 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;}\">modbusTypedefStruct DataFrame;<\/pre><\/div>\n\n\n\n<p>Next, in user code begin 2 in main function, populate the data structure with values, the following is for example. Later, a proper values shall be used.<\/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;}\">DataFrame.Slave_Address=0x11;\nDataFrame.Function_Code=0x03;\nDataFrame.Register_Address=0x01;\nDataFrame.Number_of_Data=0x02;<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>In while 1 loop, in user code begin 3, transmit the data each 100ms 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;}\">Modbus_ReadRequest(&amp;DataFrame);\n\nHAL_Delay(100);<\/pre><\/div>\n\n\n\n<p>Save, build and run the project 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\/12\/2025-12-31_11-12-13-1024x34.jpg\" alt=\"\" class=\"wp-image-4132\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/12\/2025-12-31_11-12-13-1024x34.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/12\/2025-12-31_11-12-13-300x10.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/12\/2025-12-31_11-12-13-768x26.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/12\/2025-12-31_11-12-13-1536x51.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/12\/2025-12-31_11-12-13-1150x38.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/12\/2025-12-31_11-12-13-750x25.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/12\/2025-12-31_11-12-13-400x13.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/12\/2025-12-31_11-12-13-250x8.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/12\/2025-12-31_11-12-13.jpg 1986w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>By probing the AB pins of the RS485, you should get the following:<\/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\/2026\/01\/RigolDS0.png\" alt=\"\" class=\"wp-image-4203\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/RigolDS0.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/RigolDS0-300x185.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/RigolDS0-768x473.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/RigolDS0-750x461.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/RigolDS0-400x246.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/01\/RigolDS0-250x154.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Note: Values are in hex.<\/p>\n\n\n\n<p>Next, we shall develop the firmware to response to request to read by following one of the sensor documentation.<\/p>\n\n\n\n<p>Stay tuned.<\/p>\n\n\n\n<p>Happy coding \ud83d\ude09<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Part 3 of the guide moves beyond basic link verification and introduces practical Modbus RTU transactions in which the master issues read requests to the STM32-based slave. This section focuses on implementing and validating standard read function codes, register addressing, and response formatting so the emulated sensor can return meaningful data in a fully protocol-compliant [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,2,11,12],"tags":[],"class_list":["post-4197","post","type-post","status-publish","format-standard","hentry","category-data-structures","category-embedded-systems","category-peripheral-drivers","category-stm32"],"_links":{"self":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/4197"}],"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=4197"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/4197\/revisions"}],"predecessor-version":[{"id":4204,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/4197\/revisions\/4204"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4197"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4197"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4197"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}