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.

[参考译文] MSP430F6736A:ADC10 DMA 中断丢失

Guru**** 2526700 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1003892/msp430f6736a-adc10-dma-interrupt-is-lost

器件型号:MSP430F6736A

尊敬的 TI 团队:

我正在使用 DMA 从 ADC10模块提取转换结果。  我们观察到、有时 DMA 中断会丢失、或者 ADC10模块可能会卡住。 请检查随附的快照和以下代码初始化。

void initAdc10 (void){
//设置 P1.2 A0、1.1 A1、1.0 A2
P1SEL |= BIT0 | BIT1 | BIT2;//将 P1.0、.1、.2设置为非 IO
_disable_interrupt ();//禁用中断;端口映射配置
PMAPKEYID = PMAPKEY;//启用访问端口映射寄存器
P1MAP2 = PM_ANALOG;//启用 A0
P1MAP1 = PM_ANALOG;//使能 A1
P1MAP0 = PM_ANALOG;//启用 A2
PMAPKEYID = 0;//禁用访问端口映射寄存器
_ENABLE_INTERRUPT ();//重新启用所有中断

//设置 ADC10
ADC10CTL0 = ADC10SHT_2 | ADC10MSC | ADC10ON;// 16ADCclks、MSC、ADC 打开
ADC10CTL1 = ADC10SHP | ADC10CONSEQ_3;//脉冲采样模式、重复序列
ADC10CTL2 = ADC10RES;// 10位分辨率
ADC10MCTL0 = ADC10INCH_2;// A0、A1、A2 (EOS)、AVCC 基准

//设置 DMA0 (ADC10IFG 触发)
DMACTL0 = DMA0TSEL_24;// ADC10IFG 触发器
DMA0SZ = 192;
__data20_write_long ((uintptr_t)&DMA0SA、(uintptr_t)&ADC10MEM0);
//源单个地址
__data20_write_long (((uintptr_t)&DMA0DA、(uintptr_t)&ADC_Result[0]);
//目标数组地址
DMA0CTL = DMADT_4 | DMADSTINCR_3 | DMASWDW | DMAEN | DMAIE;

#if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
#pragma vector=dma_vector
_interrupt void DMA0_ISR (void)
#Elif defined (_GNU_)
void __attribute__((中断(DMA_vector)) DMA0_ISR (void)
其他
错误编译器不受支持!
#endif

开关(__evo_in_range (DMAIV、16))

案例 DMAIV_NONE:break;//无中断
案例 DMAIV_DMA0IFG:// DMA0IFG = DMA 通道0
ADC10CTL0 &=~ADC10ENC;// 64次转换完成
DMA_flag = 1;
中断;
案例 DMAIV_DMA1IFG:中断;// DMA1IFG = DMA 通道1
案例 DMAIV_DMA2IFG:中断;// DMA2IFG = DMA 通道2
案例8:中断;//保留
案例10:中断;//保留
案例12:中断;//保留
案例14:中断;//保留
案例16:中断;//保留
默认值:break;

// ADC 主任务

void adc_main (void){

if (dma_FLAG){

ADC10CTL0 |= ADC10ENC | ADC10SC;

DMA_flag = 0;

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

    请检查 DMA7以查看您是否具有类似的条件  

    https://www.ti.com/lit/er/slaz646r/slaz646r.pdf?ts=1621942401595&ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FMSP430F6736A 

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

    是的、我已经检查 了勘误表、但我认为 这里不是 DMA7、即使 TI 也提供了相同 的 DMA 示例。 请查看以下 TI 示例-  

    unsigned int adc_result[64];

    int main (空)

    unsigned char i;
    volatile unsigned int adc_result_sum;
    volatile unsigned int adc_result_average;

    WDTCTL = WDTPW | WDTHOLD;//停止 WDT

    //设置 P1.1 A1、P1.0输出
    P1SEL |= BIT1;//将 P1.1设置为非 IO
    _disable_interrupt ();//禁用中断;端口映射配置
    PMAPKEYID = PMAPKEY;//启用访问端口映射寄存器
    P1MAP1 = PM_ANALOG;//使能 A1
    PMAPKEYID = 0;//禁用访问端口映射寄存器
    _ENABLE_INTERRUPT ();//重新启用所有中断
    P1DIR |= BIT0;//将 P1.0设置为输出方向
    P1OUT &=~BIT0;//清除 P1.0

    //配置 ADC10 -脉冲采样模式;软件触发;
    ADC10CTL0 = ADC10SHT_2 | ADC10ON | ADC10MSC;// 16ADCclks、ADC 打开
    ADC10CTL1 = ADC10SHP | ADC10CONSEQ_2;//脉冲采样模式、rpt 单通道
    ADC10CTL2 = ADC10RES;// 10位分辨率
    ADC10MCTL0 = ADC10INCH_1;// A1、AVCC 参考

    //配置 DMA (ADC10IFG 触发器)
    DMACTL0 = DMA0TSEL_24;// ADC10IFG 触发器
    DMA0SZ = 64;// 64次转换
    __data20_write_long ((uintptr_t)&DMA0SA、(uintptr_t)&ADC10MEM0);
    //源单个地址
    __data20_write_long (((uintptr_t)&DMA0DA、(uintptr_t)&ADC_Result[0]);
    //目标数组地址
    DMA0CTL = DMADT_4 | DMADSTINCR_3 | DMAEN | DMAIE;
    //重复单次传输
    //递增目的
    //字访问
    //在64次转换后启用 int
    while (1)

    ADC10CTL0 |= ADC10ENC | ADC10SC;//采样和转换开始

    _bis_SR_register (LPM0_bits | GIE);//输入 LMP0、带中断
    __no_operation();//仅用于调试

    ADC_RESULT_Sum = 0x0;//清除累加寄存器
    对于(i = 0;i < 64;i++)//此处的断点;查看 ADC_Result

    ADC_Result 和+= ADC_Result [i];

    ADC_RESULT_AVERAGE = ADC_RESULT_Sum >> 6;// 64次转换结果的平均值

    __DELAY_CYCLES (50000);//在下一个64次转换之前延迟

    #if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
    #pragma vector=dma_vector
    _interrupt void DMA0_ISR (void)
    #Elif defined (_GNU_)
    void __attribute__((中断(DMA_vector)) DMA0_ISR (void)
    其他
    错误编译器不受支持!
    #endif

    开关(__evo_in_range (DMAIV、16))

    案例 DMAIV_NONE:break;//无中断
    案例 DMAIV_DMA0IFG:// DMA0IFG = DMA 通道0
    ADC10CTL0 &=~ADC10ENC;// 64次转换完成
    _BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//返回时退出 LPM0
    中断;
    案例 DMAIV_DMA1IFG:中断;// DMA1IFG = DMA 通道1
    案例 DMAIV_DMA2IFG:中断;// DMA2IFG = DMA 通道2
    案例8:中断;//保留
    案例10:中断;//保留
    案例12:中断;//保留
    案例14:中断;//保留
    案例16:中断;//保留
    默认值:break;

      

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

    如何判断 DMA/ADC 已停止? 具体来说:PilotADC 告诉我们什么?

    >ADC10CTL0  &=~ADC10ENC;// 64次转换完成

    这不会立即停止 ADC --它将一直转换直到序列完成[参考 UG (SLAU208Q)第27.7.7.6节]。 这会设置一个允许 ADC 在停止前重新启动的争用、即 Erratum ADC42 [Ref Errata (SLAZ646R) p. 4]该示例用其__delay_cycles 和较短的序列掩盖了这种可能性。

    在设置 ADC10SC 前尝试插入:

    > while (ADC10CTL1 & ADCBUSY)/* empty*/; //静态。 不应花费很长的时间。

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

    DMA/ADC 之所以停滞不前、是因为编译 ADC (外部传感器信号)通常每秒变化1-5次计数、并且您可以检查电路板温度、它也是固定的。 通常在白天或长时间后、它应相差1或2度。 我将添加"while (ADC10CTL1 & ADCBUSY)"。  我希望这能解决这个问题。  

    感谢 Gary 和 Bruce。