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.

[参考译文] TMS320F28027:通过 ePWM 触发 ADC SOC、但通过 SPI 发送的数据偶尔会错误地移动

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/568999/tms320f28027-adc-soc-triggered-via-epwm-but-data-sent-over-spi-is-sporadically-shifted-incorrectly

器件型号:TMS320F28027

您好!

我正在尝试实现一种算法、该算法计算曲线下的面积、并通过 SPI 将该结果发送到 SPI 从设备。

ADC SOC 由 ePWM1触发、并由外部中断选通、即仅当中断为高电平时、才会读取 ADC 值并将其存储在数组中。 一旦中断为低电平、数组中的值就会被读取并累加。 读取和处理整个阵列后、总和通过 SPI 发送、其中 F28027配置为 SPI 主器件。

但是、我遇到了一个奇怪的问题。 我在 SPI 从端输出右对齐数据、每次我闪存相同的代码时、它似乎会被4b/8b 等移位。 我觉得很奇怪。 现在、我只是在数组中输入一个值1、并在通过 SPI 发送之前对其进行求和。 您认为这是左对齐问题吗?! 如果该值始终发生变化、如何确定要移位的位数?

请查找以下代码:

uint16_t count = 1;

void system_init (void)
{
volatile int status = false;
volatile file *fid;

//初始化此应用程序所需的所有句柄
myAdc = ADC_init ((void *) ADC_base_ADDR、sizeof (ADC_Obj));
myClk = CLK_init ((void *) CLK_base_ADDR、sizeof (CLK_Obj));
myCpu = cpu_init ((void *) NULL、sizeof (cpu_Obj));
myFlash = flash_init ((void *) flash_base_ADDR、sizeof (flash_Obj));
myGpio = GPIO_init ((void *) GPIO_base_ADDR、sizeof (GPIO_Obj));
myPie = PI_init ((void *) PIE_BASE_ADDR、sizeof (PIE_Obj));
myPll = PLL_init ((void *) PLL_base_ADDR、sizeof (PLL_Obj));
mySci = SCI_init ((void *) SCIA_BASE_ADDR、sizeof (SCI_Obj));
myWdDog = WDOG_INIT ((void *) WDOG_BASE_ADDR、sizeof (WDOG_Obj));
mySpi = SPI_init ((void *) SPIA_BASE_ADDR、sizeof (SPI_Obj));
myComp = COMP_INIT ((void *) COMP2_base_ADDR、sizeof (COMP_Obj));
myCap = cap_init ((void *) CAPA_base_ADDR、sizeof (cap_Obj));
myPwm = PWM_init ((void *) PWM_ePWM1_base_ADDR、sizeof (PWM_Obj));

//执行基本系统初始化
WDOG_DISABLE (myWDog);

//启用时钟
CLK_enableAdcClock (myClk);
//clk_enableTbClockSync (myClk);
//clk_enableHrPwmClock (myClk);
CLK_enablePwmClock (myClk、PWM_NUMBER_1);
(*Device_cal)();

//选择内部振荡器1作为时钟源
CLK_setOscSrc (myClk、CLK_OscSrc_Internal);

//将 PLL 设置为 x10 /2、这将产生50MHz = 10MHz * 10/2
PLL_setup (myPll、PLL_Multiplier_12、PLL_DivideSelect_CLKIN_BY_2);

//--启用到外设的时钟
//禁用 PIE 和所有中断
PIE_DISABLE (myPie);
PI_DisableAllInts (myPie);
CPU_disableGlobalInts (myCpu);
CPU_clearIntFlags (myCpu);

//如果从闪存运行,则只将 RAM 复制到 RAM
#ifdef _flash
memcpy (&RamfuncsRunStart、&RamfuncsLoadStart、(size_t)&RamfuncsLoadSize);
#endif

//初始化 GPIO
//启用 XCLOCKOUT 以允许对振荡器1进行监控
GPIO_setMode (myGpio、GPIO_Number_18、GPIO_18_Mode_XCLKOUT);
CLK_setClkOutPreScaler (myClk、CLK_ClkOutPreScale_SYSCLKOUT_By_1);

//设置调试矢量表并启用 PIE
PI_setDebugIntVectorTable (myPie);
PIE_ENABLE (myPie);

// GPI05中断(DSP_INTn)
PI_registerPieIntHandler (myPie、PI_GroupNumber_1、PI_SubGroupNumber_4、(intVec_t)&XINT_ISR);
// TODO ADC ePWM
PI_registerPieIntHandler (myPie、PI_GroupNumber_10、PI_SubGroupNumber_1、(intVec_t)&ADC_ISR);
// TODO ADC ePWM
//在 PIE 矢量表中注册中断处理程序
//PI_registerPieIntHandler (myPie、PI_GroupNumber_3、PI_SubGroupNumber_1、(intVec_t)&epwm1_ISR);

//初始化 GPIO
GPIO_init();

EALLOW;
GpioIntRegs.GPIOXINT1SEL.bit.GPIOSEL = 12;//将 GPIO 配置为 XINT1
EDIS;

//初始化 ADC
adc_init();

//初始化 PWM
// TODO ADC ePWM
PWM_init();

//初始化 SPI
spi_init();

//初始化 SPI FIFO
SPI_Fifo_init();

//在 Delta DSP 中将 GPIO12配置为 XINT1
#ifdef DELTADDSP
GPIO_setMode (myGpio、GPIO_Number_12、GPIO_12_Mode_generalpurpose);
GPIO_setDirection (myGpio、GPIO_Number_12、GPIO_Direction_Input);
GPIO_setPullUp (myGpio、GPIO_Number_12、GPIO_PULLUP_Enable);
GPIO_setExtInt (myGpio、GPIO_Number_12、CPU_ExtIntNumber_1);
#endif

//启用 PIE - XINT1
PI_enableInt (myPie、PI_GroupNumber_1、PI_InterruptSource_XINT_1);
//启用 PIE - ADCINT1
// TODO 调试
PI_enableInt (myPie、PI_GroupNumber_10、PI_InterruptSource_ADCINT_10_1);
//启用 CPU - INT1
CPU_enableInt (myCpu、CPU_IntNumber_1);
//启用 CPU - INT10
CPU_enableInt (myCpu、CPU_IntNumber_10);
//启用 ePWM - INT1
CPU_enableInt (myCpu、CPU_IntNumber_3);

//启用全局中断和更高优先级的实时调试事件
cpu_enableGlobalInts (myCpu);
CPU_enableDebugInt (myCpu);

//设置中断极性
PI_setExtIntPolarity (myPie、CPU_ExtIntNumber_1、PI_ExtIntPolarity_RisingAndFallingEdge);
//启用 XINT1
PI_enableExtInt (myPie、CPU_ExtIntNumber_1);
// TODO ADC ePWM
PIE_enablePwmInt (myPie、PWM_NUMBER_1);

//将闪存 OTP 等待状态设置为最小值。 这很重要
//以获得温度转换功能的性能。
FLASH_setup (myFlash);

//将 STDOUT 重定向到 SCI
状态= add_device ("scia"、_ssa、SCI_open、SCI_close、SCI_read、 SCI_WRITE、SCI_LSEEK、SCI_unlink、SCI_rename);
FID = fopen ("scia"、"w");
freopen ("scia:"、"w"、stdout);
setvbuf (stdout、NULL、_IONBF、0);
}

void adc_init ()
{
adc_enableBandGap (myAdc);
ADC_enableRefBuffers (myAdc);
ADC_POWERUP (myAdc);
ADC_ENABLE (myAdc);
ADC_setVoltRefSrc (myAdc、ADC_VoltageRefSrc_Int);

EALLOW;
//AdcRegs.ADCCTL1.bit.ADCBGPWD = true;//启用 ADC 中的带隙
AdcRegs.ADCCTL1.bit.INTPULSEPOS = true;// EOC 中断在完成前触发1个周期

AdcRegs.ADCSOC0CTL.bit.CHSEL = 4;//设置 SOC0以采样 A4
AdcRegs.ADCSOC1CTL.bit.CHSEL = 4;//将 SOC1设置为采样 A4
AdcRegs.ADCSOC0CTL.bit.ACQPS = 6;//将 SOC0 ACQPS 设置为7 ADCCLK
AdcRegs.ADCSOC1CTL.bit.ACQPS = 6;//将 SOC1 ACQPS 设置为7 ADCCLK
// TODO 调试
AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5;// 0:SW;1:CPUTimer0;5:PWM1。 触发源设置为 EPWM1
AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 5;// 0:SW;1:CPUTimer0;5:PWM1。 触发源设置为 EPWM1

AdcRegs.INTSEL1N2.bit.INT1SEL = 1;//将 ADCINT1连接到 EOC1
AdcRegs.INTSEL1N2.bit.INT1E = 1; //启用 ADCINT1
AdcRegs.INTSEL1N2.bit.INT1CONT = 0;//清除标志 ADCINT1
//AdcRegs.INTSEL1N2.bit.INT2SEL = 1;//将 ADCINT1连接到 EOC1
//AdcRegs.INTSEL1N2.bit.INT2E = 1; //启用 ADCINT1
//AdcRegs.INTSEL1N2.bit.INT2CONT = 0;//清除标志 ADCINT1

//AdcRegs.ADCINTSOCSEL.bit.SOC0 = 0;// 0:没有 ADCINT 将触发 SOCx。 TRIGSEL 将触发 SOCx 1:ADCINT1
EDIS;
}

void PWM_init()
{
clk_disableTbClockSync (myClk);

//设置 PWM
PWM_setSyncMode (myPwm、PWM_SyncMode_CounterEqualZero);
PWM_setPeriod (myPwm、ePWM_PRD); //为 ePWM1设置周期
PWM_setCounterMode (myPwm、PWM_CounterMode_Up); //向上计数并启动
PWM_setCmpA (myPwm、ePWM_PRD/2); //设置比较 A 值
PWM_enableSockpulse (myPwm); //在组上启用 SOC
PWM_setSockAPulseSrc (myPwm、PWM_SockPulseSrc_CounterEqualCmpAcincr);//从 CPMA 向上计数选择 SOC
PWM_setSockAPeriod (myPwm、PWM_SockPeriod_FirstEvent); //在发生第一个事件时生成脉冲
PWM_enableInt (myPwm);

clk_enableTbClockSync (myClk);
}

void SPI_init()
{
CLK_enableSpiaClock (myClk);

//复位打开、上升沿、16位字符位
//待办事项区域
SPI_setCharLength (mySpi、SPI_CharLength _16_Bits);

//启用主控模式、正常相位、
//启用 TALK、禁用 SPI int。
// SPI_setMode (mySpi、SPI_Mode_Slave);
// TODO DSP SPI 主设备
SPI_setMode (mySpi、SPI_Mode_Master);
SPI_enableTx (mySpi);

//无延迟上升沿:POL=0;PHA = 0
//有延迟的上升沿: POL = 0;PHA = 1
//无延迟下降沿:POL=1;PHA = 0
//下降沿有延迟: POL = 1;PHA = 1
SPI_setClkPolarity (mySpi、0);
SPI_setClkPhase (mySpi、0);
SPI_setBaudRate (mySpi、SPI_BAUDRAATE_1_MBaud);
SPI_setSteInv (mySpi、SPI_SteInv_ActiveLow);
SPI_setTriWire (mySpi、SPI_TriWire_normalFourWire);

//从复位中撤回 SPI
SPI_disableLoopBack (mySpi);
SPI_enableInt (mySpi);
SPI_ENABLE (mySpi);

//设置断点以使断点不会干扰 xmission
SPI_setPriority (mySpi、SPI_Priority_freeRun);
}

void SPI_Fifo_init ()
{
//初始化 SPI FIFO 寄存器
SPI_enableChannels (mySpi);
SPI_enableFifoEnh (mySpi);

SPI_resetTxFifo (mySpi);
SPI_clearTxFifoInt (mySpi);
SPI_setTxFifoIntLevel (mySpi、SPI_FifoLevel 1_Word);
SPI_enableTxFifoInt (mySpi);

SPI_resetRxFifo (mySpi);
SPI_clearRxFifoInt (mySpi);
//SPI_setRxFifoIntLevel (mySpi、SPI_FifoLevel 1_Word);
//SPI_enableRxFifoInt (mySpi);
}

中断空 XINT_ISR (空)
{
if (GpioDataRegs.GPADAT.bit.GPIO12 == true)
{
//设置高于阈值标志
高于 se_thrsh = true;
//递增高于_ thrsh 计数器
count_above thrsh++;
}

if (GpioDataRegs.GPADAT.bit.GPIO12 == false)
{
//未设置超出阈值标志
高于 se_thrsh = false;
//递增到低于 thrsh 计数器
count_below _ thrsh++;
}

//清除 PIE - XINT1中断
PI_clearInt (myPie、PI_GroupNumber_1);
}

中断 void ADC_ISR (void)
{
if (if_above、thrsh = true)
{
PULSE_Ampl_wr = ADC_readResult (myAdc、ADC_ResultNumber_0);
PULSE_Ampl_wr = ADC_readResult (myAdc、ADC_ResultNumber_1);

if (no_of _samples < ISR_PULSE_buffer_LEN)
{
PULSE_Ampl[NO_OD_SAMPLES]=计数;
NO_OD_SAM_++;
}
}

if (is 高于 thrsh== false)
ifo_processed = true;

//清除 ADCINT1
ADC_clearIntFlag (myAdc、ADC_IntNumber_1);
//确认 PIE 中断
PI_clearInt (myPie、PI_GroupNumber_10);
}

void main ()
{
int i = 0;
//系统初始化
system_init();

//初始化 ADC 缓冲器
adc_buffer_init ();

//延迟系统
DSP28x_usDelay (1000);

//主程序循环-持续采样温度
for (;;){
//主循环

if (is_fifo_processed = true)
{
对于(i = no_of _samples; i > 0;i---)
{
SUM_ADC_PULSE_Val = SUM_ADC_PULSE_Val + PULSE_Ampl[i];
PULSE_Ampl[i]= false;
}

// SPI 传输
//GPIO_setLow (myGpio、GPIO_Number_19);
//pulse_Ampl_rd = SPI_Read (mySpi);
SUM_ADC_16b_val = SUM_ADC_PULSE_val;
SPI_WRITE (mySpi、SUM_ADC_16b_val << 4);
//GPIO_setHigh (myGpio、GPIO_Number_19);

//重置所有状态标志
SUM_ADC_PULSE_Val = false;
ifo_processed = false;
NO_OD_SAples = false;
is _abover_thrsh =-1;
}
}


  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    只是跟进一下、看看是否有人可能有任何想法? 谢谢!
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    您是在调用 SPI_write()时移动数据,因为它是算法的一部分,还是因为 SPITXBUF 寄存器要求数据左对齐而移动数据? 如果使用后一种、则没有必要-由于您使用的是16位字符长度、因此将发送整个 SPITXBUF 寄存器、因此您无需左移。

    或者、我是否不理解您要做的事情?

    谢谢、
    惠特尼