This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] AM2432:AM243x TSN PTP PPS 信号(周期时间)行为

Guru**** 2796955 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1598994/am2432-am243x-tsn-ptp-pps-signal-cycle-time-behavior

器件型号: AM2432

您好、

我当时尝试更改 PRU ICSSG AM243x EVM 的 R5F 内核 0 上的 PPS 信号频率(周期时间)。

我将 ICSSG_IEP_DFL_CYCLE_TIME_NSECS 的值从 1000000 修改为 25000。 PPS 信号频率按照预期设置为 40kHz。 但是、PTP 跟随者不再与主时钟同步。

问题:

  1. 为了使 PTP 跟随者与主时钟同步、还需要修改哪些内容?
  2. 为什么更改 PPS 信号频率会影响 PTP 主控与跟随器之间的时钟同步?

谢谢你。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Matt:

    如 上一主题中所述:

    https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1575233/am6442-am64x-or-am243x-tsn-application-questions/6069565?tisearch=e2e-sitesearch&keymatch=PPS%252520AM243x#

    [引述 userid=“378769" url="“ url="~“~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1598994/am2432-am243x-tsn-ptp-pps-signal-cycle-time-behavior
    1. 为什么更改 PPS 信号频率会影响 PTP 主控与跟随器之间的时钟同步?

    [/报价]

    我不建议修改 ICSSG_IEP_DFL_CYCLE_TIME_NSECS、因为它会直接影响我们的 64 位时间戳计算。

    我们使用 IEP0 计时器 32 位影子模式。 Icssg_convertts 函数通过计算经过的 1ms 周期数并乘以 cycleTimeN (1,000,000 ns)、然后添加子周期偏移来重构完整的 64 位纳秒时间戳。  如果在硬件 IEP 仍以 1ms 的间隔翻转的情况下修改 cycleTimeN、则乘法将不正确。 这会导致所有 64 位时间戳的计算错误、导致 PTP 时钟偏移和漂移测量错误、最终导致主设备与跟随器之间的同步中断。

    BR
    Jc.

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 JC:

    感谢您的解释。

    我有两个后续问题:

    1. 我知道您不建议直接更改周期时间。 在这种情况下、您建议使用什么正确方法来实现 PTP 主时钟和跟随者以固定的速率(比如每 25 微秒执行一次)同步执行命令?

    我认为这是一个典型的 TSN PTP 应用。 TI 必须提供一种标准方法来建议客户如何实现这一点。

    2.您能否进一步阐述一下您所说的“如果您修改 cycleTimeNs、而硬件 IEP 仍然以 1ms 的间隔滚动...“?

    您的意思是 Icssg_convertts() 以硬编码的固定速率 (1ms ) 调用、还是根据其他 PTP 端点的请求 (1ms ) 调用? 在 R5F 内核 0 上无法更改该速率。

    或者“硬件 IEP 仍然以 1ms 的间隔滚动“中的“IEP 硬件“意味着什么?

    因为我在 Icssg_convertts() 中发现了这个 问题、cycleTimeNs 是由 Icssg_Cfg 结构传递的参数。 在 修改 ICSSG_IEP_DFL_CYCLE_TIME_NSECS 时、应保留此值。

    uint64_t Icssg_convertTs(EnetPer_Handle hPer,
                             uint64_t ts)
    {
        /* ... */
        uint32_t cycleTimeNs = hIcssg->cycleTimeNs;
        /* ... */
        
        if(hIcssg->clockTypeFw == ICSSG_TIMESYNC_CLKTYPE_SYSTEM_TIME)
        {
            /* ... */
        }
        else
        {
            /* ... */
            ns = ns * cycleTimeNs + iepCntLo;
        }
        
        return ns;
    }

    非常感谢您的帮助!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Matt:

    1.  我知道您不建议直接更改周期时间。 在这种情况下、您建议采用什么正确方法来实现 PTP 主控和跟随者以固定的速率(例如每 25 微秒执行一次)同步(基于主控时钟)执行命令?

    您能否说明一下“execute commands in synce“是什么意思?

    [引述 userid=“378769" url="“ url="~“~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1598994/am2432-am243x-tsn-ptp-pps-signal-cycle-time-behavior/6162995

    您能否进一步阐述一下您说的“如果您修改 cycleTimeN、而硬件 IEP 仍然以 1ms 的间隔滚动...“?

    您的意思是 Icssg_convertts() 以硬编码的固定速率 (1ms ) 调用、还是根据其他 PTP 端点的请求 (1ms ) 调用? 在 R5F 内核 0 上无法更改该速率。

    或者“硬件 IEP 仍然以 1ms 的间隔滚动“中的“IEP 硬件“意味着什么?

    [/报价]

    为了澄清, Icssg_convertts() 是一个时间戳转换函数 — 它将硬件时间戳格式转换为软件可以解释的 64 位时间戳。 这与 PTP 同步间隔无关。 ICSSG IEP 计数器以相对时间戳模式运行、其中 IEP 计数器以配置的间隔(默认为 1ms)回滚。 该软件需要一个绝对 64 位时间戳来进行 PTP 操作。 Icssg_convertts() 执行此相对绝对转换。 cycleTimeN 参数告诉转换函数硬件翻转间隔是什么、以便可以正确计算绝对时间戳。 如果此参数与实际硬件 IEP 翻转配置不匹配、则转换的时间戳将不正确。

    这也是我们使用 ICSSG setClockTime API 以相对格式设置硬件时间戳的确切原因 — 注意:PRU 固件对数据包时间戳使用相同的逻辑。 如果您修改 IEP 寄存器中的周期时间、则数据包时间戳在 PRU 固件中将变得不可靠、这就是跟随者和主器件 不同步的原因(如上所述)

    BR
    Jc.

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 JC:

    对于您的问题“您能否澄清一下“execute commands in synce“是什么意思?“、
    例如、TSN 网络上有多个器件。 我们希望这些支持 TSN 的器件同时生成脉冲(在 50ns 内)。 该脉冲会触发硬件加载 DAC 值。 每个器件每 25 微秒生成一次此脉冲。
    在发生第一个脉冲后、每个器件会将其下一个 DAC 值加载到硬件中(例如通过 SPI)。 第一轮工作到此结束。 然后发生第二个脉冲、开始第二轮。 将重复相同的过程。

    因此、此处的“执行命令“是指生成周期性脉冲并加载 DAC 值;“同步“是指所有器件生成的周期性脉冲需要同时发生(在 50ns 内)。 因此、我们想利用 TSN SYNC_out0 将其用作 25 微秒周期脉冲。
    希望这澄清了我的第一个问题。

    对于#2、我想我仍然感到困惑。
    我理解不同翻转间隔的想法不起作用。 但是、您能否说明一下:在哪些组件上配置了翻转间隔?
    我知道有一个是位于 PRU 上的 IEP0 CMP0 寄存器(我更改了 cycTimeN)。 您提到“如果此参数与实际硬件 IEP 翻转配置不匹配、则转换的时间戳将不正确。“ 我认为 IEP0 CMP0 是 IEP 翻转配置。 还是有另一个翻转配置?


    另外、在 Icssg_convertts() 中、该语句是否从以太网固件读取硬件时间戳? 此以太网时间戳是否也每 1ms 翻转一次、且不可配置?

    swHi = Icssg_rd32(hIcssg, sharedRam + TIMESYNC_FW_WC_COUNT_HI_SW_OFFSET_OFFSET);


    感谢您的帮助!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Matt:  

    [引述 userid=“378769" url="“ url="~“~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1598994/am2432-am243x-tsn-ptp-pps-signal-cycle-time-behavior/6166456
    因此、此处的“执行命令“是指生成周期性脉冲并加载 DAC 值;“同步“是指所有器件生成的周期性脉冲需要同时发生(在 50ns 内)。 因此、我们想利用 TSN SYNC_out0 将其用作 25 微秒周期脉冲。
    希望这澄清了我的第一个问题。

    谢谢这澄清了我的问题。  

    [引述 userid=“378769" url="“ url="~“~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1598994/am2432-am243x-tsn-ptp-pps-signal-cycle-time-behavior/6166456

    我理解不同翻转间隔的想法不起作用。 但是、您能否说明一下:在哪些组件上配置了翻转间隔?
    我知道有一个是位于 PRU 上的 IEP0 CMP0 寄存器(我更改了 cycTimeN)。 您提到“如果此参数与实际硬件 IEP 翻转配置不匹配、则转换的时间戳将不正确。“ 我认为 IEP0 CMP0 是 IEP 翻转配置。 还是有另一个翻转配置?


    另外、在 Icssg_convertts() 中、该语句是否从以太网固件读取硬件时间戳? 此以太网时间戳是否也每 1ms 翻转一次、且不可配置?

    [/报价]

    我将在这里帮助您提供更多详细信息:

    影子模式下的 IEP 计时器使用两级翻转机制来保持 64 位纳秒时间戳。

    级别 1: IEP 低寄存器 (COUNT_REG0)
    LOW 寄存器是一个计数纳秒的 32 位计数器。 当它与 CMP0 比较值(配置为 1ms 周期)匹配时、硬件会自动将其复位为零并递增高位寄存器 (COUNT_REG1)。 这完全由硬件管理。

    2 级: IEP 高寄存器 (COUNT_REG1)
    高位寄存器会对 CMP0 复位事件的数量进行计数(即,毫秒)。 根据 TRM、这是一个 24 位计数器、在 0xFF_FFFF 停止且不会绕回。 软件必须在达到该阈值之前将其清除。 固件仅使用 23 位(掩码 0x007FFFFF)来在硬件饱和前检测溢出。 当位 23 溢出时、固件会递增存储在 TIMESYNC_FW_WC_HI_ROLLB_COUNT_OFFSET 的回滚计数器、并清除 COUNT_REG1。  

    共享存储器偏移
    Timesync_FW_WC_HI_ROLLOV_COUNT_OFFSET:存储 COUNT_REG1 翻转计数、每次 23 位溢出发生时递增。
    Timesync_FW_WC_COUNT_HI_SW_OFFSET_OFFSET:软件偏移调整、仅在设置的时钟操作期间适用。
    Timesync_CYCLE_EXTN_TIME:随时间累积的周期扩展调整。


    读取算法
    为了确保在没有竞态条件的情况下一致地读取时间戳、代码使用双读验证模式。 它读取 IEP 高电平、翻转计数和 IEP 低电平、然后再次读取 IEP 高电平和翻转计数。 如果两个读数都匹配、则时间戳有效;否则、重复该过程。 这可确保在读取高低部分之间不会发生翻转。

    另外、在 Icssg_convertts() 中、该语句是否从以太网固件读取硬件时间戳? 此以太网时间戳是否也每 1ms 翻转一次、且不可配置?

    否、TIMESYNC_FW_WC_COUNT_HI_SW_OFFSET_OFFSET 不会翻转。 这不是连续递增的计数器、而是在设置时钟运行期间捕获的 IEP COUNT_REG1 值的保存副本。 在设定的时钟操作期间、在固件将 IEP COUNT_REG1 复位为零之前、会将当前 COUNT_REG1 值保存到 TIMESYNC_FW_COUNT_HI_SW_OFFSET_OFFSET。 这会保留累积的时间偏移、以便在复位后保持时间戳连续性。 然后在时间戳计算期间将软件偏移添加到 COUNT_REG1 读数中、以在设置/获取时钟操作中保持准确的计时。

    BR
    Jc.

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 JC:

    感谢您解释更多详细信息。 我们知道更改 PPS 是不可行的。

    在这种情况下、您能否帮助回答我之前的问题:

    1. 我知道您不建议直接更改周期时间。 在这种情况下、您建议使用什么正确方法来实现 PTP 主时钟和跟随者以固定的速率(比如每 25 微秒执行一次)同步执行命令?

    我认为这是一个典型的 TSN PTP 应用。 TI 必须提供一种标准方法来建议客户如何实现这一点。

    谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    1.  我知道您不建议直接更改周期时间。 在这种情况下、您建议采用什么正确方法来实现 PTP 主控和跟随者以固定的速率(例如每 25 微秒执行一次)同步(基于主控时钟)执行命令?

    新年快乐! 抱歉、由于回复延迟、上周我在度假、本周我需要及时收到电子邮件。  

    为了以固定速率(例如每 25 微秒)在 PTP 主设备和跟随器之间实现同步命令执行、建议的方法是利用 IEP0 比较事件机制。

    建议实施方案:

    • 配置 IEP0 CMP 事件 — 使用可用的比较寄存器(例如 CMP8)在每个 25µs 生成事件、映射到主机中断。
    • 将主机中断映射到应用程序任务–主机中断会触发应用程序任务以进行同步执行。

    应用程序处理:

    • 中断时清除 IEP0 CMP8 状态
    • 使用下一个未来时间戳(当前+ 25µs、然后是+ 50µs 等)对 CMP8 进行重新编程
    • 继续此模式、直到到达 1ms 边界
    • 处理 IEP0 翻转 — 由于 IEP0 CMP0 每 1ms(周期时间)回滚一次、因此在跨越 1ms 边界时、将 IEP0 CMP8 寄存器重新编程回适当的偏移(相对于 0)。 CMP8 未使用。  

    此方法利用 PTP 同步 IEP 计时器在所有节点上进行精确的时钟对齐执行、而无需修改底层周期时间、从而在保持标准 gPTP 运行的同时确保确定行为。

    BR
    Jc.

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    新年快乐、JC!  感谢您的建议。 这与我想尝试的内容一致。 我会尝试一下、让您知道。

    谢谢你。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 JC:

    我能够使用 CMP8 获得大致正确的中断次数。 现在、我想在 CMP8 比较事件发生时同时驱动数字输出信号(如 SYNC_OUT0)。 您能介绍一下如何做到这一点吗?

    感谢您的帮助!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Matt:

    通过硬件将 CMP8 直接驱动为数字输出信号具有挑战性。

    这些替代方案中的任何一个都适合您吗?

    -主机驱动的方法:将信号路由到主机应用程序,然后触发 GPIO — 此处的应用程序延迟是一个问题。

    -低延迟方法:在 AM243x 上的另一个 ICSSG 实例上运行 GPIO 切换应用程序。


    请告诉我哪种选项适合您的要求、尤其是在需要考虑延迟的情况下。

    BR
    Jc.

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 JC:

    我们应用的重要要求是 TSN 网络上的所有这些节点都应该完全同时生成数字输出信号。 如果延迟不多、则允许延迟。

    有关您提到的两种方法的问题:

    主机驱动的方法:您是指软件在中断服务例程中控制 GPIO 吗? 如果没有、请说明。

    低延迟方法:如果在另一个 ICSSG 实例上完成 GPIO、这些数字输出信号是否同时触发? 这是如何工作的?

    请提供建议。

    谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    主机驱动的方法:您是指软件在中断服务例程中控制 GPIO 吗? 如果没有、请解释。

    正确、因此延迟取决于运行的 RTOS/HLOS。 因此、对于使用 800MHz R5F 的最高优先级 IRQ、这将大约为 1us、可能会通过大量定制优化低至 500ns。 由于互连延迟、GPIO 切换本身具有 100ns 至 200ns 的抖动

    [引述 userid=“378769" url="“ url="~“~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1598994/am2432-am243x-tsn-ptp-pps-signal-cycle-time-behavior/6203882

    低延迟方法:如果在另一个 ICSSG 实例上完成 GPIO、这些数字输出信号是否同时触发? 这是如何工作的?

    请提供建议。

    [/报价]

    这是通过第二个 ICSSG PRU 轮询 CMP 状态(可以路由到 ICSSG INTC)和切换 GPO(低延迟 3ns 抖动)来实现的、因此在此处可能小于 100ns。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Pratheesh、

    感谢您的回答。

    对于低延迟方法、“第二个 ICSSG PRU CMP 状态轮询“意味着修改 PRU 固件、而不是 R5F 代码、正确吗?

    您能详细解释一下吗?

    谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Matt:  

    抱歉、您的线程从雷达中丢失了。

    正确。 轮询 IEP CMP 状态需要在 PRU_ICSSGx 上运行自定义固件。 默认情况下、MCU+ SDK 示例在 ICSSG1 上运行 PRU 以太网、从而使 ICSSG0 可自由用于定制用例。

    这样做的一种系统性方法是:

    使用 ICSSG0 轮询 ICSSG1 IEP0 CMP 状态寄存器

    • 监控器 CMP8 状态:
    • 读取 IEP_CMP_STATUS_REG 并检查位 8 (CMP_STATUS[8])
    • 如果设置、则已发生 CMP8 事件(计数器与 IEP_CMP8_REG0/REG1 值匹配)
    • 通过将 0x100(位 8)写入 IEP_CMP_STATUS_REG 来清除状态
    • 切换 GPIO

    BR
    Jc.

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 JC:

    我刚有机会使用 TEST_LED2 GPIO 实施主机驱动方法。 GPIO 在 CMP8 比较事件触发的 25 微秒中断内切换。

    结果有点令人困惑:
    我可以在示波器上看到 GPIO 信号每 25 微秒切换一次。 但是、有一个简短的 1 毫秒包络有时会覆盖 25 微秒波形。 CMP8 事件几乎每 25 微秒发生一次、大部分时间都是如此。 但有时、它每 1 毫秒发生一次。 PTP 主设备和从设备之间的抖动太大、在这种情况下没有意义。

    在相同的代码逻辑下、如果我将中断间隔从 25 微秒更改为 50 微秒、包络似乎会消失。 PTP 主设备和从设备之间的抖动范围约为 10 微秒。

    下面是我的测试代码框架:

    uintptr_t iep0Regs;
    uint32_t cmpValue = 50000;
    EnetPer_Handle hPer = Enet_getPerHandle(gEnetAppCfg.perCtxt[0].hEnet);
    Icssg_Handle hIcssg = (Icssg_Handle)hPer;
    uintptr_t iep0Regs = (uintptr_t)hIcssg->hTimeSync->virtAddr;
    bool gpioSetHigh = false;
    
    SetupIEP0Compare(hIcssg, cmpValue);
    SetupInterrupts(hIcssg->pruss->hPruss);


    ISR:
    void my_handler()
    {
        if(HWREG(iep0Regs + CSL_ICSS_PR1_IEP0_SLV_CMP_STATUS_REG) & (1 << 8))   /* CMP8 */
        {
            HWREG(iep0Regs + CSL_ICSS_PR1_IEP0_SLV_CMP_STATUS_REG) &= ~(1 << 8);
    
            if(cmpValue != 1000000)     // IEP counter 1ms
            {
                cmpValue += 50000;
            }
            else
            {
                cmpValue = 50000;
            }
            SetupIEP0Compare(hIcssg, cmpValue);
            
            if(gpioSetHigh)
            {
                GPIO_pinWriteHigh(gpioBaseAddr, pinNum);
            }
            else
            {
                GPIO_pinWriteLow(gpioBaseAddr, pinNum);
            }
            
            gpioSetHigh = !gpioSetHigh;
            my_count++;        
        
            PRUICSS_clearEvent(gPruIcssg1Handle, 7);           /* INTC event signal 7: pr1_iep_tim_cap_cmp_pend */                        
        }       
    }
    


    两个功能:

    void SetupIEP0Compare(Icssg_Handle hIcssg, uint32_t sliceTimeNs)
    {
        uintptr_t baseAddr = (uintptr_t)hIcssg->enetPer.virtAddr;
    
        /* Set IEP0 CMP8 register */
        Icssg_wr32(hIcssg, baseAddr + CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE + CSL_ICSS_G_PR1_IEP0_SLV_CMP8_REG0, (sliceTimeNs - 4));
        Icssg_wr32(hIcssg, baseAddr + CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE + CSL_ICSS_G_PR1_IEP0_SLV_CMP8_REG1, (sliceTimeNs - 4));
    }
    
    void SetupInterrupts(PRUICSS_Handle hPruss)
    {
        PRUICSS_registerIrqHandler(hPruss,
                                   7,                      /* INTC event signal 7: pr1_iep_tim_cap_cmp_pend */
                                   CSLR_R5FSS0_CORE0_INTR_PRU_ICSSG1_PR1_HOST_INTR_PEND_5,      /* Host interrupt 7 - 2 */
                                   1,                      /*  eventNum     */
                                   1,                      /*  wait_enable  */
                                   my_handler);    
        HwiP_disableInt(CSLR_R5FSS0_CORE0_INTR_PRU_ICSSG1_PR1_HOST_INTR_PEND_5);
        uint32_t status = PRUICSS_intcInit(hPruss, &icss1_intc_initdata);
        
        HwiP_enableInt(CSLR_R5FSS0_CORE0_INTR_PRU_ICSSG1_PR1_HOST_INTR_PEND_5);
    }
    


    问题:
    1.实施是否正确? 如果是、什么可能导致此 1 微秒包络以及如何消除它?
      注意:cmpValue 是用于控制 INT 间隔的变量。 当 cmpValue 为 50000(50 微秒)时、1 毫秒的包络似乎消失了。  

      (鉴于 50 微秒间隔 INT 似乎没有问题、我怀疑中断不足以快速更新 CMP8 寄存器、有时还会在下一个 CMP8 寄存器之前更新。 然而、我测得 ISR 中花费的时间约为 1.2 微秒。 另外、这也不能解释为什么包络大约为 1 毫秒。 我想知道您是否对此有任何见解...)


    2.如果第一个问题的答案是“否“,那么错误是什么?


    感谢您的帮助!