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.

[参考译文] F28377D-SEP:SPI DMA 初始化问题

Guru**** 2812305 points

Other Parts Discussed in Thread: C2000WARE, ADS7028, SYSCONFIG

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1605863/f28377d-sep-spi-dma-intialization-issue

器件型号: F28377D-SEP
主题中讨论的其他器件: ADS7028、C2000WARE、 SysConfig

我想通过 SPI 读取 ADS7028 的 4 个通道、并以每个 10kHz PWM ISR 将这些数据存储在 DMA 中。 但是、SPI 没有像 DMA 一样被触发。 CLK 和 CS 始终为低电平。  

这是我的代码片段 — GSRAM 中的 DMA 缓冲器
#pragma DATA_SECTION (sData、“ramgs0")“);
pragma DATA_SECTION (Rdata、“ramgs0")“);
uint16_t sData[NUM_ADC_channels];
uint16_t RDATA[NUM_ADC_channels];

主循环--

void main (void)

  uint16_t i;

  设备初始化 ();
  device_initGPIO();
  interrupt_initModule();
  Interrupt_initVectorTable();

  SysCtl_enablePeripheral (SYSCTL_PERIPH_CLK_DMA);

  DINT;

  对于 (I=0;I<NUM_ADC_CHANNES;I++){
    sData[i]= 0xAAAA;
    RDATA[i]= 0x0000;
  }

  InitSystem();
  InitSPI_AND_ADS7028 ();
  InitDMA();

  INTERRUPT_REGISTER (INT_EPWM1、&INT_EPWM1_ISR);
  INTERRUPT_REGISTER (INT_DMA_CH1、&INT_DMA_CH1_ISR);

  SysCtl_disablePeripheral (SYSCTL_PERIPH_CLK_TBCLKSYNC);
  InitEPWM_Trigger();
  SysCtl_enablePeripheral (SYSCTL_PERIPH_CLK_TBCLKSYNC);
  INTERRUPT_ENABLE (INT_EPWM1);
  INTERRUPT_ENABLE (INT_DMA_CH1);
  EINT;
  ERTM;

  while (1)
  {
    //调试循环
  }
}
SPI 和 ADS7028 初始化--

void InitSPI_AND_ADS7028 (void)

  SPI_disableModule (ADS_SPI_BASE);
  SPI_setConfig (ADS_SPI_BASE、DEVICE_LSPCLK_FREQ、SPI_PROT_POL0PHA1、SPI_MODE_MASTER、1000000 8);
  SPI_enableModule (ADS_SPI_BASE);
  spi_disableFIFO (ADS_SPI_BASE);

  ADS_Write (0x01、0x01);//复位器件
  device_delay_US (10000);

  //寄存器 0x12(序列选择)
  //选择通道 1、2、3、4:
  //二进制:0001 1110 = 0x1E
  ADS_Write (0x12、0x1E);

  //启用自动序列模式(寄存器 0x10 = 0x11)
  ADS_Write (0x10、0x11);

  SPI_disableModule (ADS_SPI_BASE);
  SPI_setConfig (ADS_SPI_BASE、DEVICE_LSPCLK_FREQ、SPI_PROT_POL0PHA1、SPI_MODE_MASTER、ADS_SPI_SPEED 16);
  SPI_enableFIFO (ADS_SPI_BASE);
  SPI_resetTxFIFO (ADS_SPI_BASE);
  SPI_resetRxFIFO (ADS_SPI_BASE);

  SPI_setFIFO InterruptLevel (ADS_SPI_BASE、SPI_FIFO_TX0、SPI_FIFO_RX1);
  SPI_enableInterrupt (ADS_SPI_BASE、SPI_INT_TXFF | SPI_INT_RXFF);
  SPI_enableModule (ADS_SPI_BASE);
}
DMA 初始化--

void InitDMA (void)

  dma_initController();

 //-- RX 通道 (Ch1)--
  DMA_configAddresses (DMA_CH1_BASE、(const void *) RDATA、(const void *)(ADS_SPI_BASE + SPI_O_RXBUF);
  DMA_configBurst (DMA_CH1_BASE、1、0、1);
  DMA_configTransfer (DMA_CH1_BASE、NUM_ADC_CHANNES、0、0);
  DMA_configMode (DMA_CH1_BASE、DMA_TRIGGER_SPICRX、DMA_CFG_OneShot_DISABLE | DMA_CFG_CONTINULE_DISABLE | DMA_CFG_SIZE_16BIT);
  DMA_setInterruptMode (DMA_CH1_BASE、DMA_INT_AT_END);
  DMA_enableInterrupt (DMA_CH1_BASE);
  DMA_enableTrigger (DMA_CH1_BASE);

  //-- TX 通道 (Ch2)--
  DMA_configAddresses (DMA_CH2_BASE、(const void *)(ADS_SPI_BASE + SPI_O_TXBUF)、(const void *) sData);
  DMA_configBurst (DMA_CH2_BASE、1、1、0);
  DMA_configTransfer (DMA_CH2_BASE、NUM_ADC_CHANNES、0、0);  DMA_configMode (DMA_CH2_BASE、 DMA_TRIGGER_SPICTX、DMA_CFG_OneShot_enable | DMA_CFG_CONTINUE_DISABLE | DMA_CFG_SIZE_16BIT);
  DMA_enableTrigger (DMA_CH2_BASE);
}

中断--

__中断无效 INT_EPWM1_ISR (void)

  if (SPI_isBusy (ADS_SPI_BASE)){
    SPI_ERROR_COUNT++;
    EPWM_clearEventTriggerInterruptFlag (EPWM1_BASE);
    INTERRUPT_CLEARACKGROUP (INTERRUPT_ACK_GROUP3);
    返回;
  }
  EPWM_ISR_COUNT++;
  //重置 FIFO
  SPI_resetRxFIFO (ADS_SPI_BASE);
  SPI_resetTxFIFO (ADS_SPI_BASE);
  //将 CS 置为有效
  GPIO_writePin (ADS_CS_GPIO、0);
  //启动 DMA
  DMA_startChannel (DMA_CH1_BASE);
  DMA_startChannel (DMA_CH2_BASE);
  //强制触发器 (Kickstart)
  DMA_forceTrigger (DMA_CH2_BASE);
  EPWM_clearEventTriggerInterruptFlag (EPWM1_BASE);
  INTERRUPT_CLEARACKGROUP (INTERRUPT_ACK_GROUP3);
}

__interrupt void INT_DMA_CH1_ISR (void)

  int i;
  uint16_t RAW_DATA;
  while (SPI_isBusy (ADS_SPI_BASE));
  GPIO_writePin (ADS_CS_GPIO、1);
  DMA_ISR_COUNT++;
  对于 (I = 0;I < NUM_ADC_CHANNES;I++){
    RAW_DATA = RDATA[i];
    ADC_VOLTS[i]=(float)((RAW_DATA >> 4) 且 0x0FFF)*(3.3f / 4096.0f);
  }
  INTERRUPT_CLEARACKGROUP (INTERRUPT_ACK_group7);
}

请使用 SPICTX 检查 DMA 是否存在任何时序问题或初始化错误。

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

    您好、Souradeep、

    您是否可以尝试从 C2000ware 运行名为 SPI_EX5_LOOPBACKUP_DMA 的 SPI+DMA 示例? 我们不为 F2837xD 提供此示例、但在 C2000ware 中为其他器件提供了此示例 — 例如 F28004x(路径:[C2000ware install]/driverlib/f28004x/examples/spi)、SPI 和 DMA 实现将相同。 您是否可以尝试将示例移植到 F2837xD 并在您的设置中对其进行测试? 如果可以使该示例正常工作、最好将其用作编写代码的起点。

    此致、

    Delaney

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

    你好,我已经通过了这个文件,不知何故移植不能正常工作.  
    我有以下工作代码、可以正确配置 ADS7028、并能够读取和写入正确的数据。 但是、我想为 SPI 添加 DMA、以减轻 CPU 负载。 如果您可以帮助我完成正确的初始化并遵循相关指南、这会很有帮助。   

    #include “driverlib.h"</s>“
    #include “device.h"</s>“

    define ADS_SPI_BASE spic_base
    #define ADS_CS_GPIO 53
    #define ADS_CS_PIN_CONFIG GPIO_53_GPIO53
    #define NUM_ADC_CHANNES 4.
    // ADS7028 操作码
    #define OPCODE_WRITE 0x08
    #define OPCODE_READ 0x10
    #define OPCODE_NOP 0x00

    易失性 uint32_t ISR_COUNT = 0;
    uint16_t ADC_RAW[8]、channel_id[4];

    悬空 ADC_VOLTS[8];
    //函数原型
    无效初始系统 (void);
    void InitSPI_AND_ADS7028 (void);
    void InitEPWM_Trigger (void);
    void ADS_Write (uint8_t addr、uint8_t d);
    uint16_t ADS7028_ReadData (void);
    __interrupt void INT_EPWM1_ISR (void);

    void main (void)

    设备初始化 ();
    device_initGPIO();
    interrupt_initModule();
    Interrupt_initVectorTable();

    InitSystem();
    InitSPI_AND_ADS7028 ();

    INTERRUPT_REGISTER (INT_EPWM1、&INT_EPWM1_ISR);

    InitEPWM_Trigger();

    INTERRUPT_ENABLE (INT_EPWM1);
    EINT;
    ERTM;

    while (1)

    }
    }

    无效初始系统 (void)

    // SPI-C GPIO
    GPIO_setPinConfig (GPIO_50_SPISIMOC);
    GPIO_setPadConfig (50、GPIO_PIN_TYPE_PULLUP);
    GPIO_setQualificationMode (50、GPIO_QUAL_ASYNC);

    GPIO_setPinConfig (GPIO_51_SPENSIC);
    GPIO_setPadConfig (51、GPIO_PIN_TYPE_PULLUP);
    GPIO_setQualificationMode (51、GPIO_QUAL_ASYNC);

    GPIO_setPinConfig (GPIO_52_SPICLKC);
    GPIO_setPadConfig (52、GPIO_PIN_TYPE_PULLUP);
    GPIO_setQualificationMode (52、GPIO_QUAL_ASYNC);

    //芯片选择
    GPIO_setPinConfig (ADS_CS_PIN_CONFIG);
    GPIO_setPadConfig (ADS_CS_GPIO、GPIO_PIN_TYPE_STD);
    GPIO_setDirectionMode (ADS_CS_GPIO、GPIO_DIR_MODE_OUT);
    GPIO_writePin (ADS_CS_GPIO、1);
    }

    void InitSPI_AND_ADS7028 (void)

    SPI_disableModule (ADS_SPI_BASE);
    SPI_setConfig (ADS_SPI_BASE、DEVICE_LSPCLK_FREQ、SPI_PROT_POL0PHA1、SPI_MODE_MASTER、1000000 8);
    SPI_enableModule (ADS_SPI_BASE);
    spi_disableFIFO (ADS_SPI_BASE);

    ADS_Write (0x01、0x01);//复位
    device_delay_US (10000);
    ADS_Write (0x05、0x00);
    DEVICE_DELAY_US (1);
    ADS_Write (0x02、0x10);//启用 4 位通道 ID
    //选择通道 1、2、3、4(掩码 0x1E:0000 1111)
    ADS_Write (0x12、0x0F);
    //启动自动序列
    ADS_Write (0x10、0x11);

    SPI_disableModule (ADS_SPI_BASE);
    SPI_setConfig (ADS_SPI_BASE、DEVICE_LSPCLK_FREQ、SPI_PROT_POL0PHA1、SPI_MODE_MASTER、1000000 16);
    SPI_enableFIFO (ADS_SPI_BASE);
    SPI_resetTxFIFO (ADS_SPI_BASE);
    SPI_resetRxFIFO (ADS_SPI_BASE);
    SPI_enableModule (ADS_SPI_BASE);

    ADS7028_ReadData();
    }

    void ADS_Write (uint8_t addr、uint8_t d)

    GPIO_writePin (ADS_CS_GPIO、0);DEVICE_DELAY_US (1);
    SPI_writeDataBlockingNonFIFO (ADS_SPI_BASE、(uint16_t)(opode_write << 8);
    SPI_readDataBlockingNonFIFO (ADS_SPI_BASE);
    SPI_writeDataBlockingNonFIFO (ADS_SPI_BASE、(uint16_t)(addr << 8));
    SPI_readDataBlockingNonFIFO (ADS_SPI_BASE);
    SPI_writeDataBlockingNonFIFO (ADS_SPI_BASE、(uint16_t)(d << 8));
    SPI_readDataBlockingNonFIFO (ADS_SPI_BASE);
    DEVICE_DELAY_US (1);GPIO_writePin (ADS_CS_GPIO、1);
    }
    uint16_t ADS7028_ReadData (void)

    uint16_t rawResult;

    GPIO_writePin (ADS_CS_GPIO、0);
    DEVICE_DELAY_US (1);//如果需要、建立时间

    SPI_writeDataNonBlocking (ADS_SPI_BASE、0x0000);

    while (SPI_getRxFIFOStatus (ADS_SPI_BASE)= SPI_FIFO_RX0){
    //等待数据
    }

    rawResult = SPI_readDataNonBlocking (ADS_SPI_BASE);

    DEVICE_DELAY_US (1);//如果需要、保持时间
    GPIO_writePin (ADS_CS_GPIO、1);

    返回 rawResult;
    }

    void InitEPWM_Trigger (void)// 10kHz 触发器

    SysCtl_disablePeripheral (SYSCTL_PERIPH_CLK_TBCLKSYNC);
    GPIO_setPinConfig (GPIO_0_EPWM1A);
    EPWM_setTimeBaseCounterMode (EPWM1_BASE、EPWM_COUNTER_MODE_UP);
    EPWM_setClockPrescaler (EPWM1_BASE、EPWM_CLOCK_DIVIDER_1、EPWM_HSCLOCK_DIVIDER_1);
    EPWM_setTimeBasePeriod (EPWM1_BASE、10000);
    EPWM_setInterruptSource (EPWM1_BASE、EPWM_INT_TBCTR_ZERO);
    EPWM_setInterruptEventCount (EPWM1_BASE、1);
    EPWM_enableInterrupt (EPWM1_BASE);
    SysCtl_enablePeripheral (SYSCTL_PERIPH_CLK_TBCLKSYNC);
    }

    __中断无效 INT_EPWM1_ISR (void)

    uint16_t temp_raw;//用于保存 16 位数据包的临时变量

    ISR_COUNT_+;

    //--通道 1 --
    temp_raw = ADS7028_ReadData ();//读取[Data][ID]
    channel_id[0]= temp_raw & 0x000F;//提取 ID(低 4 位)
    ADC_RAW[0]=(temp_raw >> 4) 且 0x0FFF;//移位和屏蔽以获取 12 位数据
    ADC_VOLTS[0]=(悬空)ADC_RAW[0]*(3.3f/4096.0f);

    //--通道 2 --
    temp_raw = ADS7028_ReadData ();
    channel_id[1]= temp_raw 和 0x000F;
    ADC_RAW[1]=(temp_raw >> 4) 且 0x0FFF;
    ADC_VOLTS[1]=(悬空)ADC_RAW[1]*(3.3f/4096.0f);

    //--通道 3--
    temp_raw = ADS7028_ReadData ();
    channel_id[2]= temp_raw 和 0x000F;
    ADC_RAW[2]=(temp_raw >> 4) 且 0x0FFF;
    ADC_VOLTS[2]=(悬空)ADC_RAW[2]*(3.3f/4096.0f);

    //--通道 4 --
    temp_raw = ADS7028_ReadData ();
    channel_id[3]= temp_raw 和 0x000F;
    ADC_RAW[3]=(temp_raw >> 4)& 0x0FFF;
    ADC_VOLTS[3]=(悬空)ADC_RAW[3]*(3.3f/4096.0f);

    EPWM_clearEventTriggerInterruptFlag (EPWM1_BASE);
    INTERRUPT_CLEARACKGROUP (INTERRUPT_ACK_GROUP3);
    }

    谢谢、
    Souradeep

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

    您好、Souradeep、

    为了移植示例、我建议为 F2837xD 导入 empty_project、然后将 main.c 和.syscfg 文件的内容复制。 如果这样做、SysConfig 中是否会出现任何错误? 我认为除了更改 GPIO 设置外、唯一需要更改的是 GPIO 设置。 您能尝试一下并向我发送您遇到的任何错误吗?

    此致、

    Delaney