nrf52811墨水屏edp_service.c文件學習

on_connect函數

/**@brief Function for handling the @ref BLE_GAP_EVT_CONNECTED event from the S110 SoftDevice.** @param[in] p_epd     EPD Service structure.* @param[in] p_ble_evt Pointer to the event received from BLE stack.*/
static void on_connect(ble_epd_t * p_epd, ble_evt_t * p_ble_evt)
{p_epd->conn_handle = p_ble_evt->evt.gap_evt.conn_handle;EPD_GPIO_Init();
}
函數功能概述

on_connect函數是藍牙低功耗 (BLE) 事件處理的核心部分,主要在設備成功建立藍牙連接時被觸發。其核心功能是管理連接句柄并初始化電子紙顯示屏 (EPD) 的 GPIO 引腳配置。

代碼詳細解析
/*** @brief 處理S110 SoftDevice的BLE_GAP_EVT_CONNECTED事件* @param[in] p_epd       EPD服務結構指針,包含連接狀態和配置信息* @param[in] p_ble_evt   BLE事件指針,包含連接事件的具體數據*/
static void on_connect(ble_epd_t * p_epd, ble_evt_t * p_ble_evt)
{// 1. 保存連接句柄p_epd->conn_handle = p_ble_evt->evt.gap_evt.conn_handle;// 2. 初始化EPD相關的GPIO引腳EPD_GPIO_Init();
}
關鍵操作說明
  1. 連接句柄管理

    • 通過p_ble_evt->evt.gap_evt.conn_handle獲取藍牙連接的句柄(conn_handle
    • 將句柄存儲到p_epd->conn_handle中,用于后續通信時標識該連接
    • 連接句柄是 BLE 通信的基礎,類似網絡連接中的 Socket 描述符
  2. GPIO 初始化

    • 調用EPD_GPIO_Init()函數初始化 EPD 硬件相關的 GPIO 引腳
    • 初始化操作可能包括:
      • 設置引腳方向(輸入 / 輸出)
      • 配置引腳電平(上拉 / 下拉)
      • 初始化 SPI/I2C 等通信接口的引腳
    • 這一步為后續 EPD 顯示數據傳輸做好硬件準備
實際應用場景

當手機或其他 BLE 主機設備掃描并連接到搭載該代碼的設備時:

  1. 藍牙協議棧會生成BLE_GAP_EVT_CONNECTED事件
  2. 事件處理框架會調用on_connect函數
  3. 函數保存連接句柄并初始化 EPD 硬件,使設備準備好接收主機發送的顯示指令
  4. 后續主機可通過該連接句柄向 EPD 發送數據(如時間、圖像等)
潛在優化點
  1. 錯誤處理補充
    可添加EPD_GPIO_Init()的返回值檢查,確保初始化成功:

    uint32_t err_code = EPD_GPIO_Init();
    if (err_code != NRF_SUCCESS) {NRF_LOG_ERROR("EPD GPIO init failed, error: %d", err_code);// 可選:斷開連接或記錄錯誤狀態
    }
    
  2. 功耗優化
    若系統對功耗敏感,可在初始化時配置 GPIO 引腳的低功耗模式:

    void EPD_GPIO_Init() {// 示例:配置引腳為低功耗輸出模式nrf_gpio_cfg_output(引腳號);nrf_gpio_pin_write(引腳號, 低電平);
    }
    
  3. 連接參數記錄
    可擴展代碼以記錄連接參數(如連接間隔、超時時間):

    p_epd->conn_params.interval = p_ble_evt->evt.gap_evt.params.conn_params.interval;
    p_epd->conn_params.timeout = p_ble_evt->evt.gap_evt.params.conn_params.timeout;
    
與其他函數的協作關系
  • on_disconnect函數對應
    連接時調用EPD_GPIO_Init(),斷開時調用EPD_GPIO_Uninit()釋放資源
  • epd_service_on_write函數協作
    連接建立后,on_connect保存的conn_handle用于ble_epd_string_send等函數發送數據
  • 與硬件驅動的交互
    EPD_GPIO_Init()依賴底層 GPIO 驅動實現引腳配置

該函數是 BLE 連接建立后硬件初始化的關鍵環節,確保 EPD 設備在連接狀態下能正常接收和處理顯示指令。


ble_evt_t結構體解析

結構體概述

ble_evt_t是藍牙低功耗 (BLE) 協議棧中用于表示各類事件的核心數據結構。它采用 "事件頭 + 事件聯合體" 的設計模式,能夠高效處理不同類型的 BLE 事件,同時保持內存占用的最小化。

結構體定義詳解
typedef struct
{ble_evt_hdr_t header;           /**< 事件頭,包含事件類型標識等公共信息 */union{ble_common_evt_t  common_evt; /**< 通用事件,事件ID屬于BLE_EVT_*系列 */ble_gap_evt_t     gap_evt;    /**< GAP層事件,事件ID屬于BLE_GAP_EVT_*系列 */ble_gattc_evt_t   gattc_evt;  /**< GATT客戶端事件,事件ID屬于BLE_GATTC_EVT*系列 */ble_gatts_evt_t   gatts_evt;  /**< GATT服務器事件,事件ID屬于BLE_GATTS_EVT*系列 */} evt;                          /**< 事件聯合體,根據事件類型存儲具體事件數據 */
} ble_evt_t;
核心成員解析
1.?header字段 - 事件頭結構
  • 類型ble_evt_hdr_t(通常包含事件 ID 和長度信息)
  • 作用
    • 標識事件類型(通過header.evt_id
    • 提供事件數據長度(通過header.evt_len
    • 作為所有事件的公共前綴,便于統一處理
typedef struct
{uint16_t evt_id;                /**< Value from a BLE_<module>_EVT series. */uint16_t evt_len;               /**< Length in octets including this header. */
} ble_evt_hdr_t;

?

2.?evt聯合體 - 事件具體數據

聯合體設計的核心優勢是內存共享,不同事件類型復用同一塊內存空間:

聯合體成員對應事件類型典型應用場景
common_evt通用基礎事件協議棧內部狀態變化
gap_evtGAP(通用訪問配置文件)事件連接建立、斷開、設備發現等
gattc_evtGATT 客戶端事件讀取 / 寫入遠程服務數據
gatts_evtGATT 服務器事件接收客戶端寫入、通知請求等
設計模式分析

這種 "頭部 + 聯合體" 的設計屬于標記聯合模式 (Tagged Union),在嵌入式系統中非常常見:

  1. 空間效率

    • 無論處理哪種事件,結構體總大小等于header?+ 最大事件結構體的大小
    • 避免為每種事件類型單獨分配內存
  2. 類型安全

    • 通過header.evt_id判斷當前事件類型
    • 確保訪問聯合體成員時類型匹配
  3. 擴展性

    • 新增事件類型時只需擴展聯合體成員
    • 保持結構體接口兼容性
典型使用場景

在事件處理函數中,通常按以下流程處理ble_evt_t

void ble_evt_handler(ble_evt_t *p_ble_evt)
{// 1. 通過事件頭獲取事件類型uint32_t evt_id = p_ble_evt->header.evt_id;// 2. 根據事件類型處理不同事件switch (evt_id){case BLE_GAP_EVT_CONNECTED:// 處理連接事件,使用p_ble_evt->evt.gap_evton_connect(p_epd, p_ble_evt);break;case BLE_GATTS_EVT_WRITE:// 處理寫入事件,使用p_ble_evt->evt.gatts_evton_write(p_epd, p_ble_evt);break;// 其他事件處理...default:break;}
}
內存布局與對齊注意事項
  1. 內存對齊

    • 聯合體成員需遵循最大對齊規則
    • 例如:若ble_gatts_evt_t包含 64 位成員,則整個聯合體按 8 字節對齊
  2. 內存占用計算

    sizeof(ble_evt_t) = sizeof(ble_evt_hdr_t) + max(sizeof(ble_common_evt_t),sizeof(ble_gap_evt_t),sizeof(ble_gattc_evt_t),sizeof(ble_gatts_evt_t)
    )
    
  3. 跨平臺注意事項

    • 需通過#pragma pack等指令控制結構體對齊
    • 避免因不同編譯器對齊規則導致的協議兼容性問題
與其他結構的關聯
  • ble_evt_hdr_t結構
    通常包含uint16_t evt_iduint16_t evt_len字段,作為所有事件的公共標識

  • 各事件具體結構

    • ble_gap_evt_t包含連接句柄、連接參數等 GAP 層數據
    • ble_gatts_evt_t包含服務句柄、特征值句柄等 GATT 服務器數據
    • 這些結構根據藍牙核心規范定義,確保協議兼容性

這種設計使得 BLE 協議棧能夠以統一接口處理各類事件,同時保持高效的內存使用,非常適合資源受限的嵌入式系統環境。


ble_gap_evt_t結構體深度解析

結構體整體架構

ble_gap_evt_t是藍牙低功耗 (GAP) 層事件的核心數據結構,用于表示設備在連接、斷開、安全認證等過程中產生的各類事件。其設計采用 "連接句柄 + 事件參數聯合體" 的模式,能夠高效處理多種 GAP 事件類型。

typedef struct
{uint16_t conn_handle;                                     /**< 事件發生的連接句柄 */union                                                     /**< 事件參數聯合體,由外層結構體的evt_id標識當前類型 */{ble_gap_evt_connected_t                   connected;                    /**< 連接事件參數 */ble_gap_evt_disconnected_t                disconnected;                 /**< 斷開連接事件參數 */ble_gap_evt_conn_param_update_t           conn_param_update;            /**< 連接參數更新事件參數 */// 省略中間事件類型...ble_gap_evt_phy_update_request_t          phy_update_request;           /**< PHY更新請求事件參數 */ble_gap_evt_phy_update_t                  phy_update;                   /**< PHY更新事件參數 */} params;                                                                 /**< 事件具體參數 */
} ble_gap_evt_t;
核心成員詳解
1.?conn_handle?- 連接句柄
  • 類型uint16_t
  • 作用
    • 唯一標識一個藍牙連接,類似網絡通信中的 Socket 句柄
    • 在多連接場景中用于區分不同的客戶端連接
    • 所有 GAP 事件都與特定連接相關聯
2.?params聯合體 - 事件參數集合

聯合體包含 16 種不同類型的事件參數結構,以下是關鍵事件類型解析:

事件類型事件 ID 前綴核心應用場景
connectedBLE_GAP_EVT_CONNECTED藍牙連接建立時,攜帶連接參數和句柄
disconnectedBLE_GAP_EVT_DISCONNECTED連接斷開時,攜帶斷開原因碼
conn_param_updateBLE_GAP_EVT_CONN_PARAM_UPDATE連接參數(間隔、超時等)更新時
sec_params_requestBLE_GAP_EVT_SEC_PARAMS_REQUEST安全參數請求,如加密密鑰協商
auth_statusBLE_GAP_EVT_AUTH_STATUS認證狀態通知,攜帶認證結果
timeoutBLE_GAP_EVT_TIMEOUT連接或操作超時,攜帶超時類型
rssi_changedBLE_GAP_EVT_RSSI_CHANGED接收信號強度變化,攜帶 RSSI 值
設計模式與內存優化

這種 "句柄 + 聯合體" 的設計體現了嵌入式系統中典型的空間效率優先原則

  1. 內存共享機制

    • 無論處理哪種事件,聯合體僅占用最大事件結構的內存空間
    • 例如:ble_gap_evt_connected_t通常比ble_gap_evt_timeout_t更復雜,聯合體大小由前者決定
  2. 類型安全控制

    • 通過外層ble_evt_theader.evt_id字段判斷當前事件類型
    • 確保訪問聯合體成員時類型匹配,避免內存越界
  3. 協議兼容性設計

    • 結構體定義嚴格遵循藍牙核心規范 v5.3
    • 新增事件類型時只需擴展聯合體成員,不破壞現有接口
典型事件處理流程

以下是處理BLE_GAP_EVT_CONNECTED事件的示例代碼,展示如何解析ble_gap_evt_t

c

void ble_evt_handler(ble_evt_t *p_ble_evt)
{if (p_ble_evt->header.evt_id == BLE_GAP_EVT_CONNECTED){// 1. 獲取連接句柄uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle;// 2. 解析連接事件參數ble_gap_evt_connected_t *p_connected = &p_ble_evt->evt.gap_evt.params.connected;// 3. 提取連接參數uint16_t conn_interval = p_connected->conn_params.interval;    // 連接間隔 (1.25ms單位)uint16_t conn_latency  = p_connected->conn_params.latency;     // 連接延遲uint16_t supervision_timeout = p_connected->conn_params.sup_timeout; // 超時時間// 4. 業務邏輯處理on_connect(p_epd, p_ble_evt);}
}

內存布局與對齊考量
  1. 對齊規則

    • 聯合體成員按各自結構的最大對齊要求進行內存對齊
    • 例如:若ble_gap_evt_connected_t包含 32 位成員,則整個聯合體按 4 字節對齊
  2. 內存占用計算

    plaintext

    sizeof(ble_gap_evt_t) = sizeof(uint16_t) + max(sizeof(ble_gap_evt_connected_t),sizeof(ble_gap_evt_disconnected_t),// ... 其他事件結構大小sizeof(ble_gap_evt_phy_update_t)
    )
    

  3. 編譯器優化建議

    • 使用#pragma pack(push, 4)等指令控制對齊,避免字節填充浪費內存
    • 在跨平臺開發中,通過__attribute__((packed))確保結構體布局一致
與其他結構的協作關系
  1. ble_evt_t的關系

    • ble_gap_evt_tble_evt_t聯合體中的一個成員
    • 通過ble_evt_t->evt.gap_evt訪問 GAP 事件相關數據
  2. 與事件處理函數的交互

    • on_connecton_disconnect等函數接收ble_evt_t*指針
    • 通過類型轉換獲取ble_gap_evt_t中的具體事件參數
  3. 與協議棧的集成

    • 結構體定義由 Nordic Semiconductor SDK 提供
    • 底層協議棧填充事件數據后,通過回調函數傳遞給應用層

這種設計使得應用層能夠以統一接口處理各類 GAP 事件,同時保持對底層硬件資源的高效利用,非常適合低功耗藍牙設備的開發場景。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/85004.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/85004.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/85004.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Nginx-2 詳解處理 Http 請求

Nginx-2 詳解處理 Http 請求 Nginx 作為當今最流行的開源 Web 服務器之一&#xff0c;以其高性能、高穩定性和豐富的功能而聞名。在處理 HTTP請求 的過程中&#xff0c;Nginx 采用了模塊化的設計&#xff0c;將整個請求處理流程劃分為若干個階段&#xff0c;每個階段都可以由特…

40-Oracle 23 ai Bigfile~Smallfile-Basicfile~Securefile矩陣對比

小伙伴們是不是在文件選擇上還默認給建文件4G/個么&#xff0c;在oracle每個版本上系統默認屬性是什么&#xff0c;選擇困難癥了沒&#xff0c;一起一次性文件存儲和默認屬性看透。 基于Oracle歷代在存儲架構的技術演進分析&#xff0c;結合版本升級和23ai新特性&#xff0c;一…

【一】零基礎--分層強化學習概覽

分層強化學習&#xff08;Hierarchical Reinforcement Learning, HRL&#xff09;最早一般視為1993 年封建強化學習的提出. 一、HL的基礎理論 1.1 MDP MDP&#xff08;馬爾可夫決策過程&#xff09;&#xff1a;MDP是一種用于建模序列決策問題的框架&#xff0c;包含狀態&am…

Java延時

在 Java 中實現延時操作主要有以下幾種方式&#xff0c;根據使用場景選擇合適的方法&#xff1a; 1. Thread.sleep()&#xff08;最常用&#xff09; java 復制 下載 try {// 延時 1000 毫秒&#xff08;1秒&#xff09;Thread.sleep(1000); } catch (InterruptedExcepti…

電阻篇---下拉電阻的取值

下拉電阻的取值需要綜合考慮電路驅動能力、功耗、信號完整性、噪聲容限等多方面因素。以下是詳細的取值分析及方法&#xff1a; 一、下拉電阻的核心影響因素 1. 驅動能力與電流限制 單片機 IO 口驅動能力&#xff1a;如 STM32 的 IO 口在輸入模式下的漏電流通常很小&#xf…

NY271NY274美光科技固態NY278NY284

美光科技NY系列固態硬盤深度剖析&#xff1a;技術、市場與未來 技術前沿&#xff1a;232層NAND架構與性能突破 在存儲技術的賽道上&#xff0c;美光科技&#xff08;Micron&#xff09;始終是行業領跑者。其NY系列固態硬盤&#xff08;SSD&#xff09;憑借232層NAND閃存架構的…

微信開發者工具 插件未授權使用,user uni can not visit app

參考&#xff1a;https://www.jingpinma.cn/archives/159.html 問題描述 我下載了一個別人的小程序&#xff0c;想運行看看效果&#xff0c;結果報錯信息如下 原因 其實就是插件沒有安裝&#xff0c;需要到小程序平臺安裝插件。處理辦法如下 在 app.json 里&#xff0c;聲…

UE5 讀取配置文件

使用免費的Varest插件&#xff0c;可以讀取本地的json數據 獲取配置文件路徑&#xff1a;當前配置文件在工程根目錄&#xff0c;打包后在 Windows/項目名稱 下 讀取json 打包后需要手動復制配置文件到Windows/項目名稱 下

【kdump專欄】KEXEC機制中SME(安全內存加密)

【kdump專欄】KEXEC機制中SME&#xff08;安全內存加密&#xff09; 原始代碼&#xff1a; /* Ensure that these pages are decrypted if SME is enabled. */ 533 if (pages) 534 arch_kexec_post_alloc_pages(page_address(pages), 1 << order, 0);&#x1f4cc…

C# vs2022 找不到指定的 SDK“Microsof.NET.Sdk

找不到指定的 SDK"Microsof.NET.Sdk 第一查 看 系統盤目錄 C:\Program Files\dotnet第二 命令行輸入 dotnet --version第三 檢查環境變量總結 只要執行dotnet --version 正常返回版本號此問題即解決 第一查 看 系統盤目錄 C:\Program Files\dotnet 有2種方式 去檢查 是否…

Pytest斷言全解析:掌握測試驗證的核心藝術

Pytest斷言全解析&#xff1a;掌握測試驗證的核心藝術 一、斷言的本質與重要性 什么是斷言&#xff1f; 斷言是自動化測試中的驗證檢查點&#xff0c;用于確認代碼行為是否符合預期。在Pytest中&#xff0c;斷言直接使用Python原生assert語句&#xff0c;當條件不滿足時拋出…

【編譯原理】題目合集(一)

未經許可,禁止轉載。 文章目錄 選擇填空綜合選擇 將編譯程序分成若干個“遍”是為了 (D.利用有限的機器內存,但降低了執行效率) A.提高程序的執行效率 B.使程序的結構更加清晰 C.利用有限的機器內存并提高執行效率 D.利用有限的機器內存,但降低了執行效率 詞法分析…

uni-app項目實戰筆記13--全屏頁面的absolute定位布局和fit-content自適應內容寬度

本篇主要實現全屏頁面的布局&#xff0c;其中還涉及內容自適應寬度。 創建一個preview.vue頁面用于圖片預覽&#xff0c;寫入以下代碼&#xff1a; <template><view class"preview"><swiper circular><swiper-item v-for"item in 5&quo…

OVS Faucet Tutorial筆記(下)

官方文檔&#xff1a; OVS Faucet Tutorial 5、Routing Faucet Router 通過控制器模擬三層網關&#xff0c;提供 ARP 應答、路由轉發功能。 5.1 控制器配置 5.1.1 編輯控制器yaml文件&#xff0c;增加router配置 rootserver1:~/faucet/inst# vi faucet.yaml dps:switch-1:d…

PCB設計教程【大師篇】stm32開發板PCB布線(信號部分)

前言 本教程基于B站Expert電子實驗室的PCB設計教學的整理&#xff0c;為個人學習記錄&#xff0c;旨在幫助PCB設計新手入門。所有內容僅作學習交流使用&#xff0c;無任何商業目的。若涉及侵權&#xff0c;請隨時聯系&#xff0c;將會立即處理 1. 布線優先級與原則 - 遵循“重…

Phthon3 學習記錄-0613

List&#xff08;列表&#xff09;、Tuple&#xff08;元組&#xff09;、Set&#xff08;集合&#xff09;和 Dictionary&#xff08;字典&#xff09; 在接口自動化測試中&#xff0c;List&#xff08;列表&#xff09;、Tuple&#xff08;元組&#xff09;、Set&#xff08…

UVa12298 3KP-BASH Project

UVa12298 3KP-BASH Project 題目鏈接題意輸入格式輸出格式 分析AC 代碼 題目鏈接 UVa12298 3KP-BASH Project 題意 摘自 《算法競賽入門經典&#xff1a;訓練指南》劉汝佳&#xff0c;陳鋒著。有刪改。 你的任務是為一個假想的 3KP 操作系統編寫一個簡單的 Bash 模擬器。由于操…

云打包生成的ipa上傳構建版本經驗分享

在上架ios應用&#xff0c;在蘋果開發者中心操作的時候&#xff0c;需要提供一個構建版本&#xff0c;如下圖所示&#xff1a; 點擊藍色加號&#xff0c;添加構建版本&#xff0c;但是點擊藍色加號后&#xff0c;并沒有構建版本可以選。 原因是需要下載下面它推薦的工具來上傳…

ESP32的spi通訊(Arduino)

目錄 一.基本配置 1.esp32-wroom-32引腳圖 2.接線方式 3.Arduino芯片選擇和庫文件 3.1Arduino配置&#xff08;2.0.11&#xff09; 3.2 下載ESP32SPISlave庫&#xff08;0.6.8&#xff09;文件 二、代碼編寫 1.主機代碼 2.從機代碼 3.注意事項 三、運行效果 一.基本…

Spring-rabbit重試消費源碼分析

在集成RabbitMQ與Spring Boot 3.1.x時&#xff0c;RetryOperationsInterceptor 是實現消息重試機制的關鍵組件。這里將深入分析 RetryOperationsInterceptor 的工作原理&#xff0c;尤其是在消費者消費失敗時的行為&#xff0c;并結合底層源碼進行詳解。 一、配置解析 首先&a…