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.

TMS320F280049C: TIDA-010231软件程序的问题

Part Number: TMS320F280049C
Other Parts Discussed in Thread: TIDA-010231

程序中使用了DMA通道进行数据搬运,但是我的问题是程序中有没有数据锁存,如果没有,程序是如何确保fft分析的数据是实时数据而不是上一个窗口的数据。

void ad_acquire_data(int16_t* pAdcDataArr)
{
uint16_t idx;

for (idx = 0; idx < ADSAMPLE_SIZE; idx++)
{
test_input[2 * idx] = (int32_t) pAdcDataArr[idx];
test_input[2 * idx + 1] = 0;
}
}

这个函数是如何读取dma搬运数据结果的,搬运的结果是否为adc实时采样结果,并且这组数据到fft输入口时,数据是否还在发生改变?

  • 您好

    1‌、DMA数据搬运‌:
    DMA用于在不需要CPU干预的情况下,快速地在内存之间或内存与外设之间传输数据。在你的情况下,DMA被用来从ADC(模数转换器)搬运数据到内存中的某个缓冲区。

    ‌2、数据锁存‌:
    数据锁存通常指的是在数据被读取或处理之前,确保它不会被改变。在你的场景中,如果没有显式的锁存机制(如使用信号量、互斥锁等),那么需要依靠其他方式来确保数据的完整性。

    3‌、数据的实时性‌:
    对于FFT分析来说,确保输入的数据是实时的(即当前采样的数据,而不是上一个窗口的数据)是至关重要的。

    ‌4、函数ad_acquire_data的分析‌:
    你的函数ad_acquire_data从一个指针pAdcDataArr读取数据,并将其复制到另一个数组test_input中。这里有几个关键点需要注意:

    pAdcDataArr指向的数据源是什么?如果它是DMA搬运的目标缓冲区,那么它应该包含最新的ADC采样数据。
    数据的复制是同步进行的吗?也就是说,在复制数据时,是否有可能DMA还在向pAdcDataArr写入新的数据?如果是这样,那么可能会存在数据竞争,导致读取的数据不是完全一致的。
    ‌4、确保数据的实时性和完整性‌:

    ‌双缓冲或环形缓冲‌:一种常见的方法是使用双缓冲或环形缓冲。这样,当一个缓冲区被DMA填充时,另一个缓冲区可以被用来进行FFT分析。通过适当的同步机制(如标志位、信号量等),可以确保在FFT分析时使用的数据是完整的且不会被DMA写入覆盖。

    中断或DMA完成回调‌:可以利用DMA完成传输后的中断或回调来通知CPU数据已经准备好,从而开始FFT分析。这样可以确保FFT分析的数据是最新的。

    ‌数据拷贝的同步‌:如果ad_acquire_data函数在DMA传输完成之前被调用,那么需要确保在复制数据时DMA不会同时修改pAdcDataArr中的数据。这可以通过禁用DMA、使用锁、或确保DMA传输和数据处理在不同的时间片中进行来实现。
    ‌数据是否还在发生改变‌:

    如果ad_acquire_data函数在DMA传输完成后被调用,并且在此期间没有其他进程或线程修改pAdcDataArr中的数据,那么可以认为数据在复制到test_input时是不会发生改变的。
    然而,如果DMA在ad_acquire_data执行期间仍在运行,并且没有适当的同步机制来防止数据竞争,那么数据可能会在被复制时发生改变。

    综上所述,要确保FFT分析的数据是实时的且没有被上一个窗口的数据污染,你需要:

    确保DMA传输和数据处理之间有适当的同步。
    使用双缓冲或环形缓冲来分离数据采集和数据处理。
    在数据处理之前确认数据已经完整且不会被修改。
    如果你的当前实现没有这些机制,那么可能需要修改代码来添加适当的同步和缓冲管理。

    这是官方公布的相关SDK,您可以参考这个资料。

  • 感谢您的回复,这段例程是TI官方给的电弧检测的程序,我在阅读程序的时候,发现了DMA有三条通道,第一个通道搬运了采样结果的前512个数据,而第二通道搬运了后512个数据,第三条通道将1024个数据进行了整合,我看到程序的注释中写到了乒乓缓存的方法。

    void ARC_HAL_setupDMA(void)
    {
    //
    // Perform a hard reset on DMA
    //
    DMA_initController();
    //
    // Allow DMA to run free on emulation suspend
    //
    DMA_setEmulationMode(DMA_EMULATION_FREE_RUN);

    //
    // DMA channel 1 set up for ADCA first 512 Samples
    //
    DMA_configAddresses(ARC_DMA1_BASE, &ARC_ADCResults1,
    (uint16_t *)ARC_ADC_RESULTS_BASE);

    //
    //Transfer 1 Word (16-Bit) per burst
    //
    DMA_configBurst(ARC_DMA1_BASE, 1, 0, 1);
    //
    //Do SAMPLES amount of burst per transfer
    //
    DMA_configTransfer(ARC_DMA1_BASE, ARC_SAMPLES / 2, 0, 1);
    DMA_configMode(ARC_DMA1_BASE, DMA_TRIGGER_ADCA1,
    (DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_DISABLE |
    DMA_CFG_SIZE_16BIT));

    DMA_enableTrigger(ARC_DMA1_BASE);
    DMA_disableOverrunInterrupt(ARC_DMA1_BASE);
    DMA_setInterruptMode(ARC_DMA1_BASE, DMA_INT_AT_END);
    DMA_enableInterrupt(ARC_DMA1_BASE);

    //
    // DMA channel 2 set up for ADCA second 512 Samples
    //
    DMA_configAddresses(ARC_DMA2_BASE, &ARC_ADCResults2,
    (uint16_t *)ARC_ADC_RESULTS_BASE);

    //
    //Transfer 1 Word (16-Bit) per burst
    //
    DMA_configBurst(ARC_DMA2_BASE, 1, 0, 1);
    //
    //Do SAMPLES amount of burst per transfer
    //
    DMA_configTransfer(ARC_DMA2_BASE, ARC_SAMPLES / 2, 0, 1);
    DMA_configMode(ARC_DMA2_BASE, DMA_TRIGGER_ADCA2,
    (DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_DISABLE |
    DMA_CFG_SIZE_16BIT));

    DMA_enableTrigger(ARC_DMA2_BASE);
    DMA_disableOverrunInterrupt(ARC_DMA2_BASE);
    DMA_setInterruptMode(ARC_DMA2_BASE, DMA_INT_AT_END);
    DMA_enableInterrupt(ARC_DMA2_BASE);

    //
    // DMA channel 3 set up for copying from ADCResult1 or ADCResults to CH1Data
    //
    DMA_configAddresses(ARC_DMA3_BASE, &ARC_CH1Data,
    &ARC_ADCResults1);

    //
    //Transfer 1 Word (16-Bit) per burst
    //
    DMA_configBurst(ARC_DMA3_BASE, 1, 1, 1);
    //
    //Do SAMPLES amount of burst per transfer
    //
    DMA_configTransfer(ARC_DMA3_BASE, ARC_SAMPLES / 2, 1, 1);
    DMA_configMode(ARC_DMA3_BASE, DMA_TRIGGER_SOFTWARE,
    (DMA_CFG_ONESHOT_ENABLE | DMA_CFG_CONTINUOUS_DISABLE |
    DMA_CFG_SIZE_16BIT));

    DMA_enableTrigger(ARC_DMA3_BASE);
    DMA_disableOverrunInterrupt(ARC_DMA3_BASE);
    DMA_setInterruptMode(ARC_DMA3_BASE, DMA_INT_AT_END);
    DMA_enableInterrupt(ARC_DMA3_BASE);

    DMA_clearTriggerFlag(ARC_DMA1_BASE); // DMA channel 1
    DMA_clearTriggerFlag(ARC_DMA2_BASE); // DMA channel 2
    DMA_clearTriggerFlag(ARC_DMA3_BASE); // DMA channel 3

    //
    // Start DMA 1
    //
    DMA_startChannel(ARC_DMA1_BASE);

    }

    void ARC_reinitArcDetect(void)
    {
    //
    //Stop sampling while Arc Detection is re-initialized
    //
    ARC_HAL_disableADCTrigger();

    ARC_HAL_DMA_stop(ARC_DMA1_BASE);
    ARC_HAL_DMA_stop(ARC_DMA2_BASE);
    ARC_HAL_DMA_stop(ARC_DMA3_BASE);

    //
    //Re-initialize Arc Detection
    //
    ARC_InitArcDetect(1);

    //
    //Reset all flags
    //
    ARC_ReinitArcDetect = 0;
    ARC_startArcDetect = 0;
    is_ArcTimingError = 0;

    //
    //Start sampling again
    //
    ARC_HAL_DMA_start(ARC_DMA1_BASE);
    ARC_HAL_enableADCTrigger();
    }

    //
    //DMA CH1 ISR:
    //
    /*
    * Stops DMA CH1 after first 512 Samples have bin copied to ADCResults1.
    * Starts DMA CH2, which copies second 512 Samples to ADCResults2 Buffer
    * Sets DMA CH3 source address to ADCResults1 and destination address to CH1Data
    * Starts DMA 3, which now copies all values from ADCResults1 into the
    * 1st halve of CH1Data
    */
    void runArcDMA1ISR(void)
    {
    ARC_HAL_DMA_stop(ARC_DMA1_BASE);
    ARC_HAL_DMA_start(ARC_DMA2_BASE);

    is_ArcDataBufferFull = false;

    //
    // DMA channel 3 set up for copying from ADCResult1 or ADCResults to CH1Data
    //
    ARC_HAL_DMA_configAddresses(ARC_DMA3_BASE, &ARC_CH1Data,
    &ARC_ADCResults1);

    ARC_HAL_DMA_startAndTrigger(ARC_DMA3_BASE);

    //
    // Acknowledge interrupt
    //
    ARC_HAL_DMA_clearInterruptFlag();
    }

    //
    //DMA CH2 ISR:
    //
    /*
    * Stops DMA CH2 after first 512 Samples have bin copied to ADCResults1.
    * Starts DMA CH1, which copies second 512 Samples to ADCResults2 Buffer
    * Sets DMA CH3 source address to ADCResults2 and destination address to
    * CH1Data[512]
    * Starts DMA 3, which now copies all values from ADCResults2
    * into the 2nd halve of CH1Data
    */
    void runArcDMA2ISR(void)
    {
    ARC_HAL_DMA_stop(ARC_DMA2_BASE);
    ARC_HAL_DMA_start(ARC_DMA1_BASE);

    is_ArcDataBufferFull = true;

    //
    // DMA channel 3 set up for copying from ADCResult1 or ADCResults to CH1Data
    //
    ARC_HAL_DMA_configAddresses(ARC_DMA3_BASE, &ARC_CH1Data[ARC_SAMPLES/2],
    &ARC_ADCResults2);

    ARC_HAL_DMA_startAndTrigger(ARC_DMA3_BASE);

    //
    // Acknowledge interrupt
    //
    ARC_HAL_DMA_clearInterruptFlag();
    }

    //
    //DMA CH1 ISR:
    //
    /*
    * Stops DMA CH3 after ADCResult_N has been copied to CH1Data
    * Sets startArcDetect Flag to 1 if ADCResults 2 has been copied to CH1Data
    */
    void runArcDMA3ISR(void)
    {
    ARC_HAL_DMA_stop(ARC_DMA3_BASE);


    if(is_ArcDataBufferFull)
    {
    if(!is_ArcBusy)
    {
    ARC_startArcDetect = 1;
    }
    else
    {
    is_ArcTimingError = true;
    }
    }
    //
    // Acknowledge interrupt
    //
    ARC_HAL_DMA_clearInterruptFlag();
    }

    目前,使用该DMA通道,读取出的采样是存在问题的。

    该输入为60kHz,峰峰值2.5V,偏移1.25V的正弦信号,程序的采样频率为500kHz,我当时认为是garph拟合波形不理想,所以我将数据导数使用matlab进行拟合,拟合结果如下。

    发现问题确实是由于数据引起的。但是当我将程序暂停,发现波形变好。

    所以我认为是ad采样时,数据刷新的速度比读取速度要快,导致了数据出现跳变这种情况,当程序暂停时,采样的刷新速度和数据读取速度对齐,所以波形变好,我不知道这样理解是否有问题,还需要向您请教,再次感谢您的回复!

  • 您好

    根据您的描述,出现这种情况是有这种可能,建议你通过添加适当的延迟来测试一下,如果能通过这个中方式解决,很大可能是您理解的原因。

  • 我在读取程序的部分加入了100ms的延迟,最后得到的波形确实好了很多,感谢您的回复!

    如果可以的话,我想问一下检测程序中,这三行的修正系数是如何计算的?

    scaled = 4.342944819f * logf(BandSum);
    scaled += 2.129f; // Correct for Hanning window amplitude shift & broadband noise bin width; same as *2.0/1.225
    scaled -= POSTPROCESS_SCALING; // Subtract the post-processing bias

  • 您好

    没理解您的意思,您分享的不就是计算公式吗?如公式这样计算的。

  • 因为这个程序是ti官方给的程序,我是在读这个程序,所以发现了这个计算公式,有点理解不了,所以想请教一下您这边有没有这个程序的设计文档,想了解一下这个计算的机理。

  • 您好

    如果这是TI给的相关例程,在库文件和代码后有注释,或者在项目包里面有指导文件,如果您没有找到,您可以分享一下您看到的程序的链接,我帮您找一下。

  • 感谢您的回复,https://www.ti.com.cn/tool/cn/TIDA-010231?keyMatch=TIDA-010231&tisearch=universal_search&usecase=refdesign 这里是TI官方给出的前端设计参考,程序在CCS中resource explorer中查找TIDA-010231即可,但是我在设计文档中并没有找到程序说明。

  • 您好

    如图所示在程序中有对于这部分代码作用做了相关说明,但是没有针对性的推导公式说明。

  • 好的 感谢这几天的回复 谢谢!