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 软件环境
- 烧录工具:Luatools 下载调试工具
- 内核固件:本demo开发测试时使用的固件为Air780EGH V2032 版本固件,本demo对固件版本没有什么特殊要求,所以你如果要测试本demo时,可以直接使用最新版本的内核固件;如果发现最新版本的内核固件测试有问题,可以使用我们开发本demo时使用的内核固件版本来对比测试;
- 脚本文件:https://gitee.com/openLuat/LuatOS/tree/master/module/Air780EHM_Air780EHV_Air780EGH/demo/ble/peripheral/Air780EHM_Air5101S
- 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:唤醒重试间隔,默认 300mscurrent_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 的蓝牙应用开发提供了示例参考。