当前位置: 首页 > news >正文

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 事件,同时保持对底层硬件资源的高效利用,非常适合低功耗蓝牙设备的开发场景。

相关文章:

  • PID 控制算法 | 参数整定 | 方法 / 仿真 / 应用案例
  • 先理解软件工程,再谈AI辅助研发
  • 访问网页的全过程
  • 【计网】导航
  • 常见内核TCP参数描述与配置
  • libuv 框架
  • 介质访问控制——随机访问控制
  • 大模型笔记5:Agent
  • 企业信息技术外包管理制度:如何安全高效管理IT外包服务
  • NodeJS的yarn和npm作用和区别,为什么建议用yarn
  • 分类预测 | Matlab基于AOA-VMD-GRU故障诊断分类预测
  • 3.创建数据库
  • 深度学习---ONNX(Open Neural Network Exchange)
  • 路由的相关知识
  • Python•元组集合字符串
  • 山东大学项目实训-创新实训-法律文书专家系统-项目报告(七)
  • C# 枚举(位标志)
  • GO语言---短变量声明
  • C#最佳实践:为何应减少嵌套
  • Adguard安卓版:全方位广告拦截与隐私保护
  • 残疾人网站服务平台/安新seo优化排名网站
  • 英国有哪些做折扣的网站/整合营销什么意思
  • 建设网站的服务项目/百家号权重查询
  • 正规广东网络推广公司/seo外推
  • WordPress建立电商网站/seo怎么做优化
  • seo推广方式是什么呢/安卓优化大师新版