news 2026/7/19 1:09:56

MIPI DSI命令模式与总线翻转机制:嵌入式显示双向通信实战解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MIPI DSI命令模式与总线翻转机制:嵌入式显示双向通信实战解析

1. DSI命令模式:从单向指令到双向对话的基石

在嵌入式显示系统的开发中,我们常常需要与显示面板进行“对话”——不仅仅是单向地推送像素数据,更要能读取面板状态、获取操作确认,甚至协调帧更新的时机。MIPI DSI的命令模式(Command Mode)正是实现这种双向、精细化控制的核心机制。与视频模式(Video Mode)持续流式传输图像数据不同,命令模式更像是一问一答的协议交互,主机通过发送特定的数据包指令来控制面板的行为,例如初始化寄存器、设置亮度、或请求当前扫描线位置。

命令模式的核心价值在于其灵活性与低功耗特性。在系统待机、显示静态内容或仅需局部更新时,无需持续的高带宽视频流,通过发送简短的命令即可完成操作,能显著节省功耗。这对于电池供电的移动设备至关重要。然而,这种灵活性也带来了复杂性:如何确保命令被正确接收和执行?如何从面板获取响应?这就引入了总线翻转(Bus Turnaround, BTA)机制。你可以把DSI的物理链路(DP/DN差分对)想象成一条单行车道,默认情况下由主机(Host)控制器驾驶。当主机需要从面板(Peripheral)读取数据或等待一个确认(ACK)时,它必须先在安全区域“掉头”,把车钥匙(总线控制权)交给面板,等面板完成操作后,再交还回来。这个“掉头”过程就是BTA,它是一系列精心定义的LP(Low-Power)状态序列。

在实际操作中,命令的发送与BTA的触发紧密耦合。例如,当你通过直接命令接口发送一个DCS读命令(如读取面板ID)时,DSI控制器硬件通常会自动在命令包后附加一个BTA请求,无需软件显式触发。这是因为读操作的本质就是请求面板返回数据,必须让出总线。此时,软件的关键职责是等待:必须轮询read_completed状态位,或等待相应的中断,确认面板已经响应且总线控制权已成功收回后,才能发起下一次读写操作。如果忽视这个等待,在总线还未归还时就发起新命令,会导致数据冲突,命令丢失,这是新手最容易踩的坑之一。

对于写命令,情况略有不同。DSI规范并不强制要求每次写后都进行BTA来获取确认,但为了可靠性,尤其是在关键配置阶段(如初始化序列),强烈建议在重要的写命令后主动请求BTA。这相当于让面板回一个“收到”的纸条。你可以通过配置相关寄存器位来在写命令后插入BTA。此时,你需要检查write_completedBTA_finished状态位。如果追求极致简单和速度,且对少数命令丢失不敏感,也可以采用“盲写”加固定延时的方式。文档中提到一个经验值:命令间插入约100个TX_ESC_CLK周期的间隔。但更稳妥的做法是根据你的ESCAPE模式时钟频率和命令包长度,精确计算每个命令在总线上传输所需的最短时间,在此基础上留出余量。

注意:命令数据寄存器的细节陷阱向直接命令写数据寄存器(如direct_cmd_wrdat)写入参数时,有一个极易忽略的规范细节。对于单参数命令,你需要确保32位寄存器中未使用的高位字节被显式掩码为零。例如,如果你要发送一个8位参数,应确保写入的数据形如0x000000XX。许多硬件默认寄存器可能包含残留值,如果不做清零,发送出去的数据包中就会包含非零的垃圾数据。虽然部分面板可能忽略这些字节,但这违反了DSI规范,在某些严格遵循标准的屏上可能导致未定义行为。对于无参数的命令,在发送前,务必先通过写direct_cmd_fifo_rst寄存器来清空发送路径FIFO,然后再写入零值数据,以确保发送的是干净的零参数命令包。

2. 总线翻转(BTA)机制:控制权交接的精确舞步

总线翻转是DSI双向通信的咽喉要道,其过程如同一场精确编排的握手仪式。整个过程由物理层(D-PHY)的LP(低功耗)状态机驱动,软件通过配置协议层触发,但必须理解其硬件时序才能有效调试。

2.1 BTA的触发与状态流转

BTA的发起源于协议层。当命令流管理器(CSM)需要面板响应时,会向D-PHY发出一个“翻转请求”(Turn Request)。此时,如果总线处于空闲的LP11状态,D-PHY便会开始执行一系列标准的LP状态切换:LP11 → LP10 → LP00 → LP10 → LP00。这个序列是一个明确的信号,告知对端:“我将释放总线控制权”。值得注意的是,在最后一个LP00状态,控制器会持续驱动该状态2-3个TX_ESC_CLK周期,这是一个关键的稳定期,确保面板能可靠地检测到这个“释放”信号。

面板侧的D-PHY持续监测总线状态。一旦检测到控制器发出的完整LP翻转序列,它便知道控制器已“松手”。此时,面板会驱动总线进入LP00 → LP10 → LP11序列,这个反向序列宣告“我已接管总线”。控制器检测到这个序列后,会将内部的方向(Direction)信号从输出(0)切换为输入(1),正式进入接收模式。至此,总线控制权完成从主机到面板的移交。

面板在完成响应数据(如读数据、ACK触发包或错误报告包)的发送后,需要将总线归还。它会执行与主机相同的LP11→LP10→LP00→LP10→LP00序列。主机D-PHY检测到该序列后,会再次切换方向信号,收回总线控制权。整个双向BTA的时序,在文档的图12-483中有清晰展示,核心是两段对称的LP状态序列,中间夹着面板的数据传输阶段。

2.2 软件层的协同与状态监控

在软件驱动层面,我们并不直接操纵LP状态,而是通过一系列状态标志位来监控BTA的进程。理解每个标志位的含义是编写健壮驱动的基础:

  • cmd_transmission: 命令正在发送中。此位置位时,总线通常由主机控制,正在发送命令包。
  • BTA_completed: 主机发出的BTA请求序列已完成。这个标志位仅表示“我已经把释放总线的信号发出去了”,并不代表面板已经接管或响应完成。此时总线处于“无人驾驶”的过渡期。
  • BTA_finished: 面板已归还总线,主机重新成为控制器。这是安全发起下一个命令的唯一标志。只有检测到此位,才能确保总线已完全回到主机掌控。
  • read_completed/read_completed_with_err: 读操作整体完成。这包含了主机发送读命令、执行BTA、面板返回数据、面板执行BTA归还总线这一完整链条的成功或失败状态。
  • te_received: 收到了来自面板的撕裂效应(TE)触发信号。这在自动TE同步模式下是关键状态。
  • write_completed/trigger_completed: 写命令或触发命令发送完成。对于不要求BTA的简单写操作,此位置位即表示操作结束。

一个典型的带响应的命令操作流程如下:

  1. 软件配置并触发一个读命令。
  2. 轮询等待cmd_transmission位清零,表示命令包已发送完毕。
  3. 轮询等待BTA_completed置位,表示主机已发出总线释放请求。
  4. 轮询等待BTA_finished置位,表示面板已归还总线。在此之间,CPU只能等待,不能操作任何其他DSI命令寄存器
  5. 检查read_completedread_completed_with_err,确认读操作结果。
  6. 如果成功,从返回路径(RP)FIFO中读取数据。

实操心得:状态轮询与中断的取舍对于实时性要求不高的初始化流程,使用简单的轮询(Polling)等待状态位即可,代码简单。但对于在显示刷新关键路径(如等待TE信号以同步帧���新)上的操作,或者需要低功耗的场景,强烈建议使用中断。可以为BTA_finishedread_completedte_received等关键事件配置中断服务程序(ISR)。这能极大释放CPU资源,避免忙等待。在中断服务程序中,除了处理事件,务必清除相应的中断状态标志位,否则会导致中断持续触发或丢失后续中断。

2.3 异常处理与超时机制

BTA过程并非总是顺利。面板可能无响应、响应超时或返回错误。因此,驱动中必须加入超时(Timeout)机制。

  • BTA超时:从发出BTA请求(BTA_completed置位)到收回总线(BTA_finished置位)应有时间上限。这个超时值需要根据面板手册中规定的最大响应时间来设定,通常需要考虑面板内部处理时间、总线LP状态切换时间等。如果超时,应视为通信故障,进行错误恢复(如重置D-PHY链路)。
  • 数据接收超时:在BTA_finished置位后,如果预期有读数据返回,但RP FIFO中迟迟没有数据或数据不完整,也应设定超时。这可能意味着面板虽然归还了总线,但并未发送有效数据包。

当发生超时或检测到错误状态位(如read_completed_with_err)时,完整的错误恢复流程应包括:

  1. 停止当前所有待处理的命令传输。
  2. 重置命令流管理器(CSM)和返回路径(RP)的相关状态机。
  3. 清空发送和接收FIFO。
  4. 根据情况,可选择执行一次轻量级的D-PHY重新初始化(如触发ULPS退出序列)。
  5. 重新发送失败的命令或从错误点恢复业务流程。

3. 返回路径(RP)与数据接收:解析来自面板的“回音”

当总线控制权通过BTA移交给面板后,主机便切换为接收者角色。返回路径(Return Path, RP)模块负责处理从D-PHY接收到的所有数据,其行为类似于一个目标设备(Target)。理解RP的工作机制,是正确处理面板响应的关键。

3.1 RP的接口与数据流

RP通过一组信号与D-PHY的接收接口连接,核心信号如下表所示:

信号名称方向描述
direction输入方向标志。高电平表示D-PHY处于接收模式(面板正在发送),此时RP应开始工作。这是RP工作的总开关。
rx_valid_esc输入数据有效。高电平表示rx_data_esc上的数据在当前rx_clk_esc上升沿有效。RP必须在此刻锁存数据。
rx_data_esc[7:0]输入接收数据字节。在低功耗数据接收模式(rx_lpdt_esc有效)下,面板发送的数据字节,[0]位为最先接收的位。
rx_lpdt_esc输入低功耗数据接收模式指示。高电平表示当前正在通过LP模式接收数据(即非高速模式)。
rx_trigger_esc[3:0]输入触发命令接收。4位信号,指示接收到一个4位的转义触发命令。同一时间只有一位有效。
stop_state_dl1输入停止状态指示。异步信号,表示D-PHY通道已进入LP11停止状态。

数据接收的时钟rx_clk_esc由面板在发送数据时一并产生(内嵌时钟)。RP模块在direction=1rx_valid_esc=1的每个rx_clk_esc上升沿采样数据。当rx_lpdt_esc有效时,表明数据是在低功耗模式下传输的。

3.2 消息解码与错误处理逻辑

RP接收到的消息主要分为两类:触发消息(Trigger)读数据包(Read Packet)。RP硬件会进行初步解码,并将结果提交给寄存器供软件读取。

1. 触发消息处理:触发消息是简单的4位编码。RP会几乎直接将其映射到寄存器。reg_triggerreg_req会被置位,同时reg_rd_data<3:0>在一个时钟周期内保持触发值。然而,RP硬件会进行关键的解码以识别特殊触发:

  • TE触发:如果触发值对应TE响应(例如,根据触发映射表,trigger_val=1b0010可能对应TE),RP会通过专用信号csm_te_received通知命令流管理器(CSM),用于自动TE同步控制。
  • ACK触发:如果触发值对应“无错误确认”(如trigger_val=1b0100),RP会置位reg_ack信号。
  • 其他未定义的触发值,RP不做处理,直接传递给寄存器,由应用软件决定如何响应。

2. 读数据包处理:对于读数据包(短包或长包),RP的处理流程更为复杂,包含头部解析、ECC校验和负载提取:

  • 头部解析与ECC:RP首先接收并缓存4字节的包头(Header)。如果使能了ECC功能,会立即进行单比特错误纠正或多比特错误检测。这是第一道错误过滤关卡
  • 非法包处理:如果包头中的操作码(Opcode)不在DSI协议定义的合法显示命令集内,RP会认为这是一个不可解码的错误。它会丢弃整个包以及后续在同一BTA周期内收到的所有字节,直到下一次方向改变(BTA)。同时,它会设置err_undecodableuncorrectable_err错误标志。即使ECC校正失败,只要包头操作码可识别,RP仍会尝试继续处理。
  • 短读包:对于DCS或通用短读响应,RP将2字节的有效负载数据通过reg_rd_data<15:0>传递给寄存器,并置位reg_reqreg_startreg_endreg_read等信号。数据长度信息(Size)会从包头解码出来并通过reg_size端口传递。
  • 长读包:RP进入“LONG”状态。它首先通过reg_size报告总数据长度,然后开始将接收到的每个数据字节通过reg_data存入返回包FIFO,并同时计算校验和(Checksum)。这里有一个关键限制:RP FIFO的深度是有限的(例如文档提到最大支持16字节)。如果长包数据超过FIFO深度,err_oversize错误会被置位,超出的数据仅用于校验和计算,不会被存储。
  • 包结束(EoT)处理:EoT包(包头0x08)本身不会被传递给控制块。如果RP在预期收到EoT包时(例如,在“带错误确认”之后)没有检测到EoT,会设置err_missing_eot错误。如果收到了多余的EoT包或在非预期位置收到,会设置err_eot_with_err

3.3 返回路径FIFO与软件读取策略

RP接收到的数据(主要是读包负载)会先存入一个位于寄存器模块的返回包FIFO中。软件通过多次读取一个特定的寄存器来访问这个FIFO。这里有一个至关重要的设计假设和潜在陷阱

硬件设计假设,一旦软件发起一个读请求,它会在发起下一个读请求之前,将当前读操作预期的所有返回数据从RP FIFO中读完。基于这个假设,每次开始一个新的读操作时,硬件会自动清空RP FIFO中所有未读的数据

这意味着,如果你发起了一个读命令,但由于某种原因(如中断延迟、任务调度)没有及时读取FIFO,然后又发起了另一个读命令,那么前一个读命令的返回数据将永久丢失。这会导致数据错乱和难以调试的软件问题。

避坑指南:RP FIFO的读取纪律

  1. 同步读取:最好的实践是,在触发一个读命令后,采用轮询或中断的方式等待read_completed,一旦完成,立即进入一个循环,根据reg_size指示的长度或直到FIFO空标志,读取所有数据。
  2. 超时保护:在读取循环中加入超时机制。如果读取的字节数长时间达不到预期长度,可能发生了数据包错误或丢失,应跳出循环并检查错误状态寄存器。
  3. 错误优先:在读取数据之前,先检查read_completed_with_err和相关错误位。如果有错误,数据可能无效,应先处理错误。
  4. 虚拟通道(VC)注意:在多从设备(Multi-Peripheral)配置中,RP会记录接收数据包的虚拟通道号(reg_vc)。软件在读取数据时,需根据VC号将数据分发到正确的逻辑处理单元。

4. 撕裂效应(TE)控制:帧同步的艺术与实现细节

撕裂效应是显示技术中的一个经典问题:当显示控制器(GPU/显示驱动)向面板帧缓冲写入新帧数据的速度,与面板从帧缓冲读取数据并扫描显示的速度不一致时,屏幕上会同时出现两帧不同的内容,产生一条明显的撕裂线。在DSI命令模式下,由于主机通过命令“离散地”更新面板内部的帧缓冲,这个问题尤为突出。DSI协议提供了两种主要的TE控制机制:轮询(Polling)和自动(Automatic)模式,来确保主机只在面板的垂直消隐期(V-Blanking)或指定行进行写操作,从而实现帧同步。

4.1 轮询模式:主动询问的同步策略

轮询模式的思想很简单:主机主动、周期性地询问面板:“你现在扫描到哪一行了?”然后根据回答决定是否可以安全地更新帧缓冲。

核心命令:get_scanline(DCS 命令 0x45)这是轮询模式的基石。主机通过发送这个短读命令,面板会返回两个字节,表示当前正在扫描显示的行号(Scanline)。行号从0开始,0通常代表垂直同步(VSYNC)的开始行。

操作流程:

  1. 启用命令模式与BTA:确保DSI控制器已配置为命令模式,并且BTA功能使能。
  2. 发送读命令:主机发送get_scanline命令。由于是读操作,DSI控制器会自动在命令后附加BTA请求。
  3. 等待与读取:等待read_completed,然后从RP FIFO读取返回的扫描线值。
  4. 决策:软件将读取的扫描线值与一个安全阈值进行比较。通常,这个阈值设置为接近一帧总行数(Vtotal)的末尾,例如Vtotal - 20。如果当前扫描线已超过此阈值,说明面板即将或正在开始垂直消隐期,主机可以安全地开始发送下一帧的更新命令。
  5. 循环:如果未达到安全区域,主机等待一小段时间(例如,计算一行扫描所需的时间)后,重复步骤2-4。

轮询模式的优缺点:

  • 优点:实现简单,不依赖面板特定的TE硬件信号支持。所有符合DCS标准的命令模式面板都应支持get_scanline
  • 缺点通信开销大,延迟高,功耗也相对较高。每次查询都需要一次完整的读命令+BTA+响应周期,在高速刷新率下可能占用可观的总线带宽和CPU时间。此外,从“得知安全”到“开始发送数据”之间存在处理延迟,可能错过短暂的消隐期窗口。

实操心得:轮询间隔与功耗权衡轮询过于频繁会增加功耗和总线负载,轮询过慢则可能错过更新窗口导致卡顿。一个实用的策略是自适应轮询:在需要快速更新的动画期间,使用较短的轮询间隔(例如每1-2ms);在显示静态内容时,大幅降低轮询频率甚至暂停轮询。同时,可以根据历史扫描线数据预测下一个安全窗口的到来时间,实现“准主动”同步。

4.2 自动模式:事件驱动的同步策略

自动模式是一种更高效、更低延迟的同步方式。它依赖于面板硬件产生一个特定的TE触发信号(通常是一个脉冲),并通过DSI的触发消息机制发送给主机。主机在收到TE信号后,便知道面板已进入消隐期,可以安全更新。

配置与启用:

  1. 面板配置:主机首先需要通过DCS命令set_tear_on(0x35) 或set_tear_scanline(0x44) 来启用面板的TE输出功能set_tear_on开启TE信号,可选择模式0(仅垂直消隐期有效)或模式1(垂直和水平消隐期均有效)。set_tear_scanline更精确,可以指定在扫描到特定行N时产生TE脉冲。
  2. 控制器配置:在DSI主机控制器端,需要使能TE检测和自动BTA机制。通常涉及设置te_hw_polling_en=0(禁用轮询)、使能BTA请求位,并可能配置TE超时计数器。
  3. 发起同步:配置完成后,主机发起一次BTA请求,但不伴随任何命令。这相当于将总线控制权主动交给面板,并说:“等你准备好更新时,告诉我。”然后主机进入等待状态。

自动模式的工作流程(以文档描述为例):这是一个两步握手过程,旨在处理边界情况:

  1. 第一次BTA与等待:DSI控制器发送第一个BTA,然后等待面板响应。
    • 理想情况:面板在消隐期开始时,会先发送一个TE触发消息,然后紧接着发送一个BTA将总线归还。主机收到te_received信号,同步成功。
    • 情况A:面板只发回了BTA,没有TE。这可能是因为面板的TE生成未被启用,或不支持TE。控制器会检测到这种情况,并设置reg_err_no_te错误标志。
    • 情况B:面板无任何响应,超时。控制器设置reg_err_te_miss,但会继续等待(这是文档中强调的一点)。
  2. 第二次BTA与最终等待:如果第一次BTA后只收到了BTA(情况A),控制器会自动发起第二次BTA,然后再次等待TE+BTA。这次等待的时间窗口由可编程的TE超时计数器控制。如果超时前收到TE,则同步成功;如果再次超时或收到无TE的BTA,则最终报告错误。

TE超时计数器的计算:超时时间需要根据tx_byte_clk(或tx_esc_clk,具体取决于实现)的周期来编程。文档中的表格给出了计算公式:超时周期数 = 乘数 × te_timeout<9:0>其中乘数由te_timeout(11:10)两位决定:00=256倍,01=512倍,10=1024倍,11=2048倍。 例如,如果tx_esc_clk = 10MHz(周期100ns),设置te_timeout(11:10)=00te_timeout<9:0>=1000,则超时时间为256 * 1000 * 100ns = 25.6ms。这个值通常应略大于一帧的时间(如60Hz帧率为16.67ms),以确保能覆盖整个帧周期。

4.3 模式选择与实战建议

如何选择轮询还是自动模式?

  • 首选自动模式:只要你的显示面板硬件支持TE触发信号输出,应优先使用自动模式。它能实现最低的延迟和最高的效率,CPU干预最少,功耗也更优。
  • 降级使用轮询模式:对于不支持TE触发的低成本面板,轮询模式是唯一选择。或者在调试阶段,自动模式出现问题时,轮询模式可以作为诊断和备用方案。

自动模式下的调试技巧:

  1. 测量TE信号:如果面板有专用的TE引脚(在MIPI DBI/DPI接口中常见),用示波器测量该引脚,确认面板确实在消隐期产生了脉冲。这是排除面板端问题的第一步。
  2. 检查触发映射:确认DSI控制器中配置的触发值(trigger_val)与面板实际发送的TE触发入口代码(Trigger Entry Code)匹配。参考文档中的触发映射表,例如TE响应可能对应代码01011101,映射到trigger_val=1b0010
  3. 监控状态位:在代码中严密监控te_receivedBTA_completedBTA_finished以及错误状态位reg_err_no_tereg_err_te_miss。通过打印或日志分析状态流转,可以清晰定位问题发生在BTA请求发送、TE接收还是总线归还阶段。
  4. 调整超时时间:如果出现reg_err_te_miss,首先检查超时时间是否设置得太短。确保超时时间大于一帧周期,并留出足够余量(例如,帧周期的1.5倍)。
  5. 检查BTA使能:确保在发送启用TE的DCS命令(set_tear_on)后,确实跟随了一个独立的BTA请求将总线控制权交给面板。这是激活面板TE发送的必要条件。

一个常见的坑:TE使能命令的生效时机无论是set_tear_on还是set_tear_scanline,文档中明确提到:该命令在下一帧才开始生效。这意味着,如果你在当前帧发送了启用命令,然后立即开始等待TE信号,你很可能等不到,因为面板在当前帧仍然不会发送TE。正确的做法是:��送启用命令 -> 等待至少一帧时间(可以通过get_scanline估算或简单延时)-> 再开始自动模式的TE等待流程。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/19 1:09:46

时间维度切换:本周/本月/今年 Segmented Control

前言 在“海风日记“的回顾页中&#xff0c;时间维度切换按钮允许用户在本周、本月和今年三个维度之间切换&#xff0c;查看不同时间范围内的写作统计。 本文将从源码出发&#xff0c;深入讲解 Segmented Control 的实现。 一、Segmented Control 实现 1.1 源码 State sele…

作者头像 李华
网站建设 2026/7/19 1:09:36

传统行业职场人想转 AI,第一步不是辞职,而是把现有经验 AI 化

引言&#xff1a;AI 转型的普遍误区 —— 裸辞跨界&#xff0c;多数人折戟而归2026 年国内人工智能产业规模突破万亿&#xff0c;全年行业增速维持 30% 以上&#xff0c;制造、金融、零售、农业等传统行业 AI 渗透率突破 80%&#xff0c;AI 已经从互联网专属技术&#xff0c;变…

作者头像 李华
网站建设 2026/7/19 1:05:35

嵌入式音频通信:McBSP多通道选择与SIDETONE硬件加速详解

1. 项目概述&#xff1a;从TDM到McBSP的通道管理艺术在嵌入式音频和通信系统的开发中&#xff0c;我们常常面临一个核心矛盾&#xff1a;如何在有限的物理引脚和带宽资源下&#xff0c;高效、灵活地传输多路独立的音频或数据流&#xff1f;无论是数字音频接口&#xff08;如I2S…

作者头像 李华
网站建设 2026/7/19 1:04:18

嵌入式GPMC配置实战:地址解码、WAIT引脚与总线时序优化

1. 项目概述&#xff1a;为什么GPMC的配置如此关键&#xff1f;在嵌入式系统开发&#xff0c;尤其是基于TI Sitara系列处理器&#xff08;如AM62L&#xff09;的设计中&#xff0c;外部存储器的连接与访问性能往往是决定系统稳定性和响应速度的关键瓶颈。处理器内部虽有高速缓存…

作者头像 李华
网站建设 2026/7/19 0:49:00

Kimi LeetCode 3621. 位计数深度为 K 的整数数目 I JavaScript实现

LeetCode 3621. 位计数深度为 K 的整数数目 I JavaScript 实现javascript /*** param {number} n* param {number} k* return {number}*/ var popcountDepth function(n, k) {// k0&#xff1a;只有 1 的深度为 0if (k 0) {return n > 1 ? 1 : 0;}// 计算一个整数的 popc…

作者头像 李华