{"id":4737,"date":"2026-09-12T12:22:55","date_gmt":"2026-09-12T12:22:55","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=4737"},"modified":"2026-09-12T12:22:58","modified_gmt":"2026-09-12T12:22:58","slug":"getting-started-with-ble-on-the-stm32wb55-part-2","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=4737","title":{"rendered":"Getting Started with BLE on the STM32WB55: Part 2"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"559\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/image-1-1024x559.png\" alt=\"\" class=\"wp-image-4738\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/image-1-1024x559.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/image-1-300x164.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/image-1-768x419.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/image-1-1150x627.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/image-1-750x409.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/image-1-400x218.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/image-1-250x136.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/image-1.png 1408w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>In Part 2 of our series, we will configure the STM32WB55 to initialize its Bluetooth Low Energy stack and start broadcasting advertising packets. You\u2019ll then learn how to detect the device and establish an active connection directly from your smartphone using a BLE scanner app.<\/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>Introduction.<\/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. Introduction:<\/h2>\n\n\n\n<p>Before writing a single line of radio firmware or launching a mobile scanner app, it is crucial to understand the fundamental mechanics that make Bluetooth Low Energy so efficient. BLE was designed from the ground up to achieve ultra-low power consumption by keeping the radio turned off as much as possible. It replaces the continuous connection model of classic Bluetooth with an asynchronous, event-driven architecture centered around discovery, broadcasting, and precise connection windows.<\/p>\n\n\n\n<p>In this installment, we will demystify the Generic Access Profile (GAP), break down how BLE devices format their broadcast payloads, examine the underlying Host-Controller architecture, and trace the exact lifecycle of establishing a mobile connection.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Generic Access Profile (GAP) &amp; Discovery Architecture<\/h3>\n\n\n\n<p>The Generic Access Profile (GAP) forms the operational foundation of any BLE system. It defines how devices announce their presence, discover nearby nodes, and establish point-to-point connections. GAP categorizes devices into distinct roles depending on their operational goal:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Broadcaster vs. Observer:<\/strong>\u00a0A non-connectable topology where a node unidirectionally broadcasts data (such as a temperature sensor or beacon) without accepting incoming links, while an Observer passively listens to those packets.<\/li>\n\n\n\n<li><strong>Peripheral vs. Central:<\/strong>\u00a0A connectable topology. The\u00a0<strong>Peripheral<\/strong>\u00a0(typically a resource-constrained node or sensor) advertises its availability, while the\u00a0<strong>Central<\/strong>\u00a0device (such as a smartphone, gateway, or tablet) actively scans for peripherals and initiates connections.<\/li>\n<\/ul>\n\n\n\n<p>To handle RF interference in busy 2.4 GHz environments shared with Wi-Fi and classic Bluetooth, BLE divides the 2.4 GHz spectrum into 40 distinct 2 MHz channels. Three of these\u2014<strong>Channels 37, 38, and 39<\/strong>\u2014are explicitly designated as&nbsp;<strong>Primary Advertising Channels<\/strong>. These channels are strategically spaced across the spectrum to sit in the quiet guard bands between common Wi-Fi channels, ensuring high discoverability.<\/p>\n\n\n\n<p>A Peripheral advertises by transmitting small broadcast packets across Channels 37, 38, and 39 in rapid succession. The timing between these transmission events is known as the&nbsp;<strong>Advertising Interval (Tadv\u200b)<\/strong>. Tuning this interval is a fundamental design trade-off:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Aggressive Advertising (20 ms \u2013 100 ms):<\/strong>\u00a0Results in near-instant discovery by smartphones, but draws higher average power.<\/li>\n\n\n\n<li><strong>Low-Power Advertising (1 sec \u2013 2.5 sec):<\/strong>\u00a0Drastically reduces power consumption to microamp levels, but increases the time a smartphone takes to discover the device.<\/li>\n<\/ul>\n\n\n\n<p>Additionally, GAP supports an&nbsp;<strong>Active Scanning<\/strong>&nbsp;mechanism. When a Central device detects an advertisement packet, it can transmit a&nbsp;<code>SCAN_REQ<\/code>&nbsp;frame back to the Peripheral during a tiny listening window. The Peripheral then responds with a&nbsp;<code>SCAN_RSP<\/code>&nbsp;packet, allowing it to send an additional 31 bytes of metadata\u2014such as a full human-readable device name or custom manufacturer information\u2014without establishing an active connection.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Host-Controller Interface (HCI) &amp; Architecture<\/h3>\n\n\n\n<p>To keep real-time RF timing isolated from complex user applications, modern BLE stacks separate software tasks into two distinct functional layers: the&nbsp;<strong>Host<\/strong>&nbsp;and the&nbsp;<strong>Controller<\/strong>.<\/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;}\">+-------------------------------------------------------+\n|                     APPLICATION                       |\n+-------------------------------------------------------+\n|                        HOST                           |\n|       (GAP \/ GATT \/ L2CAP \/ Security Manager)         |\n+-------------------------------------------------------+\n|               HOST-CONTROLLER INTERFACE               |\n|                         (HCI)                         |\n+-------------------------------------------------------+\n|                     CONTROLLER                        |\n|              (Link Layer \/ Physical RF)               |\n+-------------------------------------------------------+\n<\/pre><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>The Host Layer:<\/strong>\u00a0Resides on the main application processor. It manages high-level logic, including GAP (device discovery and roles), GATT (data structuring and services), Security Manager (pairing and encryption), and L2CAP (data multiplexing).<\/li>\n\n\n\n<li><strong>The Controller Layer:<\/strong>\u00a0Runs directly on dedicated radio hardware or a low-level co-processor. It handles time-critical task management, frequency hopping, packet framing, CRC checks, and Physical Layer (PHY) RF transmissions.<\/li>\n\n\n\n<li><strong>The Host-Controller Interface (HCI):<\/strong>\u00a0A standardized communication protocol layer that sits between the Host and Controller. The Host sends asynchronous commands (e.g., &#8220;Start Advertising&#8221;) down to the Controller via HCI, and the Controller sends asynchronous status events (e.g., &#8220;Connection Completed&#8221;) back up to the Host.<\/li>\n<\/ul>\n\n\n\n<p>Because BLE stack operations are non-blocking and event-driven, the application CPU does not spin in execution loops waiting for radio responses. Instead, the MCU sits in a low-power sleep state until an HCI interrupt or callback wakes the system to handle incoming packet events.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Advertising Payload Structure<\/h3>\n\n\n\n<p>Every piece of data broadcast by a BLE Peripheral must strictly adhere to the standardized packet structures defined by the Bluetooth SIG. In legacy BLE 4.2, the raw payload of an advertising packet is capped at&nbsp;<strong>31 bytes<\/strong>&nbsp;(expanded up to 254 bytes in BLE 5.0 Extended Advertising).<\/p>\n\n\n\n<p>Inside this 31-byte limit, data is organized into self-contained blocks known as&nbsp;<strong>AD Structures<\/strong>&nbsp;(Advertising Data Structures). Each structure uses a&nbsp;<strong>Length-Type-Value (LTV)<\/strong>&nbsp;formatting scheme:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Length (1 Byte):<\/strong>\u00a0Specifies the total byte count of the AD Type and Payload that follow.<\/li>\n\n\n\n<li><strong>AD Type (1 Byte):<\/strong>\u00a0Identifies the category of data being transmitted. Common types include:\n<ul class=\"wp-block-list\">\n<li><code>0x01<\/code>: Flags (e.g., General Discoverable Mode, BR\/EDR Not Supported).<\/li>\n\n\n\n<li><code>0x09<\/code>: Complete Local Name (human-readable string like\u00a0<code>\"My BLE Node\"<\/code>).<\/li>\n\n\n\n<li><code>0x02<\/code>\u00a0\/\u00a0<code>0x03<\/code>: 16-bit Service UUIDs (notifying scanners of supported GATT services).<\/li>\n\n\n\n<li><code>0xFF<\/code>: Manufacturer Specific Data (custom vendor payloads).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Value (Variable):<\/strong>\u00a0The raw data bytes corresponding to the AD Type.<\/li>\n<\/ul>\n\n\n\n<p>By evaluating these AD structures during a scan, Central devices can filter discovered hardware based on company IDs, offered services, or target names before deciding to initiate a connection.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Connection States &amp; Link Management<\/h3>\n\n\n\n<p>When a smartphone or Central device decides to connect to a Peripheral, it waits for the next advertisement packet and sends a&nbsp;<code>CONNECT_IND<\/code>&nbsp;request on the same channel. At this point, the Peripheral halts advertising, and both devices transition into a point-to-point&nbsp;<strong>Connected State<\/strong>.<\/p>\n\n\n\n<p>Once connected, data is no longer broadcast publicly; instead, communication occurs during dedicated, synchronized transmission windows defined by several key parameters:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Connection Interval (CONN_INT):<\/strong>\u00a0The precise time delay between consecutive data exchange windows (ranging from 7.5 ms to 4 seconds). Both devices wake up synchronously, exchange data frames, and immediately go back to sleep.<\/li>\n\n\n\n<li><strong>Slave Latency:<\/strong>\u00a0The number of consecutive connection intervals that the Peripheral is allowed to skip if it has no new data to send. This lets the Peripheral keep its radio off even if the Central wakes up frequently.<\/li>\n\n\n\n<li><strong>Supervision Timeout:<\/strong>\u00a0The maximum time allowed between valid packet exchanges before the link is considered lost, triggering a disconnect.<\/li>\n<\/ul>\n\n\n\n<p>When a disconnection occurs (whether triggered by user command or signal loss), stack callbacks report a disconnection event back to the Host application. This allows the firmware to update its state machine, update physical status indicators, and automatically restart advertising so new Central devices can connect.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"559\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/Gemini_Generated_Image_7tuw197tuw197tuw-1024x559.jpg\" alt=\"\" class=\"wp-image-4739\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/Gemini_Generated_Image_7tuw197tuw197tuw-1024x559.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/Gemini_Generated_Image_7tuw197tuw197tuw-300x164.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/Gemini_Generated_Image_7tuw197tuw197tuw-768x419.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/Gemini_Generated_Image_7tuw197tuw197tuw-1150x627.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/Gemini_Generated_Image_7tuw197tuw197tuw-750x409.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/Gemini_Generated_Image_7tuw197tuw197tuw-400x218.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/Gemini_Generated_Image_7tuw197tuw197tuw-250x136.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/Gemini_Generated_Image_7tuw197tuw197tuw.jpg 1408w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. STM32CubeMX Setup:<\/h2>\n\n\n\n<p>We shall continue from the previous guide <a href=\"https:\/\/blog.embeddedexpert.io\/?p=4695\" data-type=\"link\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=4695\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n\n\n\n<p>First, from System Core, enable HSEM (Hardware Semaphore) as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-42-36-1024x662.jpg\" alt=\"\" class=\"wp-image-4740\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-42-36-1024x662.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-42-36-300x194.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-42-36-768x497.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-42-36-1536x993.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-42-36-2048x1324.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-42-36-1150x744.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-42-36-750x485.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-42-36-400x259.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-42-36-250x162.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, enable IPPC and related interrupt as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-44-30-1024x662.jpg\" alt=\"\" class=\"wp-image-4741\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-44-30-1024x662.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-44-30-300x194.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-44-30-768x497.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-44-30-1536x993.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-44-30-2048x1324.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-44-30-1150x744.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-44-30-750x485.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-44-30-400x259.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-44-30-250x162.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, from timers, enable RTC and calendar as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-45-49-1024x662.jpg\" alt=\"\" class=\"wp-image-4742\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-45-49-1024x662.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-45-49-300x194.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-45-49-768x497.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-45-49-1536x993.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-45-49-2048x1324.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-45-49-1150x744.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-45-49-750x485.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-45-49-400x259.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-45-49-250x162.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, from Connectivity, enable RF module as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-47-00-1024x662.jpg\" alt=\"\" class=\"wp-image-4743\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-47-00-1024x662.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-47-00-300x194.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-47-00-768x497.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-47-00-1536x993.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-47-00-2048x1324.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-47-00-1150x744.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-47-00-750x485.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-47-00-400x259.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-47-00-250x162.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, from Computing, enable CRC as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-48-00-1024x662.jpg\" alt=\"\" class=\"wp-image-4744\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-48-00-1024x662.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-48-00-300x194.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-48-00-768x497.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-48-00-1536x993.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-48-00-2048x1324.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-48-00-1150x744.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-48-00-750x485.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-48-00-400x259.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-48-00-250x162.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, from Middleware and Software Package, STM32_WPAN, select BLE and configure it as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>BLE Wireless Stack is set to Full.<\/li>\n\n\n\n<li>Custom Template to Enabled.<\/li>\n\n\n\n<li>Set the LOCAL_NAME to MY_BLE.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-49-14-1024x662.jpg\" alt=\"\" class=\"wp-image-4745\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-49-14-1024x662.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-49-14-300x194.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-49-14-768x497.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-49-14-1536x993.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-49-14-2048x1324.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-49-14-1150x744.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-49-14-750x485.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-49-14-400x259.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-49-14-250x162.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, from BLE GATT:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Number of Services to 1.<\/li>\n\n\n\n<li>Short and long name to My_Services (You can choose your own).<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-53-39-1024x662.jpg\" alt=\"\" class=\"wp-image-4746\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-53-39-1024x662.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-53-39-300x194.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-53-39-768x497.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-53-39-1536x993.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-53-39-2048x1324.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-53-39-1150x744.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-53-39-750x485.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-53-39-400x259.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-53-39-250x162.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, from MY_SERVICES tab (Or what ever the name you gave to the services):<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Set number of characters to 2.<\/li>\n\n\n\n<li>Set UUID to 56 78<\/li>\n<\/ul>\n\n\n\n<p>For Characteristic 1 general:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Short and long Name as MY_TX_CHAR<\/li>\n\n\n\n<li>UUID to 12 34<\/li>\n\n\n\n<li>Value length to 20<\/li>\n\n\n\n<li>From properties, set it to Notify.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"588\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-55-58-1024x588.jpg\" alt=\"\" class=\"wp-image-4747\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-55-58-1024x588.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-55-58-300x172.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-55-58-768x441.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-55-58-1536x882.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-55-58-2048x1176.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-55-58-1150x661.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-55-58-750x431.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-55-58-400x230.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-55-58-250x144.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>For characteristics 2:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Short and long name to MY_RX_CHAR.<\/li>\n\n\n\n<li>UUID 12 35<\/li>\n\n\n\n<li>Value length to 20<\/li>\n\n\n\n<li>Properties to Write without response.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"588\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-59-39-1024x588.jpg\" alt=\"\" class=\"wp-image-4748\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-59-39-1024x588.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-59-39-300x172.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-59-39-768x441.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-59-39-1536x882.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-59-39-2048x1176.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-59-39-1150x661.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-59-39-750x431.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-59-39-400x230.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_14-59-39-250x144.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, from BLE advertising:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Set peripheral advertise and connect to yes.<\/li>\n\n\n\n<li>Central Scan and connect to yes.<\/li>\n\n\n\n<li>Observer scan to yes.<\/li>\n\n\n\n<li>Set to CGF_GAP_DEVICE_NAME STM32WB55<\/li>\n\n\n\n<li>Enable Include AD_TYPE_COMPLETE_NAME and set it to STM32WB55EE (This name shall appear when scan for BLE).<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_15-01-49-1024x662.jpg\" alt=\"\" class=\"wp-image-4749\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_15-01-49-1024x662.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_15-01-49-300x194.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_15-01-49-768x497.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_15-01-49-1536x993.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_15-01-49-2048x1324.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_15-01-49-1150x744.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_15-01-49-750x485.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_15-01-49-400x259.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/2026-09-12_15-01-49-250x162.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Thats all for the configuration.<\/p>\n\n\n\n<p>Click on generate code and this 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>Open the project in STM32CubeIDE.<\/p>\n\n\n\n<p>From Core\/inc open app_conf.h header file.<\/p>\n\n\n\n<p>In user code begin Generic_Parameters, declare 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;}\">#define ADV_TYPE     0\n#define ADV_FILTER    0<\/pre><\/div>\n\n\n\n<p><span style=\"font-family: Roboto, sans-serif;font-size: 16px\">Thats all for the firmware.<\/span><p style=\"font-family: Roboto, sans-serif;font-size: 16px;line-height: inherit;border: 0px;margin: 0px 0px 1.5em\">Save, build the project and run it as follows:<\/p><figure class=\"wp-block-image\" style=\"margin-bottom: 1.5em;border: 0px;padding: 0px;overflow: hidden;max-width: 100%;border-radius: 6px;font-family: Roboto, sans-serif;font-size: 16px\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"34\" class=\"wp-image-4349\" style=\"overflow: hidden;border-radius: 6px\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-1024x34.png\" alt=\"\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-1024x34.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-300x10.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-768x26.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-1536x51.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-1150x38.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-750x25.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-400x13.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-250x8.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1.png 1986w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><p style=\"font-family: Roboto, sans-serif;font-size: 16px;line-height: inherit;border: 0px;margin: 0px 0px 1.5em\">You may download the project from our github repository from\u00a0<a style=\"font-family: inherit;font-style: inherit;line-height: inherit;border: 0px;text-decoration: none;background-image: none;background-position: 0% 0%;background-size: auto;background-repeat: repeat;background-attachment: scroll\" href=\"https:\/\/github.com\/hussamaldean\/Embedded-Expert-Post-Projects\/tree\/main\/Projects\/STM32_WB55\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. Results:<\/h2>\n\n\n\n<p>Using LightBlue app on your phone, you can connect to STM32WB55EE as follows:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"471\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/IMG_0975-471x1024.png\" alt=\"\" class=\"wp-image-4750\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/IMG_0975-471x1024.png 471w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/IMG_0975-138x300.png 138w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/IMG_0975-768x1669.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/IMG_0975-707x1536.png 707w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/IMG_0975-943x2048.png 943w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/IMG_0975-1150x2499.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/IMG_0975-750x1630.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/IMG_0975-400x869.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/IMG_0975-250x543.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/09\/IMG_0975.png 1320w\" sizes=\"(max-width: 471px) 100vw, 471px\" \/><\/figure><\/div>\n\n\n<p><\/p>\n\n\n\n<p>Note the second services, 1234 and 1235, they are the characteristics we declare in STM32CubeMX.<\/p>\n\n\n\n<p>Next part, we shall develop the application to send and receive data to\/from smartphone.<\/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 Part 2 of our series, we will configure the STM32WB55 to initialize its Bluetooth Low Energy stack and start broadcasting advertising packets. You\u2019ll then learn how to detect the device and establish an active connection directly from your smartphone using a BLE scanner app. In this guide, we shall cover the following: 1. Introduction: [&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-4737","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\/4737"}],"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=4737"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/4737\/revisions"}],"predecessor-version":[{"id":4751,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/4737\/revisions\/4751"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4737"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4737"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4737"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}