20 极物科技 | DALI协议栈 - 配置命令详解

极物科技 | 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. 注意事项

  1. 重复帧要求:所有配置命令 (32-129) 需要连续两帧相同数据才生效
  2. DTR 持久性:DTR 值不保存到 EEPROM,断电后丢失
  3. 场景 MASK:场景值 255 表示"不改变",调用时跳过
  4. 分组位操作:使用位或/位与操作,不影响其他分组
  5. 地址格式 :短地址在 DTR0 中为 0AAA AAA1 格式,需右移 1 位
  6. 渐变停止:配置参数时会停止当前渐变过程
  7. 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 运维。

我们的市场覆盖:

服务网点已覆盖全国核心城市(含长三角、珠三角、成渝等),并以高品质的方案深耕家居生活、酒店民宿、企业办公、疗愈康养、餐馆会所等多个细分领域。

(如果您在开发或落地中遇到技术问题,欢迎通过官网或后台私信与我交流探讨)

相关推荐
阿钱真强道3 小时前
22 极物科技 | DALI协议栈 - 特殊命令与设备发现机制
极物·极物智能·极物科技·iec 62386·设备发现·dali协议栈·智慧照明
阿钱真强道21 小时前
19 极物科技 | DALI协议栈 - 标准命令集解析
极物·极物智能·极物科技·iec 62386·调光控制·dali协议栈·标准命令
阿钱真强道1 天前
17 极物科技 | DALI协议栈 - 物理层位编解码详解
曼彻斯特编码·极物·极物智能·极物科技·iec 62386·dali协议栈
阿钱真强道2 天前
16 极物科技 | DALI协议栈 - 架构总览与模块设计
智能家居·照明·极物·极物智能·极物科技·iec 62386·dali协议栈
阿钱真强道4 天前
11 极物科技 | DALI调光灯 - 功能接口与调试指南
智能照明·极物·极物智能·极物科技·dali调光灯·调光控制·调试指南
阿钱真强道4 天前
12 极物科技 | DALI调光灯 - 设备发现与地址分配机制
智能照明·极物·极物智能·极物科技·dali调光灯·设备发现·地址分配
阿钱真强道5 天前
09 极物科技 | DALI调光灯 - IEC 62386 底层协议解析
智能照明·总线协议·极物·极物智能·极物科技·dali调光灯·iec 62386
阿钱真强道6 天前
07 极物科技 | DALI调光灯 - 快速接入指南
智能照明·极物·极物智能·极物科技·dali调光灯·iec 62386·调光控制
阿钱真强道6 天前
08 极物科技 | DALI调光灯 - UDP 通讯协议规范
通讯协议·智能照明·极物·极物智能·极物科技·dali调光灯·iec 62386