{"id":1814,"date":"2025-10-09T00:00:00","date_gmt":"2025-10-08T15:00:00","guid":{"rendered":"https:\/\/twarelab.com\/?p=1814"},"modified":"2025-10-02T14:59:21","modified_gmt":"2025-10-02T05:59:21","slug":"stm32f4-c-project-tutorial-step-5","status":"publish","type":"post","link":"https:\/\/twarelab.com\/en\/blog\/stm32f4-c-project-tutorial-step-5\/","title":{"rendered":"[STM32F4] C++ \ud504\ub85c\uc81d\ud2b8 \ud29c\ud1a0\ub9ac\uc5bc &#8211; Step 5"},"content":{"rendered":"<h2 class=\"wp-block-heading\">Using the SPI Peripheral in C++<\/h2>\n\n\n\n<p class=\"translation-block\">The SPI (Serial Peripheral Interface) is a widely used communication interface in embedded systems <strong>for high-speed data exchange with sensors, external memory devices, displays, and more<\/strong>.\n\nUnlike UART, SPI follows a <strong>master\/slave architecture<\/strong> and operates with four main signals: <strong>SCLK, MOSI, MISO, and CS (Chip Select)<\/strong>.<\/p>\n\n\n\n<p class=\"translation-block\">In this step, we\u2019ll explore how to design SPI communication using a <strong>class-based structure<\/strong> in C++.\nUnlike UART\u2014where interrupt or DMA-based extensions are common\u2014SPI protocols often vary by device, so it\u2019s typical to derive <strong>device-specific subclasses<\/strong> from a shared base class, rather than creating generalized extensions.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">BaseSPI: The Core Class<\/h2>\n\n\n\n<p class=\"translation-block\">The BaseSPI class provides a common foundation for SPI communication.\nIts key features include:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Transmit\/Receive Functions<\/strong><br>Supports both single-byte and multi-byte transfers.<\/li>\n\n\n\n<li><strong>Communication Properties<\/strong><br>Manages SPI settings such as:\nClock Prescaler, Clock Polarity and Phase (CPOL\/CPHA), Bit Order (MSB\/LSB first), Data Frame Length<\/li>\n\n\n\n<li><strong>Chip Select (CS) Control<\/strong><br>Controls the CS pin to initiate and terminate communication with slave devices.<\/li>\n<\/ul>\n\n\n\n<p>This class handles only general SPI operations, while <strong>device-specific command sets and protocols<\/strong> are implemented in derived classes.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Device-Specific Extension Classes<\/h2>\n\n\n\n<p class=\"translation-block\">Since each SPI device follows its own protocol, it\u2019s efficient to create dedicated subclasses that inherit from BaseSPI. Examples include:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"translation-block\"><strong>AT25 Series EEPROMs<\/strong> \u2192 Require specific read\/write command sets.<\/li>\n\n\n\n<li class=\"translation-block\"><strong>External ADC\/DACs<\/strong> \u2192 Use sampling start\/stop commands and register access sequences.<\/li>\n\n\n\n<li class=\"translation-block\"><strong>Display Controllers (e.g., ST7735, ILI9341)<\/strong> \u2192 Require distinguishing between command and data transmissions.<\/li>\n<\/ul>\n\n\n\n<p class=\"translation-block\">Therefore, it is most efficient to implement dedicated device-specific classes that inherit from BaseSPI.<\/p>\n\n\n\n<p class=\"translation-block\">Each device class utilizes the transfer functions of BaseSPI while implementing its own instruction set and communication protocol.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Code Examples<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Example 1 \u2013 SPI-Based EEPROM Class<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Include Header and Declare Object<\/strong> <\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include \"BaseSPI.h\"\n\nBaseSPI tmpSPI;<\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting &amp; Tips<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Corrupted data<\/strong>\n<ul class=\"wp-block-list\">\n<li>Clock polarity (CPOL) or phase (CPHA) mismatch<\/li>\n\n\n\n<li>Configure SPI mode (Mode 0\u20133) according to the device datasheet<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>No response from slave<\/strong>\n<ul class=\"wp-block-list\">\n<li>CS pin not properly controlled<\/li>\n\n\n\n<li>Ensure CS is driven low before and high after communication<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Speed issues<\/strong>\n<ul class=\"wp-block-list\">\n<li>Prescaler too high or too low<\/li>\n\n\n\n<li>Adjust SPI clock according to device specifications<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Protocol mismatch<\/strong>\n<ul class=\"wp-block-list\">\n<li>Incorrect command\/data sequence<\/li>\n\n\n\n<li>Implement a dedicated device class to handle protocol details<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"translation-block\">In this step, we introduced a class-based structure for implementing SPI communication:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"translation-block\"><strong>BaseSPI<\/strong> \u2013 Provides core features such as transmit\/receive, CS control, and configuration management.<\/li>\n\n\n\n<li class=\"translation-block\"><strong>Device-Specific Classes<\/strong> \u2013 Implement device protocols for EEPROMs, sensors, and display controllers.<\/li>\n\n\n\n<li><strong>Application Layer<\/strong> \u2013 Simply calls the device class APIs without worrying about low-level SPI details.<\/li>\n<\/ul>\n\n\n\n<p class=\"translation-block\">In the next step, we\u2019ll select one SPI-based device and demonstrate the actual data transfer and receive flow as a practical example.<\/p>","protected":false},"excerpt":{"rendered":"<p>C++\uc5d0\uc11c SPI Peripheral \uc0ac\uc6a9\ud558\uae30 SPI(Serial Peripheral Interface)\ub294 \uc784\ubca0\ub514\ub4dc \uc2dc\uc2a4\ud15c\uc5d0\uc11c \uc13c\uc11c, \uc678\ubd80 \uba54\ubaa8\ub9ac, \ub514\uc2a4\ud50c\ub808\uc774 \ub4f1 \ub2e4\uc591\ud55c \uc7a5\uce58\uc640 \uace0\uc18d \ud1b5\uc2e0\uc744 \ud558\uae30 \uc704\ud574 \ub110\ub9ac \uc0ac\uc6a9\ub418\ub294 \uc778\ud130\ud398\uc774\uc2a4\uc785\ub2c8\ub2e4.UART\uc640 \ub2ec\ub9ac \ub9c8\uc2a4\ud130\/\uc2ac\ub808\uc774\ube0c \uad6c\uc870\ub97c \uac00\uc9c0\uace0, \ud074\ub7ed \uc2e0\ud638\ub97c \ud3ec\ud568\ud55c 4\uc120(SCLK, MOSI, MISO, CS)\uc744 \ud1b5\ud574 \ub3d9\uc791\ud569\ub2c8\ub2e4. \uc774\ubc88 \ub2e8\uacc4\uc5d0\uc11c\ub294 SPI\ub97c \ud074\ub798\uc2a4 \uae30\ubc18 \uad6c\uc870\ub85c \uc124\uacc4\ud558\ub294 \ubc29\ubc95\uc744 \ub2e4\ub8f9\ub2c8\ub2e4.UART\uc640 \ub2ec\ub9ac SPI\ub294 \uc7a5\uce58\ub9c8\ub2e4 \ud504\ub85c\ud1a0\ucf5c\uc774 \ub2ec\ub77c [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_themeisle_gutenberg_block_has_review":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1,13,12],"tags":[87,51,42,32],"class_list":["post-1814","post","type-post","status-publish","format-standard","hentry","category-blog","category-en","category-ko","tag-c","tag-spi","tag-stm32f4","tag-tw100pc"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/twarelab.com\/en\/wp-json\/wp\/v2\/posts\/1814","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/twarelab.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/twarelab.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/twarelab.com\/en\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/twarelab.com\/en\/wp-json\/wp\/v2\/comments?post=1814"}],"version-history":[{"count":2,"href":"https:\/\/twarelab.com\/en\/wp-json\/wp\/v2\/posts\/1814\/revisions"}],"predecessor-version":[{"id":1816,"href":"https:\/\/twarelab.com\/en\/wp-json\/wp\/v2\/posts\/1814\/revisions\/1816"}],"wp:attachment":[{"href":"https:\/\/twarelab.com\/en\/wp-json\/wp\/v2\/media?parent=1814"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/twarelab.com\/en\/wp-json\/wp\/v2\/categories?post=1814"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/twarelab.com\/en\/wp-json\/wp\/v2\/tags?post=1814"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}