跳转至

Air780EGP/EGG/EGH + Air5101S 蓝牙功能演示

作者:王世豪 | 最后修改:2026-04-14

一、概述

本演示项目展示了 Air780EGG/EGP/EGH 核心板通过 Air5101S 蓝牙模块实现蓝牙低功耗(BLE)通信的完整功能演示。

项目采用模块化设计,支持多种蓝牙功能演示,为开发者提供 Air5101S 蓝牙模块的使用参考方案。

通过本演示,开发者可以学习如何:

  • 使用 Air5101S 蓝牙模块进行 BLE 通信
  • 实现基于蓝牙的数据收发功能
  • 处理蓝牙连接状态和数据传输
  • 配置蓝牙模块参数和功能

二、演示功能概述

本 demo 演示的核心功能为:

基础功能

  • 双向数据通信:中心设备与外围设备的数据交互
  • 设备参数管理:设备名称、MAC 地址、固件版本等参数配置

高级功能

  • 看门狗保护:看门狗初始化和喂狗机制,确保系统稳定性
  • 低功耗控制:支持 P0/P1/P3 三种功耗模式切换

三、准备硬件环境

3.1 Air780EGG/EGP/EGH 核心板

使用 Air780EGG/EGP/EGH 核心板,如下图所示:

此核心板的详细使用说明参考:硬件手册和证书 中的 Air780EGG/EGP/EGH 核心板使用说明

3.2 Air5101S 开发板

3.3 PC 电脑

WINDOWS 10 及以上系统,其他暂无特别要求;

3.4 数据通信线

USB 数据线(其一端为 Type-C 接口,用于连接 Air780EGG/EGP/EGH 核心板)。

Air780EGG/EGP/EGH 核心板和数据线的硬件接线方式为:

  • Air780EGG/EGP/EGH 核心板通过 TYPE-C USB 口供电,核心板正面的 ON/OFF 拨动开关 拨到 ON 一端;
  • TYPE-C USB 数据线直接插到核心板的 TYPE-C USB 座子,另外一端连接电脑 USB 口;

3.5 接线说明

Air780EGG/EGP/EGH
Air5101S
UART1_TX
RXD
UART1_RX
TXD
GND
GND
3.3V
VBAT

四、准备软件环境

4.1 软件环境

  1. 烧录工具:Luatools 下载调试工具
  2. 内核固件:本demo开发测试时使用的固件为Air780EGH V2032 版本固件,本demo对固件版本没有什么特殊要求,所以你如果要测试本demo时,可以直接使用最新版本的内核固件;如果发现最新版本的内核固件测试有问题,可以使用我们开发本demo时使用的内核固件版本来对比测试;
  3. 脚本文件:https://gitee.com/openLuat/LuatOS/tree/master/module/Air780EHM_Air780EHV_Air780EGH/demo/ble/peripheral/Air780EHM_Air5101S
  4. LuatOS 运行所需要的 lib 文件:使用 Luatools 烧录时,勾选 添加默认 lib 选项,使用默认 lib 脚本文件。

准备好软件环境之后,接下来查看如何烧录项目文件到 Air780EGG/EGP/EGH 核心板中,将本篇文章中演示使用的项目文件烧录到 Air780EGG/EGP/EGH 核心板中。

五、API 接口说明

详细 API 文档请参考:

exril_5101 扩展库:https://docs.openluat.com/osapi/ext/exril_5101/

六、代码示例介绍

6.1 项目架构

main.lua (入口文件)
    ├── exril_5101_main.lua (主控模块)
    │   ├── exril_5101_receiver.lua (数据接收)
    │   └── exril_5101_sender.lua (数据发送)
    ├── exril_5101_timer.lua (定时发送数据)
    ├── exril_5101_wdt.lua (看门狗)
    └── exril_5101_lowpower.lua (低功耗控制)

6.2 模块功能说明

6.2.1 main.lua - 入口文件

  • 项目入口和总体调度
  • 加载所有功能模块
  • 定义项目名称和版本号

6.2.2 exril_5101_main.lua - 主控模块

1、核心功能

  • BLE 功能初始化和设备参数配置
  • 处理所有 BLE 事件(连接、断开、数据接收、错误处理)
  • 协调各模块间的通信

2、初始化

-- 默认配置参数
local default_config = {
    -- 设备名称(不超过20字符)
    device_name = "Air5101_Test",
    -- -- 广播类型(可连接)
    -- adv_type = exril_5101.ADV_C,
    -- -- 广播间隔(毫秒)
    -- adv_interval = 30,
    -- -- 广播数据
    -- adv_data = "02010603031218",
}

-- 初始化配置
local function init_config()
    log.info("exril_5101_main", "========== 配置初始化 ==========")

    -- 1. 获取当前工作模式
    local success, mode = exril_5101.mode()

    -- 2. 切换到AT模式(确保可以配置参数)
    log.info("exril_5101_main", "切换到AT指令模式...")
    success, mode = exril_5101.mode(exril_5101.MODE_AT)

    -- 3. 配置设备参数
    log.info("exril_5101_main", "配置设备参数...")
    local config_result, err = exril_5101.set({
        name = default_config.device_name,
        mtu_len = 247,
    })

    -- 4. 查询设备信息
    log.info("exril_5101_main", "查询设备信息...")
    local info, err = exril_5101.get({"name", "mac", "ver"})

    return true
end

初始化步骤:

  • 模式检查:获取当前工作模式状态
  • 模式切换:切换到 AT 模式进行参数配置

3、BLE 事件回调函数

-- BLE事件回调函数
local function ble_event_cb(event, payload)    
    if event == "connected" then
        sys.sendMsg(TASK_NAME, "BLE_EVENT", "CONNECTED", payload)
    elseif event == "disconnected" then
        sys.sendMsg(TASK_NAME, "BLE_EVENT", "DISCONNECTED", payload)
    elseif event == "data" then
        sys.sendMsg(TASK_NAME, "BLE_EVENT", "DATA_RECV", payload)
    elseif event == "error" then
        log.warn("收到错误码:", payload.error_type, payload.error_code)
    elseif event == "system" and payload.type == "mac" then
        sys.sendMsg(TASK_NAME, "BLE_EVENT", "REBOOT_DETECTED")
    end
end

事件处理逻辑:

  • 连接成功:发送 CONNECTED 消息到主任务
  • 连接断开:发送 DISCONNECTED 消息到主任务
  • 数据接收:发送 DATA_RECV 消息到主任务
  • 错误处理:记录错误码,不中断流程
  • 系统事件:检测设备重启,触发重新初始化

4、主任务处理函数

-- 主任务处理函数
local function exril_5101_main_task_func()
    local msg

    while true do
        -- 初始化配置
        local result = init_config()

        -- 注册BLE事件回调
        exril_5101.on(ble_event_cb)
        log.info("exril_5101_main", "BLE事件回调已注册")

        -- 主模块初始化完成,通知其他模块
        sys.publish("EXRIL_5101_MAIN_READY")

        while true do
            msg = sys.waitMsg(TASK_NAME, "BLE_EVENT")
            log.info("exril_5101_main", "收到BLE事件:", msg[2], msg[3])

            -- 设备重启
            if msg[2] == "REBOOT_DETECTED" then
                log.info("exril_5101_main", "检测到设备重启,重新初始化...")
                goto EXCEPTION_PROC
            end

            -- 蓝牙连接成功
            if msg[2] == "CONNECTED" then
                log.info("exril_5101_main", "蓝牙连接成功")
                -- 通知 sender 连接成功
                sys.sendMsg(exril_5101_sender.TASK_NAME, "BLE_EVENT", "CONNECTED", true)

            -- 蓝牙断开连接
            elseif msg[2] == "DISCONNECTED" then
                log.info("exril_5101_main", "蓝牙断开连接")
                -- 通知 sender 连接断开
                sys.sendMsg(exril_5101_sender.TASK_NAME, "BLE_EVENT", "DISCONNECTED")

            -- 收到数据
            elseif msg[2] == "DATA_RECV" then
                local payload = msg[3]
                if payload and payload.data then
                    -- 调用 receiver 处理接收到的数据
                    exril_5101_receiver.proc(payload.mode, payload.data)
                end
            end
        end

        -- 出现异常
        ::EXCEPTION_PROC::

        -- 清空此task绑定的消息队列中的未处理的消息
        sys.cleanMsg(TASK_NAME)

        -- 5秒后跳转到循环体开始位置,自动重新初始化
        log.info("exril_5101_main", "等待5秒后重新尝试...")
        sys.wait(5000)
    end
end

任务处理逻辑:

  • 消息循环:使用 sys.waitMsg() 等待 BLE 事件
  • 事件分发:根据事件类型调用相应处理逻辑
  • 异常处理:支持设备重启检测和自动重试
  • 资源清理:异常时清空消息队列

5、模块协调机制

模块间通信:

  • 连接状态通知:连接/断开时通知 exril_5101_sender 模块
  • 数据接收处理:收到数据时调用 exril_5101_receiver.proc() 处理
  • 初始化完成信号:发布 EXRIL_5101_MAIN_READY 通知看门狗模块

错误处理策略:

  • 初始化失败:5 秒后自动重试
  • 设备重启:检测到重启后重新初始化
  • 消息队列清理:异常时清空未处理消息

6.2.3 exril_5101_receiver.lua - 数据接收模块

  • 处理接收到的 BLE 写入请求数据
  • 发布 RECV_BLE_DATA 消息供其他应用模块订阅
local exril_5101_receiver = {}

-- 处理接收到的BLE数据
function exril_5101_receiver.proc(mode, data)
    log.info("exril_5101_receiver", "收到数据 [模式:" .. mode .. "]:", data)

    -- 发布消息供其他模块订阅
    sys.publish("RECV_BLE_DATA", mode, data)
end

return exril_5101_receiver

6.2.4 exril_5101_sender.lua - 数据发送模块

1、核心功能

  • 管理 BLE 数据发送队列
  • 处理 SEND_DATA_REQ 消息
  • 控制数据发送流程

2、数据队列管理

-- 数据发送队列
local send_queue = {}

-- 当前正在发送的数据项
local current_send_item = nil

功能说明:

  • 使用 Lua 表实现 FIFO(先进先出)队列
  • send_queue 存储待发送的数据项
  • current_send_item 记录当前正在发送的数据

3、发送请求处理

-- "SEND_DATA_REQ"消息的处理函数
local function send_data_req_proc_func(data, cb)
    table.insert(send_queue, {data = data, cb = cb})
    sys.sendMsg(TASK_NAME, "BLE_EVENT", "SEND_REQ", ble_connected)
end

sys.subscribe("SEND_DATA_REQ", send_data_req_proc_func)

处理流程:

  • 订阅"SEND_DATA_REQ"消息,接收到发送请求
  • 将数据项插入发送队列
  • 发送消息通知发送任务有新数据
  • 传递当前连接状态

4、数据发送逻辑

-- 按顺序发送send_queue中的数据
local function send_item_func()
    while #send_queue>0 do
        current_send_item = table.remove(send_queue, 1)
        local result = exril_5101.send(current_send_item.data)

        if result then
            send_item_cbfunc(true)
            return
        else
            if current_send_item.cb then
                current_send_item.cb.func(false, current_send_item.cb.para)
            end
        end
    end
end

发送流程:

  • 循环处理队列中的每个数据项
  • 调用 exril_5101.send() 接口发送数据
  • 发送成功:执行回调并返回
  • 发送失败:立即通知调用方失败

5、连接状态管理

-- BLE连接状态
local ble_connected = false

-- 连接成功处理
if msg[2] == "CONNECTED" then
    ble_connected = true
    sys.publish("BLE_CONNECT_STATUS", true)
    send_item_func()

-- 连接断开处理  
elseif msg[2] == "DISCONNECTED" then
    ble_connected = false
    sys.publish("BLE_CONNECT_STATUS", false)
    -- 清空队列并通知所有发送失败
end

状态管理:

  • 连接成功:立即开始发送队列数据
  • 连接断开:清空队列,通知所有发送失败
  • 状态同步:发布连接状态供其他模块使用

6、错误处理机制

-- 处理发送结果的回调函数
local function send_item_cbfunc(result)
    if current_send_item and current_send_item.cb then
        current_send_item.cb.func(result, current_send_item.cb.para)
    end
end

错误处理:

  • 发送失败时立即执行回调通知调用方
  • 连接断开时清空队列并通知所有失败
  • 确保每个发送请求都有结果反馈

6.2.5 exril_5101_timer.lua - 定时器模块

1、核心功能

  • 创建循环定时器定时发送数据
  • 根据 BLE 连接状态控制定时器启停
  • 演示 notify 数据发送功能

2、配置参数定义

-- 配置参数
local config = {
    notify_interval = 5000,  -- notify发送间隔(毫秒)
    counter = 0,            -- 计数器
}

参数说明:

  • notify_interval:定时发送间隔,默认 5 秒
  • counter:发送计数器,记录发送次数

3、定时器回调函数

-- 定时器回调函数 - 发送notify数据
function send_notify_data_timer_cbfunc()
    config.counter = config.counter + 1
    local notify_data = "Notify " .. config.counter .. " " .. os.date("%H:%M:%S")

    -- 发布消息"SEND_DATA_REQ"
    sys.publish("SEND_DATA_REQ", "timer", notify_data, 
        {func = send_data_cbfunc, para="notify "..notify_data})
end

定时器逻辑:

  • 每次执行计数器加 1
  • 生成包含序号和时间的通知数据
  • 发布发送请求到数据发送模块
  • 包含回调函数用于结果处理

4、连接状态处理

-- BLE连接状态处理函数
local function ble_connect_status_handler(status)
    if status then
        -- 蓝牙连接成功,启动定时器
        sys.timerLoopStart(send_notify_data_timer_cbfunc, config.notify_interval)
        log.info("exril_5101_timer", "已启动notify发送定时器, 间隔:", config.notify_interval, "ms")

    else
        -- 蓝牙断开连接,停止定时器
        sys.timerStop(send_notify_data_timer_cbfunc)
        log.info("exril_5101_timer", "已停止notify发送定时器")

        -- 重置计数器
        config.counter = 0
    end
end

-- 订阅BLE连接状态事件
sys.subscribe("BLE_CONNECT_STATUS", ble_connect_status_handler)
  • 连接成功:启动循环定时器,开始周期性发送
  • 连接断开:停止定时器,重置计数器
  • 状态订阅:监听 BLE 连接状态变化

5、发送结果回调

-- 数据发送结果回调函数
local function send_data_cbfunc(result, para)
    log.info("exril_5101_timer", "发送结果:", result, "参数:", para)
end

回调功能:

  • 记录发送成功/失败结果

6.2.6 exril_5101_wdt.lua - 看门狗模块

1、核心功能

  • 看门狗初始化和配置
  • 定时喂狗任务
  • 系统异常保护

2、配置参数定义

-- 配置参数
local config = {
    timeout = 60,           -- 看门狗超时时间(秒)
    level = 0,              -- 超时动作电平
    width = 100,            -- 复位脉冲宽度(毫秒)
    feed_interval = 20000,  -- 喂狗间隔(毫秒)
}

参数说明:

  • timeout:看门狗超时时间,60 秒后系统复位
  • level:超时动作电平,0 表示低电平复位
  • width:复位脉冲宽度,100ms 确保可靠复位
  • feed_interval:喂狗间隔,20 秒(安全余量)

3、初始化任务

-- 看门狗初始化任务
local function wdt_init_task()
    log.info("exril_5101_wdt", "等待主模块初始化完成...")

    local result = sys.waitUntil("EXRIL_5101_MAIN_READY", 30000)
    if not result then
        log.error("exril_5101_wdt", "等待主模块初始化超时(30秒),看门狗初始化失败")
        return
    end

    log.info("exril_5101_wdt", "收到主模块初始化完成信号,开始初始化看门狗...")

    -- 1. 检查当前工作模式
    local success, mode = exril_5101.mode()

    -- 2. 如果不是AT模式,先切换到AT模式
    if mode ~= exril_5101.MODE_AT then
        success, mode = exril_5101.mode(exril_5101.MODE_AT)
    end

    -- 3. 初始化看门狗
    success = exril_5101.wdt.init(config.timeout, config.level, config.width)
    if success then
        log.info("exril_5101_wdt", "看门狗初始化成功")

        -- 启动喂狗任务
        sys.taskInit(watchdog_feed_task)
    else
        log.error("exril_5101_wdt", "看门狗初始化失败")
    end
end

初始化流程:

  • 依赖等待:等待主模块 EXRIL_5101_MAIN_READY 信号,30 秒超时
  • 模式检查:获取当前工作模式
  • 模式切换:如果不是 AT 模式,自动切换到 AT 模式
  • 看门狗初始化:配置超时时间、电平、脉冲宽度
  • 任务启动:初始化成功后启动喂狗任务

4、喂狗任务

-- 喂狗任务
local function watchdog_feed_task()
    log.info("exril_5101_wdt", "喂狗任务启动,间隔:", config.feed_interval / 1000, "秒")

    while true do
        sys.wait(config.feed_interval)

        -- 使用wdt.feed(),它会自动处理:
        -- 1. 检查看门狗是否已初始化
        -- 2. 自动切换到AT模式(如果需要)
        -- 3. 执行喂狗(最高优先级)
        -- 4. 自动切回原模式
        local success = exril_5101.wdt.feed()
        if success then
            log.debug("exril_5101_wdt", "喂狗成功")
        else
            log.error("exril_5101_wdt", "喂狗失败")
        end
    end
end

喂狗机制:

  • 定时执行:20 秒间隔循环喂狗
  • 自动处理:exril_5101.wdt.feed() 自动处理模式切换
  • 状态监控:记录喂狗成功/失败状态

6.2.7 exril_5101_lowpower.lua - 低功耗控制模块

1、核心功能

  • 支持三种功耗模式切换,本模块只是一个功能演示
  • 发布 POWER_STATE_CHANGED 消息
  • 功耗状态管理

2、配置参数定义

-- 配置参数
local config = {
    enable = true,              -- 是否启用低功耗控制
    normal_duration = 10000,    -- 常规模式持续时间(毫秒)
    lowpower_duration = 10000,  -- 低功耗模式持续时间(毫秒)
    lowpower_mode = exril_5101.P1,  -- 低功耗模式
    wakeup_retry = 3,           -- 唤醒重试次数
    wakeup_delay = 300,         -- 唤醒重试间隔(毫秒)
}

-- 当前功耗状态
local current_power_mode = exril_5101.P0

参数说明:

  • enable:是否启用低功耗控制
  • normal_duration:常规模式持续时间,默认 10 秒
  • lowpower_duration:低功耗模式持续时间,默认 10 秒
  • lowpower_mode:低功耗模式选择,默认 P1 模式
  • wakeup_retry:唤醒重试次数,默认 3 次
  • wakeup_delay:唤醒重试间隔,默认 300ms
  • current_power_mode:当前功耗状态,初始为 P0

3、进入低功耗模式

-- 切换到低功耗模式
local function enter_lowpower()
    log.info("lowpower", "进入低功耗模式...")

    -- 检查并切换到AT模式
    local success, mode = exril_5101.mode()
    if success and mode ~= exril_5101.MODE_AT then
        log.info("lowpower", "当前不在AT模式,切换到AT模式...")
        local success = exril_5101.mode(exril_5101.MODE_AT)
        if not success then
            log.error("lowpower", "切换到AT模式失败")
            return false
        end
    end

    local success, msg = exril_5101.power(config.lowpower_mode)
    if success then
        current_power_mode = config.lowpower_mode
        sys.publish("POWER_STATE_CHANGED", current_power_mode)
        log.info("lowpower", "已进入低功耗模式:", current_power_mode)
        return true
    else
        log.error("lowpower", "进入低功耗模式失败:", msg)
        return false
    end
end

进入低功耗流程:

  • 模式检查:检查当前工作模式
  • 模式切换:如果不是 AT 模式,自动切换到 AT 模式
  • 功耗切换:调用 exril_5101.power() 进入低功耗模式
  • 状态更新:更新当前功耗状态
  • 消息发布:发布 POWER_STATE_CHANGED 消息
  • 错误处理:记录操作失败信息

4、唤醒到常规模式

-- 唤醒并切换到常规模式
local function wakeup_to_normal()
    log.info("lowpower", "唤醒到常规模式...")

    for i = 1, config.wakeup_retry do
        log.info("lowpower", "尝试唤醒 (" .. i .. "/" .. config.wakeup_retry .. ")...")

        local success, msg = exril_5101.power(exril_5101.P0, true)
        if success then
            current_power_mode = exril_5101.P0
            sys.publish("POWER_STATE_CHANGED", current_power_mode)
            log.info("lowpower", "第" .. i .. "次唤醒成功")
            return true
        else
            log.error("lowpower", "第" .. i .. "次唤醒失败:", msg)
        end

        if i < config.wakeup_retry then
            sys.wait(config.wakeup_delay)
        end
    end

    log.error("lowpower", "多次唤醒失败")
    return false
end

唤醒流程:

  • 重试机制:支持最多 3 次唤醒尝试
  • 延迟等待:每次重试间隔 300ms
  • 状态恢复:唤醒成功后切换到 P0 常规模式
  • 消息通知:发布状态变化消息
  • 详细日志:记录每次唤醒尝试结果

5、功耗模式特性

三种功耗模式:

P0 常规模式:蓝牙正常工作;

P1 低功耗模式:可被发现和连接,唤醒后,会在 80ms 后再次进入 P1。

P3 低功耗模式:可被发现和连接,唤醒后,自动退出 P3,进入常规模式 P0;

模式选择策略:

演示用途:默认使用 P1 模式进行演示

实际应用:根据具体需求选择合适的功耗模式

可配置性:支持通过配置参数修改模式

七、功能演示

7.1 数据传输功能

7.1.1 外围设备接收中心设备的写入数据

注:nrf connect 作为中心设备,AirEGP/EGG/EGH+Air5101S 作为外围设备。

1、烧录示例 demo 到 AirEGP/EGG/EGH 核心板后,手机端打开 nrf connect 蓝牙调试软件,找到广播的设备名称为"Air5101_Test"的设备并连接。

2、手机连接 Air5101S 后,界面如下所示:

Generic Access 和 Generic Attribute 是 BLE 共有的服务,Unknown Service 为广播者自定义添加的服务,点开 Unknown Service ,对应的是 Air5101S 的服务 UUID 和特征值 UUID 以及其属性值。

3、中心设备发送,外围设备被动接收

手机通过 nrf connect 中服务 UUID=0xff00,特征值 UUID=0xff02(可写操作),向外围设备发送数据。

nrf connect 操作界面如下:

luatools 日志如下:

7.1.2 外围设备向中心设备发送 notify 数据

注:nrf connect 作为中心设备,AirEGP/EGG/EGH+Air5101S 作为外围设备。外围设备向中心设备发送 notify 数据,需要中心设备先开启 notify 订阅,下图是 nrf connec 开启订阅的方式,点击图标”↓↓↓“即可。

点击图标”↓↓↓“后,APP 后台自动监听从设备 notify 上来的数据,右滑界面,可以看到接收到的每条数据。

7.2 定时喂狗

初始化后,主控会按照设定的 20s 间隔定时喂狗,如下图所示:

如果主控喂狗超时,Air5101S 会复位主控。

7.3 低功耗模式下唤醒

示例代码默认关闭了低功耗演示,测试低功耗以及唤醒的时候可以打开。

打开低功耗模块后,Air5101S 会在开机 10s 后进入低功耗模式,然后 10s 后会被主控唤醒并切换到常规模式,如下图所示,可以发现唤醒后可以正常进行喂狗操作。

八、常见问题与解决方案

8.1 如何判断 Air5101S 和主设备是否连接?

1、主动调用 exril_5101.status(timeout) 接口,查询当前连接状态。

2、通过 exril_5101.on(callback) 回调事件的"connected"和"disconnected" 事件来判断是否连接。

8.2 数据发送失败

1、BLE 连接状态异常

2、发送队列阻塞

3、数据格式不正确

九、总结

本演示项目为开发者提供了完整的 Air5101S 蓝牙模块使用方案,通过模块化设计实现了 BLE 通信、数据收发、看门狗保护和低功耗控制等核心功能。项目适用于物联网设备、数据采集、远程控制等应用场景,具有功能完整、稳定性高、易于使用的特点,为基于没有蓝牙功能的 Air780EGG/EGP/EGH 模组 + Air5101S 的蓝牙应用开发提供了示例参考。