本帖最后由 dffzh 于 2025-5-13 13:11 编辑
#申请原创#
@21小跑堂
产品用于工业自动化领域,所以对总线响应时间的实时性要求比较高,为了调优这个总线响应时间,在基于MCU和ADC芯片的SPI数据读取以及MCU和从站芯片的SPI通信交互这块,可真的是煞费苦心,听我慢慢道来!
1、使用不同方案并测试MCU和ADC芯片的SPI通信时间
(1)使用硬件SPI + STM32 HAL库标准发送和接收函数 10M速率,采集4个通道,使用IO口电平翻转的方法进行测试; 耗时200us左右
标准库的发送和接收函数耗时: 发送:HAL_SPI_Transmit // 3.5us 接收:HAL_SPI_Receive // 7.35us (2)使用软件模拟SPI 采集4个通道,耗时140us左右
采集一次,ADC驱动函数需发送2个字节+接收6个字节:
优化ADC采集函数:
采集4个通道,大部分最短耗时106us:
2、MCU和从站芯片的SPI通信时间测试
(1)使用标准SPI + HAL库标准发送和接收函数 10M速率,使用IO口电平翻转的方法进行测试; 运行一次协议栈的中断服务程序,耗时1.28ms左右;
所以此时如果在上位机上设置扫描周期1ms,即PDI中断周期是1ms,模块是无法进行连接到主站的。 (2)使用标准SPI+自编的发送和接收函数 运行一次协议栈的PDI中断服务程序PDI_Isr,耗时 442us左右;
用PLC主机实测,扫描周期配置为500us时,模块无法正常运行;屏蔽PDI函数里的部分与通信相关的代码,中断执行一次400us左右,然后扫描周期配置为500us时,模块可以正常运行。修改机制后测试: 之前的PDI函数是放在PDI外部中断里执行的,现在设计为在中断里只设置标志位,而将该函数放到main里运行;用主机实测,扫描周期配置为500us时,模块可以正常运行。然后简单进行了这种情况的滤波滞后时间测试,结果如下表所示; 扫描周期 | 滤波滞后时间 | 500us | 52ms | 600us | 29ms | 700us | 20ms | 800us | 16ms | 900us | 15ms | 1000us | 13ms | 从测试可以看出,扫描周期配置为500us时,滞后时间太长,无法达到要求;即修改的机制虽然可以保证中断执行正常,但因PDI_Isr接口执行时间不变,滤波滞后时间较长。扫描周期>=1000us基本可以符合需求。 (3)使用软件模拟SPI 运行一次协议栈的PDI中断服务程序,耗时582us左右;
上位机上设置扫描周期>=1ms,模块可以连接到主站。以下是三种方案的运行PDI函数的时间对比: 方案 | 运行时间 | 硬件SPI + HAL库函数 | 1.28ms | 硬件SPI + 自编函数 | 442us | 软件SPI | 582us |
3、协议栈优化前后的时间测试 对运行在main主程序里的协议栈接口MainLoop的运行频次进行了优化,其优化方案为:如果设置了滤波使能,则每运行50次ADC采集及数据处理接口后再运行1次协议栈【按时间计算的话,大概是每隔5ms多运行1次】; 对比测试了优化前后的滞后时间,分别是33ms和14ms,如下图所示:
4、滤波设置后的滞后时间测试 对程序设计进行了以下优化: 1、 减少main主程序里的协议栈运行频次;即提高ADC采集和数据处理接口的运行频次; 2、 MCU和ADC的通信机制改为模拟SPI;即缩短标准SPI字节处理之间的寄存器标志位等待时间; 3、 优化ADC采集数据的驱动函数接口;即提高ADC数据采集接口的执行速度; 4、 MCU和ESC的通信机制改为标准SPI+自编函数;即提高SPI传输数据的速度;
实测滤波设置后的滞后时间:一般在13ms-14ms左右,如下图,扫描周期配置1000us,进行了不同电压的测试:
反正这个产品的总线响应时间调测,我当时真的是快要调测到吐了...... 不知道朋友们有木有在时间优化方便改程序改到不想改的地步?
|
@21小跑堂 :是的,二姨的经验值得学习
对比测试硬件SPI + HAL库函数 、 硬件SPI + 自编函数 、软件SPI 三种方式的运行时间,找到更合适的采样方式。根据二姨的经验,使用DMA+寄存器操作,完全摒弃库函数,可以将速度更好的提升,特别是HAL库,为了降低用户使用难度,库函数变的臃肿,执行效率低下。高速场景还需掌握寄存器的操作。