极物科技 | DALI协议栈 - 配置命令详解
前言
在智能控制领域,"协议壁垒"与"系统稳定性"始终是绕不开的难题。极物科技(Zeewo)以 "重构空间交互体验" 为使命,通过自研的 极物 OS,实现了 KNX、DALI、CAN、RS485 等多种总线协议在单一主机上的深度融合。
我们认为,一个真正优秀的智能系统,不仅要实现灯光、遮阳、温控、音乐、安防等全生态设备的无界融合 ,更要确保本地运行、断网可用 ,并具备WEB 远程调试 和 OTA 固件升级的能力。基于此底层架构,我们推出了诸如带双路 DALI 的 KNX 主机、HomeKit 网桥等核心硬件,并将极物 OS 成功接入了 Apple HomeKit、小度、纯血鸿蒙及 HomeAssistant 等主流生态系统。
一句话概述:本文深入解析极物 DALI 协议栈 32-129 配置命令的完整实现逻辑。
本文聚焦于 DALI 配置命令集,涵盖 RESET、DTR 数据寄存器、场景设置、分组管理、地址配置、渐变参数设置等核心命令的处理流程,展示配置数据的内存映射与 EEPROM 持久化机制。


1. 配置命令总览
1.1 基础配置命令 (32-48)
| 命令值 | 命令名称 | 功能说明 |
|---|---|---|
| 32 | RESET | 恢复出厂设置 |
| 33 | STORE_ACTUAL_LEVEL_IN_THE_DTR | 保存当前亮度到 DTR0 |
| 34 | SAVE_PERSISTENT_VARIABLES | 保存变量到 EEPROM |
| 35 | SET_OPERATING_MODE | 设置操作模式 |
| 36 | RESET_MEMORY_BANK | 重置内存 Bank |
| 37 | IDENTIFY_DEVICE | 设备识别(闪烁) |
| 42 | SET_MAX_LEVEL_WITH_DTR0 | 设置最大亮度 |
| 43 | SET_MIN_LEVEL_WITH_DTR0 | 设置最小亮度 |
| 44 | SET_SYSTEM_FAILURE_LEVEL_WITH_DTR0 | 设置故障亮度 |
| 45 | SET_POWER_ON_LEVEL_WITH_DTR0 | 设置上电亮度 |
| 46 | SET_FADE_TIME_WITH_DTR0 | 设置渐变时间 |
| 47 | SET_FADE_RATE_WITH_DTR0 | 设置渐变速度 |
| 48 | SET_EXTENDED_FADE_TIME_WITH_DTR0 | 设置扩展渐变时间 |
1.2 场景配置命令 (64-95)
| 命令值 | 命令名称 | 功能说明 |
|---|---|---|
| 64~79 | SET_SCENE 0~15 WITH_DTR0 | 设置场景亮度 |
| 80~95 | REMOVE_FROM_SCENE 0~15 | 从场景移除 |
1.3 分组配置命令 (96-127)
| 命令值 | 命令名称 | 功能说明 |
|---|---|---|
| 96~111 | ADD_TO_GROUP 0~15 | 添加到分组 |
| 112~127 | REMOVE_FROM_GROUP 0~15 | 从分组移除 |
1.4 地址与内存命令 (128-129)
| 命令值 | 命令名称 | 功能说明 |
|---|---|---|
| 128 | SET_SHORT_ADDRESS_WITH_DTR0 | 设置短地址 |
| 129 | ENABLE_WRITE_MEMORY | 启用内存写入 |
2. 重复帧机制
所有配置命令都需要连续两帧相同数据才生效:
c
if ((slave_info->rec_data >= RESET) && (slave_info->rec_data <= ENABLE_WRITE_MEMORY)) {
if (repeat_flag == false) {
return RECEIVE_FIRST; // 第一帧,等待重复帧
}
}
3. 基础配置命令详解
3.1 RESET 命令 (32)
功能:恢复所有参数到出厂默认值。
c
case RESET:
dali.long_level = 0xfe000000;
last_active_level = POWER_MAX;
dali_ram.variable.target_level = POWER_MAX;
dali_ram.variable.power_on_level = POWER_MAX;
dali_ram.variable.system_failure_level = POWER_MAX;
dali_ram.variable.minimum_level = dali_ram.variable.physical_minimum_level;
dali_ram.variable.maximum_level = POWER_MAX;
dali_ram.variable.fade_rate = 0x07;
dali_ram.variable.fade_time = 0x00;
dali_ram.variable.extended_fade_time_base = 0;
dali_ram.variable.extended_fade_time_multiplier = 0;
dali_ram.variable.random_address.high = 0xFF;
dali_ram.variable.random_address.mid = 0xFF;
dali_ram.variable.random_address.low = 0xFF;
dali_ram.variable.group_0_7 = 0x00;
dali_ram.variable.group_8_15 = 0x00;
for (i = 0; i < 16; i++) {
dali_ram.variable.scene[i] = POWER_MASK;
}
current_fast_fade_time = 0x00;
dali_ram.variable.fast_fade_time = 0x00;
dali_ram.variable.dimming_curve = LOGARITHMIC;
update_flag |= VAR_UPDATE;
search_address.high = 0xFF;
search_address.mid = 0xFF;
search_address.low = 0xFF;
status_information |= RESET_STATE;
fade_direction = FADE_DIRECT;
break;
恢复默认值汇总:
| 参数 | 默认值 |
|---|---|
| target_level | 254 (MAX) |
| power_on_level | 254 |
| system_failure_level | 254 |
| minimum_level | physical_minimum_level |
| maximum_level | 254 |
| fade_rate | 7 |
| fade_time | 0 |
| group_0_7 | 0x00 |
| group_8_15 | 0x00 |
| scene0\~15 | 255 (MASK) |
| dimming_curve | LOGARITHMIC |
3.2 STORE_ACTUAL_LEVEL_IN_THE_DTR (33)
功能:将当前亮度保存到 DTR0。
c
case STORE_ACTUAL_LEVEL_IN_THE_DTR:
dtr0 = dali.s.level;
break;
3.3 SAVE_PERSISTENT_VARIABLES (34)
功能:触发 EEPROM 写入,保存所有变更数据。
c
case SAVE_PERSISTENT_VARIABLES:
dali_hal_save_persistent_variables();
if (status_information & FADE_RUNNING) {
fade_direction = FADE_DIRECT; // 停止渐变
}
break;
EEPROM 保存流程:
c
void dali_hal_save_persistent_variables(void) {
dali_eeprom_update_tick(); // 立即执行更新
}
void dali_eeprom_update_tick(void) {
dali_update_to_eeprom();
}
void dali_update_to_eeprom() {
if (update_flag == 0) return; // 无变更,不保存
for (i = DALI_DATA_NO_SAVE_INDEX + 1; i < g_dali_data_size; i++) {
errom_data = eeprom_read_cache(i);
if (*(g_dali_data_P + i) != errom_data) {
eeprom_write_cache(i, *(g_dali_data_P + i)); // 仅写入变更数据
}
}
eeprom_data_is_write_sucess();
update_flag = 0;
}
3.4 SET_OPERATING_MODE (35)
功能:设置操作模式(厂商自定义)。
c
case SET_OPERATING_MODE:
if ((dtr0 > 0) && (dtr0 < 0x80)) {
break; // 无效范围
}
dali_ram.variable.operating_mode = dtr0;
break;
3.5 IDENTIFY_DEVICE (37)
功能:触发设备识别(闪烁 10 秒)。
c
case IDENTIFY_DEVICE:
identify_flag = true;
w10s_identify_time = W10S; // 10 秒
if (status_information & FADE_RUNNING) {
fade_direction = FADE_DIRECT; // 停止渐变
}
break;
识别闪烁实现:
c
void dali_hal_identify_device(void) {
if (identify_delay-- == 0) {
identify_delay = 10;
} else {
return;
}
if (identify_count == 0XFFF) {
identify_count_flag = 0;
} else if (identify_count == 0) {
identify_count_flag = 1;
}
if (identify_count_flag) {
identify_count++;
} else {
identify_count--;
}
dali_hal_update_pwm_output(identify_count);
dali_hal_update_pwm_output_tc(identify_count);
}
4. 亮度参数配置
4.1 SET_MAX_LEVEL_WITH_DTR0 (42)
c
case SET_MAX_LEVEL_WITH_DTR0:
if (dtr0 > dali_ram.variable.minimum_level) {
dali_ram.variable.maximum_level = dtr0;
} else {
dali_ram.variable.maximum_level = dali_ram.variable.minimum_level;
}
if (dtr0 == POWER_MASK) {
dali_ram.variable.maximum_level = POWER_MAX;
}
// 如果当前亮度超过新最大值,限制到最大值
temp = dali_ram.variable.maximum_level;
if (dali.s.level > temp) {
dali.s.level = temp;
dali_ram.variable.target_level = temp;
fade_direction = FADE_DIRECT;
status_information |= LIMIT_ERROR;
} else {
if (status_information & FADE_RUNNING) {
fade_direction = FADE_DIRECT;
}
status_information &= ~LIMIT_ERROR;
}
update_flag |= VAR_UPDATE;
break;
4.2 SET_MIN_LEVEL_WITH_DTR0 (43)
c
case SET_MIN_LEVEL_WITH_DTR0:
if (dtr0 < dali_ram.variable.physical_minimum_level) {
dtr0 = dali_ram.variable.physical_minimum_level;
} else if (dtr0 > dali_ram.variable.maximum_level) {
dtr0 = dali_ram.variable.maximum_level;
}
dali_ram.variable.minimum_level = dtr0;
dali_cmd_direct_arc_power_control(dali_ram.variable.minimum_level);
update_flag |= VAR_UPDATE;
break;
4.3 SET_SYSTEM_FAILURE_LEVEL_WITH_DTR0 (44)
c
case SET_SYSTEM_FAILURE_LEVEL_WITH_DTR0:
dali_ram.variable.system_failure_level = dtr0;
dali_ram.variable.tc_fail_level = dali_ram.variable.tc_target_level;
update_flag |= VAR_UPDATE;
break;
4.4 SET_POWER_ON_LEVEL_WITH_DTR0 (45)
c
case SET_POWER_ON_LEVEL_WITH_DTR0:
dali_ram.variable.power_on_level = dtr0;
dali_ram.variable.tc_powon_level = dali_ram.variable.tc_target_level;
update_flag |= VAR_UPDATE;
break;
5. 渐变参数配置
5.1 SET_FADE_TIME_WITH_DTR0 (46)
c
case SET_FADE_TIME_WITH_DTR0:
if (dtr0 > 0x0F) {
dtr0 = 0x0F; // 限制到 0~15
}
dali_ram.variable.fade_time = dtr0;
update_flag |= VAR_UPDATE;
break;
5.2 SET_FADE_RATE_WITH_DTR0 (47)
c
case SET_FADE_RATE_WITH_DTR0:
if (dtr0 > 0x0F) {
dtr0 = 0x0F;
} else if (dtr0 == 0x00) {
dtr0 = 1; // LED 系统最小为 1
}
dali_ram.variable.fade_rate = dtr0;
update_flag |= VAR_UPDATE;
break;
5.3 SET_EXTENDED_FADE_TIME_WITH_DTR0 (48)
c
case SET_EXTENDED_FADE_TIME_WITH_DTR0:
if (dtr0 > 0x4F) {
dali_ram.variable.extended_fade_time_base = 0;
dali_ram.variable.extended_fade_time_multiplier = 0;
} else {
dali_ram.variable.extended_fade_time_base = dtr0 & 0x0F; // 低 4 bit
dali_ram.variable.extended_fade_time_multiplier = (dtr0 & 0x70) >> 4; // 高 3 bit
}
break;
扩展渐变时间计算:
c
uint16_t extended_fade_time_mul[] = {0, 1, 10, 100, 6000};
// 实际渐变时间 = extended_fade_time_base × multiplier
// 例如: base=5, multiplier=2 → 5 × 10 = 50 秒
6. 场景配置命令
6.1 SET_SCENE 0~15 WITH_DTR0 (64-79)
c
case SET_SCENE0_WITH_DTR0:
case SET_SCENE1_WITH_DTR0:
// ... 到 SET_SCENE15_WITH_DTR0
dali_ram.variable.scene[slave_info->rec_data & 0x0F] = dtr0;
dali_ram.variable.tc_scene[slave_info->rec_data & 0x0F] = dali_ram.variable.tc_target_level;
update_flag |= VAR_UPDATE;
break;
场景配置示例:
设置场景 5:
第一帧: SET_SCENE5_WITH_DTR0 (dtr0 = 180)
第二帧: SET_SCENE5_WITH_DTR0 (dtr0 = 180)
执行:
scene[5] = 180
tc_scene[5] = tc_target_level (当前色温)
6.2 REMOVE_FROM_SCENE 0~15 (80-95)
c
case REMOVE_FROM_SCENE0:
case REMOVE_FROM_SCENE1:
// ... 到 REMOVE_FROM_SCENE15
dali_ram.variable.scene[slave_info->rec_data & 0x0F] = POWER_MASK;
update_flag |= VAR_UPDATE;
break;
效果:场景值设为 255 (MASK),调用该场景时不改变灯具状态。
7. 分组配置命令
7.1 ADD_TO_GROUP 0~15 (96-111)
c
case ADD_TO_GROUP0:
case ADD_TO_GROUP1:
// ... 到 ADD_TO_GROUP7
low = slave_info->rec_data & 0x07;
temp = dali_ram.variable.group_0_7;
temp = temp | (1 << low);
dali_ram.variable.group_0_7 = temp;
update_flag |= VAR_UPDATE;
break;
case ADD_TO_GROUP8:
case ADD_TO_GROUP9:
// ... 到 ADD_TO_GROUP15
low = slave_info->rec_data & 0x07;
temp = dali_ram.variable.group_8_15;
temp = temp | (1 << low);
dali_ram.variable.group_8_15 = temp;
update_flag |= VAR_UPDATE;
break;
分组位映射:
group_0_7: bit0=组0, bit1=组1, ..., bit7=组7
group_8_15: bit0=组8, bit1=组9, ..., bit7=组15
设备属于组 3 和组 10:
group_0_7 = 0x08 (bit3=1)
group_8_15 = 0x04 (bit2=1, 对应组10)
7.2 REMOVE_FROM_GROUP 0~15 (112-127)
c
case REMOVE_FROM_GROUP0:
case REMOVE_FROM_GROUP1:
// ... 到 REMOVE_FROM_GROUP15
low = slave_info->rec_data & 0x07;
temp = dali_ram.variable.group_0_7; // 或 group_8_15
temp = temp & ~(1 << low);
dali_ram.variable.group_0_7 = temp;
update_flag |= VAR_UPDATE;
break;
8. 地址与内存命令
8.1 SET_SHORT_ADDRESS_WITH_DTR0 (128)
c
case SET_SHORT_ADDRESS_WITH_DTR0:
if (dtr0 == ADDR_MASK) {
// 删除短地址
dali_ram.variable.short_address = ADDR_MASK;
update_flag |= VAR_UPDATE;
status_information |= MISSING_SHORT_ADDR;
} else if ((dtr0 & 0x81) == 0x01) {
// dtr0 格式: 0AAA AAA1 → 00AA AAAA
dali_ram.variable.short_address = (dtr0 >> 1);
update_flag |= VAR_UPDATE;
status_information &= ~MISSING_SHORT_ADDR;
}
break;
地址格式说明:
DTR0 = 0x0B (0000 1011)
→ short_address = 0x0B >> 1 = 0x05 (5)
DTR0 = 0xFF (ADDR_MASK)
→ short_address = 0xFF (未编址)
8.2 ENABLE_WRITE_MEMORY (129)
c
case ENABLE_WRITE_MEMORY:
write_memory_enabled = true;
break;
启用后,允许通过 WRITE_MEMORY_LOCATION 命令写入 Memory Bank。
9. DTR 数据寄存器
9.1 三个 DTR 寄存器
c
uint8_t dtr0 = 0x00; // 数据寄存器 0
uint8_t dtr1 = 0x00; // 数据寄存器 1
uint8_t dtr2 = 0x00; // 数据寄存器 2
9.2 DTR 设置方式
DTR 通过特殊命令设置:
c
case DATA_TRANSFER_REGISTER: // 0xA3
dtr0 = slave_info->rec_data;
break;
case DATA_TRANSFER_REGISTER_1: // 0xC3
dtr1 = slave_info->rec_data;
break;
case DATA_TRANSFER_REGISTER_2: // 0xC5
dtr2 = slave_info->rec_data;
break;
9.3 DTR 查询命令
c
case QUERY_CONTENT_DTR:
// 根据 dtr0 返回不同值
break;
case QUERY_CONTENT_DTR1:
ret = dtr1;
break;
case QUERY_CONTENT_DTR2:
ret = dtr2;
break;
10. 更新标志管理
10.1 更新标志定义
c
#define VAR_UPDATE (1 << 0) // 变量区更新
#define BANK0_UPDATE (1 << 1) // Bank0 更新
#define BANK1_UPDATE (1 << 2) // Bank1 更新
10.2 更新标志设置时机
| 命令类型 | 设置标志 |
|---|---|
| 亮度参数配置 | VAR_UPDATE |
| 场景配置 | VAR_UPDATE |
| 分组配置 | VAR_UPDATE |
| 地址配置 | VAR_UPDATE |
| Bank0 写入 | BANK0_UPDATE |
| Bank1 写入 | BANK1_UPDATE |
10.3 EEPROM 写入策略
c
void dali_update_to_eeprom() {
if (update_flag == 0) return; // 无变更
for (i = DALI_DATA_NO_SAVE_INDEX + 1; i < g_dali_data_size; i++) {
errom_data = eeprom_read_cache(i);
if (*(g_dali_data_P + i) != errom_data) {
eeprom_write_cache(i, *(g_dali_data_P + i)); // 差异写入
}
}
eeprom_data_is_write_sucess();
update_flag = 0; // 清除标志
}
11. 注意事项
- 重复帧要求:所有配置命令 (32-129) 需要连续两帧相同数据才生效
- DTR 持久性:DTR 值不保存到 EEPROM,断电后丢失
- 场景 MASK:场景值 255 表示"不改变",调用时跳过
- 分组位操作:使用位或/位与操作,不影响其他分组
- 地址格式 :短地址在 DTR0 中为
0AAA AAA1格式,需右移 1 位 - 渐变停止:配置参数时会停止当前渐变过程
- EEPROM 寿命:仅在数据变更时写入,避免频繁擦写
12. 相关文档
- 《极物科技 | DALI协议栈 - 架构总览与模块设计》
- 《极物科技 | DALI协议栈 - 物理层位编解码详解》
- 《极物科技 | DALI协议栈 - 帧传输状态机与地址解析》
- 《极物科技 | DALI协议栈 - 标准命令集解析》
- 《极物科技 | DALI协议栈 - 查询命令全解》
- 《极物科技 | DALI协议栈 - 特殊命令与设备发现机制》
- 《极物科技 | DALI调光灯 - 快速接入指南》
关于极物科技(ZEEWO)
极物科技(Zeewo)致力于为用户提供智能控制系统及硬件产品。我们以总线系统为技术底座,以**"稳定、可靠、快速响应"**为产品底线,是国内少有的拥有 KNX、DALI 全套软硬件自主研发能力的厂商之一。
我们的核心能力:
- 系统架构:自研极物 OS,支持多协议无界融合(KNX/DALI/CAN/RS485/IP)。
- 核心硬件:带双路 DALI 的 KNX 主机、超薄全金属定制面板、各类智选传感器及网关。
- 生态互联:深度融入 Apple HomeKit、Matter、小度、HomeAssistant 及纯血鸿蒙生态。
- 调试交付:独家支持 ETS 导出 XML 直接导入进行 APP 免编程调试,支持远程 WEB 运维。
我们的市场覆盖:
服务网点已覆盖全国核心城市(含长三角、珠三角、成渝等),并以高品质的方案深耕家居生活、酒店民宿、企业办公、疗愈康养、餐馆会所等多个细分领域。
(如果您在开发或落地中遇到技术问题,欢迎通过官网或后台私信与我交流探讨)

