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.

[参考译文] TMS320F28377D:TMS320F28377D

Guru**** 2524550 points


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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1187303/tms320f28377d-tms320f28377d

器件型号:TMS320F28377D

您好!

我修改了原始示例 ADC_Ex5_SoC_Continuous、该示例将2个连续转换为1个转换。

代码如下:

//
// Included Files
//
#include "driverlib.h"
#include "device.h"

//
// Function Prototypes
//
void configureADC(uint32_t adcBase);
void setupADCContinuous(uint32_t adcBase, uint32_t channel);

//
// Defines
//
#define RESULTS_BUFFER_SIZE 1024 //buffer for storing conversion results
//(size must be multiple of 16)
#define EX_ADC_RESOLUTION 12
// 12 for 12-bit conversion resolution, which supports (ADC_MODE_SINGLE_ENDED)
// Sample on single pin (VREFLO is the low reference)
// Or 16 for 16-bit conversion resolution, which supports (ADC_MODE_DIFFERENTIAL)
// Sample on pair of pins (difference between pins is converted, subject to
// common mode voltage requirements; see the device data manual)

//
// Globals
//
uint16_t adcAResults[RESULTS_BUFFER_SIZE];
uint16_t resultsIndex;

void main(void)
{
//
// Initialize device clock and peripherals
//
Device_init();

//
// Disable pin locks and enable internal pullups.
//
Device_initGPIO();

//
// Initialize PIE and clear PIE registers. Disables CPU interrupts.
//
Interrupt_initModule();

//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
//
Interrupt_initVectorTable();


//
// Configure the ADC and power it up
//
configureADC(ADCA_BASE);

//
// Setup the ADC for continuous conversions on channel 0
//
setupADCContinuous(ADCA_BASE, 0U);

//
// Initialize results buffer
//
for(resultsIndex = 0; resultsIndex < RESULTS_BUFFER_SIZE; resultsIndex++)
{
adcAResults[resultsIndex] = 0;
}
resultsIndex = 0;

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

//
// Take conversions indefinitely in loop
//
do
{
//
// Enable ADC interrupts
//
ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER1);
// ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER2);
// ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER3);
// ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER4);

//
// Clear all interrupts flags(INT1-4)
//
HWREGH(ADCA_BASE + ADC_O_INTFLGCLR) = 0x000F;

//
// Initialize results index
//
resultsIndex = 0;

//
// Software force start SOC0 to SOC7
//
// HWREGH(ADCA_BASE + ADC_O_SOCFRC1) = 0x00FF;
ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER0 );
ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER1 );
ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER2 );
ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER3 );
ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER4 );
ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER5 );
ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER6 );
ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER7 );
ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER8 );
ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER9 );
ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER10 );
ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER11);
ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER12);
ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER13);
ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER14);
ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER15);

//
// Keep taking samples until the results buffer is full
//
while(resultsIndex < RESULTS_BUFFER_SIZE)
{
//
// Wait for first set of 8 conversions to complete
//
while(false == ADC_getInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1));

//
// Clear the interrupt flag
//
ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);

//
// Save results for first 8 conversions
//
// Note that during this time, the second 8 conversions have
// already been triggered by EOC6->ADCIN1 and will be actively
// converting while first 8 results are being saved
//
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER0);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER1);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER2);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER3);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER4);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER5);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER6);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER7);

//
// Wait for the second set of 8 conversions to complete
//
// while(false == ADC_getInterruptStatus(ADCA_BASE, ADC_INT_NUMBER4));

//
// Clear the interrupt flag
//
// ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER4);

//
// Save results for second 8 conversions
//
// Note that during this time, the first 8 conversions have
// already been triggered by EOC14->ADCIN2 and will be actively
// converting while second 8 results are being saved
//
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER8);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER9);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER10);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER11);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER12);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER13);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER14);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER15);

}

//
// Disable all ADCINT flags to stop sampling
//
ADC_disableInterrupt(ADCA_BASE, ADC_INT_NUMBER1);
// ADC_disableInterrupt(ADCA_BASE, ADC_INT_NUMBER2);
// ADC_disableInterrupt(ADCA_BASE, ADC_INT_NUMBER3);
// ADC_disableInterrupt(ADCA_BASE, ADC_INT_NUMBER4);

//
// At this point, adcAResults[] contains a sequence of conversions
// from the selected channel
//

//
// Software breakpoint, hit run again to get updated conversions
//
asm(" ESTOP0");
}
while(1); // Loop forever
}

//
// configureADC - Write ADC configurations and power up the ADC for both
// ADC A and ADC B
//
void configureADC(uint32_t adcBase)
{
//
// Set ADCDLK divider to /4
//
ADC_setPrescaler(adcBase, ADC_CLK_DIV_4_0);

//
// Set resolution and signal mode (see #defines above) and load
// corresponding trims.
//
#if(EX_ADC_RESOLUTION == 12)
ADC_setMode(adcBase, ADC_RESOLUTION_12BIT, ADC_MODE_SINGLE_ENDED);
#elif(EX_ADC_RESOLUTION == 16)
ADC_setMode(adcBase, ADC_RESOLUTION_16BIT, ADC_MODE_DIFFERENTIAL);
#endif

//
// Set pulse positions to late
//
ADC_setInterruptPulseMode(adcBase, ADC_PULSE_END_OF_CONV);

//
// Power up the ADCs and then delay for 1 ms
//
ADC_enableConverter(adcBase);

//
// Delay for 1ms to allow ADC time to power up
//
DEVICE_DELAY_US(1000);
}

//
// setupADCContinuous - setup the ADC to continuously convert on one channel
//
void setupADCContinuous(uint32_t adcBase, uint32_t channel)
{
uint16_t acqps;

//
// Determine acquisition window (in SYSCLKS) based on resolution
//
if(EX_ADC_RESOLUTION == 12)
{
acqps = 30; // 150ns
}
else //resolution is 16-bit
{
acqps = 64; // 320ns
}
//
// - NOTE: A longer sampling window will be required if the ADC driving
// source is less than ideal (an ideal source would be a high bandwidth
// op-amp with a small series resistance). See TI application report
// SPRACT6 for guidance on ADC driver design.
// - NOTE: A slightly longer S+H window is used with 12-bit resolution to
// ensure the data collection loop can keep up with the ADC
//

//
// Configure SOCs channel no. & acquisition window.
//
ADC_setupSOC(adcBase, ADC_SOC_NUMBER0, ADC_TRIGGER_SW_ONLY,
(ADC_Channel)channel, acqps);
ADC_setupSOC(adcBase, ADC_SOC_NUMBER1, ADC_TRIGGER_SW_ONLY,
(ADC_Channel)channel, acqps);
ADC_setupSOC(adcBase, ADC_SOC_NUMBER2, ADC_TRIGGER_SW_ONLY,
(ADC_Channel)channel, acqps);
ADC_setupSOC(adcBase, ADC_SOC_NUMBER3, ADC_TRIGGER_SW_ONLY,
(ADC_Channel)channel, acqps);
ADC_setupSOC(adcBase, ADC_SOC_NUMBER4, ADC_TRIGGER_SW_ONLY,
(ADC_Channel)channel, acqps);
ADC_setupSOC(adcBase, ADC_SOC_NUMBER5, ADC_TRIGGER_SW_ONLY,
(ADC_Channel)channel, acqps);
ADC_setupSOC(adcBase, ADC_SOC_NUMBER6, ADC_TRIGGER_SW_ONLY,
(ADC_Channel)channel, acqps);
ADC_setupSOC(adcBase, ADC_SOC_NUMBER7, ADC_TRIGGER_SW_ONLY,
(ADC_Channel)channel, acqps);
ADC_setupSOC(adcBase, ADC_SOC_NUMBER8, ADC_TRIGGER_SW_ONLY,
(ADC_Channel)channel, acqps);
ADC_setupSOC(adcBase, ADC_SOC_NUMBER9, ADC_TRIGGER_SW_ONLY,
(ADC_Channel)channel, acqps);
ADC_setupSOC(adcBase, ADC_SOC_NUMBER10, ADC_TRIGGER_SW_ONLY,
(ADC_Channel)channel, acqps);
ADC_setupSOC(adcBase, ADC_SOC_NUMBER11, ADC_TRIGGER_SW_ONLY,
(ADC_Channel)channel, acqps);
ADC_setupSOC(adcBase, ADC_SOC_NUMBER12, ADC_TRIGGER_SW_ONLY,
(ADC_Channel)channel, acqps);
ADC_setupSOC(adcBase, ADC_SOC_NUMBER13, ADC_TRIGGER_SW_ONLY,
(ADC_Channel)channel, acqps);
ADC_setupSOC(adcBase, ADC_SOC_NUMBER14, ADC_TRIGGER_SW_ONLY,
(ADC_Channel)channel, acqps);
ADC_setupSOC(adcBase, ADC_SOC_NUMBER15, ADC_TRIGGER_SW_ONLY,
(ADC_Channel)channel, acqps);

//
// Setup interrupt trigger for SOCs. ADCINT2 will trigger first 8 SOCs.
// ADCINT1 will trigger next 8 SOCs
//

//
// ADCINT2 trigger for SOC0-SOC7
//
ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER0,
ADC_INT_SOC_TRIGGER_ADCINT1);
ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER1,
ADC_INT_SOC_TRIGGER_ADCINT1);
ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER2,
ADC_INT_SOC_TRIGGER_ADCINT1);
ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER3,
ADC_INT_SOC_TRIGGER_ADCINT1);
ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER4,
ADC_INT_SOC_TRIGGER_ADCINT1);
ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER5,
ADC_INT_SOC_TRIGGER_ADCINT1);
ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER6,
ADC_INT_SOC_TRIGGER_ADCINT1);
ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER7,
ADC_INT_SOC_TRIGGER_ADCINT1);

//
// ADCINT1 trigger for SOC8-SOC15
//
ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER8,
ADC_INT_SOC_TRIGGER_ADCINT1);
ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER9,
ADC_INT_SOC_TRIGGER_ADCINT1);
ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER10,
ADC_INT_SOC_TRIGGER_ADCINT1);
ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER11,
ADC_INT_SOC_TRIGGER_ADCINT1);
ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER12,
ADC_INT_SOC_TRIGGER_ADCINT1);
ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER13,
ADC_INT_SOC_TRIGGER_ADCINT1);
ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER14,
ADC_INT_SOC_TRIGGER_ADCINT1);
ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER15,
ADC_INT_SOC_TRIGGER_ADCINT1);

//
// Disable Interrupt flags
//
ADC_disableInterrupt(adcBase, ADC_INT_NUMBER1);
// ADC_disableInterrupt(adcBase, ADC_INT_NUMBER2);
// ADC_disableInterrupt(adcBase, ADC_INT_NUMBER3);
// ADC_disableInterrupt(adcBase, ADC_INT_NUMBER4);

//
// Enable continuous mode
//
ADC_enableContinuousMode(adcBase, ADC_INT_NUMBER1);
// ADC_enableContinuousMode(adcBase, ADC_INT_NUMBER2);
// ADC_enableContinuousMode(adcBase, ADC_INT_NUMBER3);
// ADC_enableContinuousMode(adcBase, ADC_INT_NUMBER4);

//
// Configure interrupt triggers
//
ADC_setInterruptSource(adcBase, ADC_INT_NUMBER1, ADC_SOC_NUMBER15);
// ADC_setInterruptSource(adcBase, ADC_INT_NUMBER1, ADC_SOC_NUMBER14);
// ADC_setInterruptSource(adcBase, ADC_INT_NUMBER1, ADC_SOC_NUMBER13); // good results
// ADC_setInterruptSource(adcBase, ADC_INT_NUMBER1, ADC_SOC_NUMBER5);
}

//
// End of file
//

当我输入5kHz 正弦波并使用不同的中断源时、我看到有干扰。 我希望  ADC_setInterruptSource (adcBase、ADC_INT_number1、ADC_SOC_NUMBER15); 不应出现任何干扰、因为它会确保所有转换完成。 这是图形的屏幕截图

谢谢 Vadim

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

    您好!  

    由于假期,专家不在办公室。 请在星期二之前回复。

    谢谢。

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

    您好 Vadim、

    如果所有16个 SOC 只使用1个中断、则在开始转换下一组 SOC 之前、没有足够的时间转换这些值。 您查看的示例提供了触发所有16个 SOC (至少2个中断)的正确方法、这样就有足够的时间在读取其他 SOC 的结果的同时转换 SOC。

    此外、作为后续说明、请使用 Instert -> Code 方法复制和粘贴代码。 您在此处插入代码的方式会使读取变得不必要、我将无法轻松找到您所谈论的内容。

    此致、

    Omer Amir

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

    您好、Omer、

    感谢您的支持。 我知道 ADC SOC 根据轮循方法具有优先级。 我理解这一点、因为在前一个转换未完成之前、当前转换将不会开始。

    在这种情况下、分配给最后一个 SOC15的中断应触发第一个通道的第一个 SOC0? 因此,如果我的 ePWM 时基大于连续16 SOC*75 ns,我应该看不到任何干扰?

    我认为我所做的与示例相同、A2输入的示例中具有16个连续通道与4个通道之间存在差异。

    //! This example sets up ePWM1 to periodically trigger a set of conversions on
    //! ADCA including multiple SOCs that all convert A2 to achieve oversampling on
    //! A2. 
    //!
    //! ADCA Interrupt ISRs are used to read results of ADCA.
    //!
    //! \b External \b Connections \n
    //!  - A0, A1, A2 should be connected to signals to be converted.
    //!
    //! \b Watch \b Variables \n
    //! - \b adcAResult0 - Digital representation of the voltage on pin A0
    //! - \b adcAResult1 - Digital representation of the voltage on pin A1
    //! - \b adcAResult2 - Digital representation of the voltage on pin A2
    //!

    谢谢 Vadim

    PS 我尝试按照您的建议输入代码。

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

    您好 Vadim、

    [引用 userid="301556" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1187303/tms320f28377d-tms320f28377d/4481943 #4481943"]在这种情况下、分配给最后一个 SOC15的中断应触发第一个通道的第一个 SOC0?

    分配给 SOC 的中断将导致 SOC 触发、因此您可以使用1个中断来触发多个 SOC。 但是、代码的结构是这样的、这样中断1会触发全部16个 SOC。 当到达 ISR 或再次触发中断时、数据可能已就绪、也可能未就绪、SOC 可能没有时间在触发另一个中断之前转换结果(您可以监控中断溢出状态)。

    [引用 userid="301556" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1187303/tms320f28377d-tms320f28377d/4481943 #4481943"]因此,如果我的 EPWM 时基大于连续16 SOC*75 ns,我不应该看到任何干扰?

    如果您使用 ePWM 来触发 SOC、而不仅仅是中断或软件触发器、那么如果您使时基周期足够长、那就可以了。 但是、您拥有的代码看起来不像 ePWM 被用来触发 SOC、它看起来就像您正在使用 ADC 中断1。

    [引用 userid="301556" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1187303/tms320f28377d-tms320f28377d/4481943 #4481943"]我尝试按照您的建议输入代码[/quot]

    我已重新编排了您的原始帖子、以便更易于查看。

    此致、

    Omer Amir

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

    谢谢 Omer、

    因此 、如果我在中使用 ADC_TRIGGER_SW_ONLY

    ADC_setupSOC(adcBase, ADC_SOC_NUMBER0, ADC_TRIGGER_SW_ONLY,
    (ADC_Channel)channel, acqps);

    我必须定义触发 SOC ADC_INT_SOC_TRIGGER_ADCINT1的中断

    ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER0,
    ADC_INT_SOC_TRIGGER_ADCINT1);

    在原始示例中、16个 SOC 被分成2组、每个组由不同的中断触发。

    谢谢 Vadim

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

    您好 Vadim、

    是的、没错;原始示例使用了2组中断并使用 ADCINT1来触发一组 SOC、但这是因为使用1个中断不会在该中断再次触发之前提供足够的时间来转换结果。 如果使用 ePWM 或 CPU 计时器等触发器、则应能够将周期设置为足够长、以便能够转换结果(但在一定程度上、这将不会 尽可能快速连续地转换结果、 因为在延长转换时间时、您将丢失值)。
    此致、
    Omer Amir
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢 Omer 的快速响应!

    Vadim