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.

[参考译文] TMS320F28069F:具有软件触发 ADC 的 C28x 杂散 ADC 中断

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1018698/tms320f28069f-c28x-spurious-adc-interrupts-with-software-triggered-adc

器件型号:TMS320F28069F
主题中讨论的其他器件:C2000WARE

您好!

我遇到了软件强制 ADC 转换的问题。 我有两个 ADC 中断。 一个是在 SO0和 SOC1上同步进行 ADC 转换时 EOC 触发的快速中断。 较慢的中断是 SOC2和 SOC3上同步进行 ADC 转换时 EOC 触发的。 较慢的中断 SOC 从快速中断中的递减采样数中触发。 我注意到代码中有伪中断、似乎是软件强制中断调用的原因;在注释掉软件强制中断调用后、伪快速中断不会发生。 这个问题的另一个因素是我在 PIE 中使用了两个中断。 当我将较慢的中断更改为使用 PIEIER10时、代码工作正常。 请参阅以下代码。 我会发布我的所有代码、但很遗憾它很大。 重要的一点不是直接使用整个寄存器访问、而不是 c2000ware 代码中的逐位示例。 下面是我观察到的内容的屏幕截图

并注释掉软件强制中断

working_high_speed_trace

在软件强制中断的情况下、中断保持触发状态

spurious_interrupts

以下 是相关的代码摘录。 我``问题出在快速 ISR 内部的 Δ Σ AdcRegs.ADCSOCFRC1 |= ADCSOC_SOC2;Δ Σ。 我的调试器显示 PIEIFR1和 ADCINTFLG 的中断标志看起来正确、也只有 ADCINT1处于暂挂状态。 然而、在调用软件强制 SoC 后、ADCINTFLG 会转至0x0103、PIEIFR1 = 0x0022、ADCINTOVF = 0x0003。 我已经检查 了 AdcRegs.ADCSOCFRC1的存储器地址、它是正确的。

问题:

  • 是否无法从 ISR 上下文中调用软件强制 SoC?
  • RMW 操作和 ADCSOCFRC1不正确吗?
  • 是否一次无法使用来自 PIE 组的多个中断?

static const PwmConfig resolver_pwm_config =
{
    .enable_center_aligned=true,
    .counts=937,//94,
    .adc_trigger={.enable=true, .event_scaler=ePwmSocPulseOnThirdEvent},
    .compliment={.enable=false, .edge_delay=0},
    .sync={.enable=false, .phase_counts=0, .sync_out=ePwmSyncOutSyncIn}
};

static const SampleConfig resolver_adc_config =
{
    .soc_index=0,
    .channel=eAdcInA0,
    .trigger_source=eAdcTriggerPwm1SocA,
    .sample_time=7,
    .enable_simultaneous_sample=true,
    .adc_interrupt={.enable=true, .interrupt_index=1}
};

static const SampleConfig current_adc_config =
{
    .soc_index=2,
    .channel=eAdcInA1,
    .trigger_source=eAdcTriggerSoftware,
    .sample_time=7,
    .enable_simultaneous_sample=true,
    .adc_interrupt={.enable=true, .interrupt_index=2}
};

__interrupt void adc_resolver_isr(void)
{
    static const unsigned down_count = 4;
    static unsigned isr_count = 0;

    hal_resolver_isr_pin_toggle();

    hal_resolver_sin = AdcResult.ADCRESULT0;
    hal_resolver_cos = AdcResult.ADCRESULT1;

    // start phase current adc sampling
    if (++isr_count >= down_count)
    {
        isr_count = 0;
        AdcRegs.ADCSOCFRC1 |= ADCSOC_SOC2;
    }

    AdcRegs.ADCINTFLGCLR |= ADCINT_BIT1;
    AdcRegs.ADCINTOVFCLR |= ADCINT_BIT1;
    PieCtrlRegs.PIEACK = PIEACK_GROUP1;
}

__interrupt void adc_current_isr(void)
{
    static unsigned down_count = 20;
    static unsigned isr_count = 0;

    hal_current_isr_pin_toggle();

    hal_current_a = AdcResult.ADCRESULT2;
    hal_current_b = AdcResult.ADCRESULT3;

    AdcRegs.ADCINTFLGCLR |= ADCINT_BIT2;
    AdcRegs.ADCINTOVFCLR |= ADCINT_BIT2;
    PieCtrlRegs.PIEACK = PIEACK_GROUP1;
}

void hal_boot_init(void)
{
    f28_setup_system_control(&system_config);
    DINT; // Disable CPU interrupts
    f28_setup_peripheral_interrupt_control();

    // Disable CPU interrupts and clear all CPU interrupt flags
    IER = 0x0000;
    IFR = 0x0000;

    f28_setup_peripheral_interrupt_table();

    // map isrs
    EALLOW;
    PieVectTable.ADCINT1 = &adc_resolver_isr;
    PieVectTable.ADCINT2 = &adc_current_isr;
    PieVectTable.ADCINT9 = &adc_1kHz_isr;
    PieVectTable.TINT2 = &cpu_timer2_isr;
    PieVectTable.SPIRXINTA = &sci_rxa_isr;
    EDIS;

    hal_gpio_init();

    f28_adc_init();
    f28_adc_soc_setup(&adc_1khz_config);
    f28_adc_soc_setup(&current_adc_config);
    f28_adc_soc_setup(&resolver_adc_config);

    f28_timer_init(&CpuTimer2Regs, &msec_timer_config);

    f28_sci_init(&SciaRegs, &sci_a_config, LSPCLK_SPEED);
    f28_can_init(&can_node, &can_bitrate, &can_mask_filter);
    f28_pwm_init(&EPwm1Regs, &resolver_pwm_config);

    // Enable ADCINT1,2,9
     PieCtrlRegs.PIEIER1 = (PIEIxR_INTx1 | PIEIxR_INTx2 | PIEIxR_INTx6);
    // Enable SCIRXA
     PieCtrlRegs.PIEIER9 = (PIEIxR_INTx1);

    // Enable Int1=Adc; Int9=sci; Int14=timer2 interrupt
    IER = (IxR_INT1 | IxR_INT9 | IxR_INT14);

    // Enable global Interrupts and higher priority real-time debug events
    EINT;   // Enable Global interrupt INTM
    ERTM;   // Enable Global realtime interrupt DBGM
}

最后、这里是使用 ADCINT3和 PIEIER10的跟踪。 这就是我期望发生的情况。 代码更改如下;该代码不会在软件 SoC 启动后产生奇数 ADCINTFLG = 0x0103。 但是、它会产生 ADCINTFLG = 0x0005、PIEIF1 = 0x0002、PIEIF10 = 0x0007、ADCINTOVF = 0x0000。 这里奇怪的是、为什么 ADCINTFLG = 0x0005而不是0x0001?

working with adcint3

static const SampleConfig current_adc_config =
{
    .soc_index=2,
    .channel=eAdcInA1,
    .trigger_source=eAdcTriggerSoftware,
    .sample_time=7,
    .enable_simultaneous_sample=true,
    .adc_interrupt={.enable=true, .interrupt_index=3}
};

__interrupt void adc_current_isr(void)
{
    static unsigned down_count = 20;
    static unsigned isr_count = 0;

    hal_current_isr_pin_toggle();

    hal_current_a = AdcResult.ADCRESULT2;
    hal_current_b = AdcResult.ADCRESULT3;

    AdcRegs.ADCINTFLGCLR |= ADCINT_BIT3;
    AdcRegs.ADCINTOVFCLR |= ADCINT_BIT3;
    PieCtrlRegs.PIEACK = PIEACK_GROUP10;
}

void hal_boot_init(void)
{
    f28_setup_system_control(&system_config);
    DINT; // Disable CPU interrupts
    f28_setup_peripheral_interrupt_control();

    // Disable CPU interrupts and clear all CPU interrupt flags
    IER = 0x0000;
    IFR = 0x0000;

    f28_setup_peripheral_interrupt_table();

    // map isrs
    EALLOW;
    PieVectTable.ADCINT1 = &adc_resolver_isr;
    PieVectTable.ADCINT3 = &adc_current_isr;
    PieVectTable.ADCINT9 = &adc_1kHz_isr;
    PieVectTable.TINT2 = &cpu_timer2_isr;
    PieVectTable.SPIRXINTA = &sci_rxa_isr;
    EDIS;

    hal_gpio_init();

    f28_adc_init();
    f28_adc_soc_setup(&adc_1khz_config);
    f28_adc_soc_setup(&current_adc_config);
    f28_adc_soc_setup(&resolver_adc_config);

    f28_timer_init(&CpuTimer2Regs, &msec_timer_config);

    f28_sci_init(&SciaRegs, &sci_a_config, LSPCLK_SPEED);
    f28_can_init(&can_node, &can_bitrate, &can_mask_filter);
    f28_pwm_init(&EPwm1Regs, &resolver_pwm_config);

    // Enable ADCINT1,2,9
    PieCtrlRegs.PIEIER1 = (PIEIxR_INTx1 | PIEIxR_INTx6);
    PieCtrlRegs.PIEIER10 = PIEIxR_INTx3;

    // Enable SCIRXA
    PieCtrlRegs.PIEIER9 = (PIEIxR_INTx1);

    // Enable Int1=Adc; Int9=sci; Int14=timer2 interrupt
    IER = (IxR_INT1 | IxR_INT9 | IxR_INT10 | IxR_INT14);

    // Enable global Interrupts and higher priority real-time debug events
    EINT;   // Enable Global interrupt INTM
    ERTM;   // Enable Global realtime interrupt DBGM
}

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

    Nick、

    很抱歉、对于延迟的回复、您能否在 ADC 寄存器初始化后为这两组示例代码布置 INTSEL1N2和 INTSEL3N4的值?  

    如果您只是想在 ADC 基址的偏移量0x8和0x9处布置16位寄存器、这将是很好的。  在同步模式下、我相信两个 EoC 都将在组中触发、因此理论上、您可以为同一组2个样本设置2 INT。

    此外、您能否在第一个示例中评论 PIE10的状态?  我想看到的原因是、ADCINT1和 ADCINT2在 PIE 组1和 PIE 组10中都是重复的。  组1是将 ADC ISR 设置为最高优先级组、组10是这样、如果使用的 ADCISPR 超过2、则所有 ADCISPR 都位于类似组中、以实现一致的优先级。  我想知道是否在 PIE 组中同时启用了 INT1/INT2、会发生什么情况(尽管您必须在两个位置投射 ISR 以使代码执行)

    最棒的

    Matthew

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

    感谢 Matt 的回答。 不用担心延迟。 我意识到我非常详细。

    我在 hal_boot_init ()的末尾放置了一个断点。 我检查了 ADC 的内核寄存器

    寄存器如下、用于在 PIEIER1上使用 ADCINT1、2、9 (导致重新发生中断的设置)

    INTSEL1N2    0x2321    ADC Interrupt 1 and 2 Selection [Memory Mapped]    
    INTSEL3N4    0x0000    ADC Interrupt 3 and 4 Selection [Memory Mapped]    
    INTSEL5N6    0x0000    ADC Interrupt 5 and 6 Selection [Memory Mapped]    
    INTSEL7N8    0x0000    ADC Interrupt 7 and 8 Selection [Memory Mapped]    
    INTSEL9N10    0x0024    ADC Interrupt 9 and 10 Selection [Memory Mapped]
    
    PIEIER1    0x0023    PIE, INT1 Group Enable Register [Memory Mapped]    
    PIEIFR1    0x0000    PIE, INT1 Group Flag Register [Memory Mapped]    
    PIEIER2    0x0000    PIE, INT2 Group Enable Register [Memory Mapped]    
    PIEIFR2    0x0000    PIE, INT2 Group Flag Register [Memory Mapped]    
    PIEIER3    0x0000    PIE, INT3 Group Enable Register [Memory Mapped]    
    PIEIFR3    0x0000    PIE, INT3 Group Flag Register [Memory Mapped]    
    PIEIER4    0x0000    PIE, INT4 Group Enable Register [Memory Mapped]    
    PIEIFR4    0x0000    PIE, INT4 Group Flag Register [Memory Mapped]    
    PIEIER5    0x0000    PIE, INT5 Group Enable Register [Memory Mapped]    
    PIEIFR5    0x0000    PIE, INT5 Group Flag Register [Memory Mapped]    
    PIEIER6    0x0000    PIE, INT6 Group Enable Register [Memory Mapped]    
    PIEIFR6    0x0000    PIE, INT6 Group Flag Register [Memory Mapped]    
    PIEIER7    0x0000    PIE, INT7 Group Enable Register [Memory Mapped]    
    PIEIFR7    0x0000    PIE, INT7 Group Flag Register [Memory Mapped]    
    PIEIER8    0x0000    PIE, INT8 Group Enable Register [Memory Mapped]    
    PIEIFR8    0x0000    PIE, INT8 Group Flag Register [Memory Mapped]    
    PIEIER9    0x0001    PIE, INT9 Group Enable Register [Memory Mapped]    
    PIEIFR9    0x0000    PIE, INT9 Group Flag Register [Memory Mapped]    
    PIEIER10    0x0000    PIE, INT10 Group Enable Register [Memory Mapped]    
    PIEIFR10    0x0003    PIE, INT10 Group Flag Register [Memory Mapped]    
    PIEIER11    0x0000    PIE, INT11 Group Enable Register [Memory Mapped]    
    PIEIFR11    0x0000    PIE, INT11 Group Flag Register [Memory Mapped]    
    PIEIER12    0x0000    PIE, INT12 Group Enable Register [Memory Mapped]    
    PIEIFR12    0x0000    PIE, INT12 Group Flag Register [Memory Mapped]    

    这些是将 ADCINT1与 PIEIER1搭配使用的寄存器、以及将 ADC3、4用于 PIEIER10的寄存器

    INTSEL1N2    0x0E21    ADC Interrupt 1 and 2 Selection [Memory Mapped]    
    INTSEL3N4    0x2423    ADC Interrupt 3 and 4 Selection [Memory Mapped]    
    INTSEL5N6    0x0000    ADC Interrupt 5 and 6 Selection [Memory Mapped]    
    INTSEL7N8    0x0000    ADC Interrupt 7 and 8 Selection [Memory Mapped]    
    INTSEL9N10    0x0000    ADC Interrupt 9 and 10 Selection [Memory Mapped]    
    
    PIEIER1    0x0001    PIE, INT1 Group Enable Register [Memory Mapped]    
    PIEIFR1    0x0003    PIE, INT1 Group Flag Register [Memory Mapped]    
    PIEIER2    0x0000    PIE, INT2 Group Enable Register [Memory Mapped]    
    PIEIFR2    0x0000    PIE, INT2 Group Flag Register [Memory Mapped]    
    PIEIER3    0x0000    PIE, INT3 Group Enable Register [Memory Mapped]    
    PIEIFR3    0x0000    PIE, INT3 Group Flag Register [Memory Mapped]    
    PIEIER4    0x0000    PIE, INT4 Group Enable Register [Memory Mapped]    
    PIEIFR4    0x0000    PIE, INT4 Group Flag Register [Memory Mapped]    
    PIEIER5    0x0000    PIE, INT5 Group Enable Register [Memory Mapped]    
    PIEIFR5    0x0000    PIE, INT5 Group Flag Register [Memory Mapped]    
    PIEIER6    0x0000    PIE, INT6 Group Enable Register [Memory Mapped]    
    PIEIFR6    0x0000    PIE, INT6 Group Flag Register [Memory Mapped]    
    PIEIER7    0x0000    PIE, INT7 Group Enable Register [Memory Mapped]    
    PIEIFR7    0x0000    PIE, INT7 Group Flag Register [Memory Mapped]    
    PIEIER8    0x0000    PIE, INT8 Group Enable Register [Memory Mapped]    
    PIEIFR8    0x0000    PIE, INT8 Group Flag Register [Memory Mapped]    
    PIEIER9    0x0001    PIE, INT9 Group Enable Register [Memory Mapped]    
    PIEIFR9    0x0000    PIE, INT9 Group Flag Register [Memory Mapped]    
    PIEIER10    0x000C    PIE, INT10 Group Enable Register [Memory Mapped]    
    PIEIFR10    0x0003    PIE, INT10 Group Flag Register [Memory Mapped]    
    PIEIER11    0x0000    PIE, INT11 Group Enable Register [Memory Mapped]    
    PIEIFR11    0x0000    PIE, INT11 Group Flag Register [Memory Mapped]    
    PIEIER12    0x0000    PIE, INT12 Group Enable Register [Memory Mapped]    
    PIEIFR12    0x0000    PIE, INT12 Group Flag Register [Memory Mapped]    


    如果我误读或错过了您的问题的答案、请告诉我

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

    此外、我将 PIE_VECT_TABLE 设置为禁止在您之前提到的 PIEIER10复制中使用 ADCINT1和 ADCINT2

        // Group 10 PIE Peripheral Vectors
        PINT rsvd10_1; // Can be ADCINT1, but must make ADCINT1 in Group 1 space "reserved".
        PINT rsvd10_2; // Can be ADCINT2, but must make ADCINT2 in Group 1 space "reserved".
        PINT ADCINT3;
        PINT ADCINT4;
        PINT ADCINT5;
        PINT ADCINT6;
        PINT ADCINT7;
        PINT ADCINT8;

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

    Nick、

    您还能检查 ADCINTSOCSELn 寄存器的值吗? 除非您打算自触发 ADC 转换、否则它们都应为零。

    Tommy

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

    非工作和工作中的 ADC? 您是否希望这些寄存器恰好在我完成初始化之后或在我以最快的 ISR 启动软件强制 ADC 之后出现断点?

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

    Nick、

    我没有在您的代码段中看到这些寄存器被配置。 如果为 true、则可以在工作或非工作场景的中等执行断点之后的任何时间捕获它们。 目标是确认没有来自代码重用的转接设置。

    Tommy

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

    我想你发现了 Tommy 这个问题。 c2000ware 的 ADC 偏移均值函数使这些寄存器能够启用 SoC。

    ADCINTSOCSEL1   0xAAAA   ADC 中断 SOC 选择1 [存储器映射]    
    ADCINTSOCSEL2   0x5555   ADC 中断 SOC 选择2 [存储器映射]    

    针对此问题的重新关注是、当我从 c2000ware F2806x_adc.c 复制此函数时、我没有阅读警告

    // AdcConversion - This function initiates several ADC conversions and returns 
    // the average. It uses ADCINT1 and ADCINT2 to "ping-pong" between SOC0-7 
    // and SOC8-15 and is referred to as "ping-pong" sampling.
    // * IMPORTANT *
    // This function will overwrite previous ADC settings. Recommend saving 
    // previous settings.
    //
    Uint16
    AdcConversion(void)

    我添加了行来清除这些寄存器、它看起来很实用。 谢谢!

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

    Nick、

    我很高兴听到您让它立即工作!

    Tommy

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

    再次感谢您的帮助、这一问题令人沮丧。 我几乎想芯片中的某些东西是错误的、但当然、这是程序员的错误!