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.

[参考译文] MSP430F6777A:使用 DMA 的多通道 ADC 读取问题

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1362695/msp430f6777a-multi-channel-adc-reading-problem-using-dma

器件型号:MSP430F6777A

我正在 MSP430F6777A 微处理器上使用 DMA 方法进行6通道 ADC 读取。 我将 ADC_TABLE[]数组显示为目标地址。 我按以下顺序将读取的 ADC 值保存到 ADC_TABLE[]。

ADC_TABLE []=[ADC_Channel5、ADC_Channel4、ADC_Channel3、ADC_Channel2、ADC_Channel1、 ADC_Channel0]

但在一段时间运行后、ADC 值开始被记录如下:

ADC_TABLE []=[ADC_Channel3、ADC_Channel2、ADC_Channel1、ADC_Channel0、ADC_Channel5、 通道4]

如何解决该问题?

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

    你好、Keles

    您能否参考并检查单序列和 DMA 使用的示例代码?

    https://www.ti.com/tool/download/SLAC648的 msp430f677xA_ADC10_10.c

    谢谢

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

    我通过按如下所示编辑中断来解决了错误。

    #pragma vector = Timer1_A1_vector
    __interrupt void Timer1_A1_ISR (空)
    {
    //对 TAIV 寄存器的任何访问、读取或写入都会自动复位
    //最高的"挂起"中断标志
    开关(_even_in_range (TA1IV、14)){
    情形0:中断;//无中断
    案例2:中断;
    情形4:断路;//未使用 CCR2
    案例6:断路;//未使用 CCR3
    情形8:中断;// CCR4未使用
    案例10:中断;// CCR5未使用
    情形12:断路;// CCR6未使用
    判例14:中断;
    默认值:中断;


    __ bis_SR_register (GIE);
    //LPM4_EXIT;
    while (adc10_a_isBusy (adc10_a_base));//等待 ADC 处于空闲状态(不忙)

    ADC10_A_startConversion (ADC10_A_base、ADC10_A_SEQOFCHANNELS);//启用和启动 ADC 转换

    __delay_cycles (5000);//延迟以允许转换完成

    TA1IV = 0;

    我在开始转换前等待 ADC 空闲、并在开始转换后增加了延迟。

    在当前软件中、我还在计时器中断中执行不同的操作。 使用 while ()和__delay_cycles ()是否会导致任何问题?

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

    你好、Keles

    感谢您的反馈!

    >>我按如下方式编辑中断解决了错误。

    我很高兴知道错误已得到解决

    >>使用 while ()和__delay_cycles ()是否会导致任何问题?

    while (ADC10_A_isBusy (ADC10_A_base)

    __delay_cycles (5000);//延迟以允许转换完成

    我认为 while 环路是可以的、

    我认为、如果 CPU 负载正常、那么延迟是可以的、

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

    解决此问题的更好方法是调整 ADC 设置(时钟分频器等)、以便始终在下一次触发之前完成。 如果时钟具有很多固有可变性并且与计时器时钟异步、则增加额外的裕量。

    在计时器中断内部等待是个不好主意。 您很容易在等待下一个计时器中断后结束。 由于您在 ISR 中再次启用中断、这可能会导致堆栈帧级联耗尽可用的 SRAM。

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

    尊敬的 Li 和 Schultz:

    感谢您的反馈。

    您认为以下方法如何?

    使用中断标志: 在 ISR 中设置一个标志并通过检查该标志来处理主循环中的长时间运行操作。

    例如:

    volatile bool adc_conversion_needed = false;
    
    #pragma vector = TIMER1_A1_VECTOR
    __interrupt void TIMER1_A1_ISR(void)
    {
        switch (__even_in_range(TA1IV, TAIV_TAIFG))
        {
            case TAIV_TACCR1:
                break;
            case TAIV_TACCR2:
                break;
            case TAIV_TACCR3:
                break;
            case TAIV_TACCR4:
                break;
            case TAIV_TACCR5:
                break;
            case TAIV_TACCR6:
                break;
            case TAIV_TAIFG:
                adc_conversion_needed = true; // Set the flag
                break;
            default:
                break;
        }
        TA1IV = 0; // Clear the interrupt flag
    }
    
    void main(void)
    {
        WDT_A_hold(WDT_A_BASE);
    
        // Timer and ADC initialization code
    
        while (1)
        {
            if (adc_conversion_needed)
            {
                adc_conversion_needed = false; // Clear the flag
    
                while (ADC10_A_isBusy(ADC10_A_BASE));
    
                ADC10_A_startConversion(ADC10_A_BASE, ADC10_A_SEQOFCHANNELS);
    
                __delay_cycles(5000); // Delay to allow the conversion to complete
            }
    
            // Other main loop code
        }
    }

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

    通常、当您使用 DMA 时、可以同时执行其他操作。 您可能只是通过 ADC 查询结果、而不是什么都不旋转。

    但这只是一个代码片段、剩下的代码片段可能会有一定的意义。 也许吧。

    哦、"TA1IV = 0"充其量是毫无意义的、最糟糕的是一个危险。 读取 TA1IV 会自动清除中断。

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

    在代码中、我在中断中执行不同的操作。 就像这样;

    案例 TAIV_TAIFG:

       my_function1();

       my_function2();

       my_function3();


       adc_conversion_needed = true;//设置标志


    中断;