1120977_zh-CN

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

1120977_zh-CN

1120977_zh-CN

回复:DMA Ping-Pong应用<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

Overview

        Ping-Pong是一种特殊的已链接传输情况,由于与更复杂版本的已链接传输相比,它的使用通常更为频繁。

Ping-Pong传输通常至少使用两个缓冲区。不论何时,DMA操作都会载入或取消载入一个缓冲区。另一个缓冲区的操作与由软件控制的操作相反,这样在DMA控制器当前使用的缓冲区为满或空时,可将该缓冲区准备好以供使用。图1显示了从外设至存储器中两个缓冲区的Ping-Pong传输的描述符示例。

pastedImage_1.png

图1

实施细节

       为了将ADC转换结果连续传输到RAM,我将使用四个DMA描述符以Ping-Pong模式工作。

实现这一目标,如图2所示。

pastedImage_5.png

图 2 Ping-Pong 模式下的数据流

硬件介绍

  •         LPCXpressor54114 BoardOM13089

pastedImage_8.png

图3 LPCXpressor54114板

示例代码

      该代码基于periph_adc示例程序,使用SCTimer输出作为ADC的硬件触发信号,同时,ADC转换后的值会自动传输到指定的RAM区域。

#include "board.h"

#define SCT_PWM            LPC_SCT

#define NUM_BUFFERS 4
#define DMA_TRANSFER_SIZE 8
#define ADC_INPUT_CHANNEL 1

#define SCT_PWM_RATE   10000          /* PWM frequency 10 KHz */
#define SCT_PWM_PIN_OUT    7          /* COUT7 Generate square wave */
#define SCT_PWM_OUT        1          /* Index of OUT PWM */

uint16_t adcOut;

ALIGN(512) DMA_CHDESC_T ADC_TransferDescriptors[NUM_BUFFERS];


uint16_t CapturedData[32];

uint16_t DMA_Sum=0;

/**
 *
 * ADC IRQ not Used right now... Only for testing
 */
void ADC_SEQA_IRQHandler(void)
{
            /* If SeqA flags is set i.e. data in global register is valid then read it */
        Chip_GPIO_SetPinState(LPC_GPIO, 0, 6, true);
        //DEBUGOUT("ADC Output = %d\r\n", adcOut);
        Chip_GPIO_SetPinState(LPC_GPIO, 0, 6, false);
        Chip_ADC_ClearFlags(LPC_ADC,0xFFFFFFFF);
}


void DMA_IRQHandler(void)
{
        static uint16_t DMA_Sum=0;
        
        DMA_Sum++;
        
         if(DMA_Sum ==8)
         {
           DMA_Sum=4;
         }

       
     Chip_GPIO_SetPinState(LPC_GPIO, 0, 7,true);

     /* Rrror interrupt on channel 0? */
     if ((Chip_DMA_GetIntStatus(LPC_DMA) & DMA_INTSTAT_ACTIVEERRINT) != 0)
     {
          /* This shouldn't happen for this simple DMA example, so set the LED
             to indicate an error occurred. This is the correct method to clear
             an abort. */
          Chip_DMA_DisableChannel(LPC_DMA, DMA_CH0);
          while ((Chip_DMA_GetBusyChannels(LPC_DMA) & (1 << DMA_CH0)) != 0) {}
          Chip_DMA_AbortChannel(LPC_DMA, DMA_CH0);
          Chip_DMA_ClearErrorIntChannel(LPC_DMA, DMA_CH0);
          Chip_DMA_EnableChannel(LPC_DMA, DMA_CH0);
          Board_LED_Set(0, true);
     }

     Chip_GPIO_SetPinState(LPC_GPIO, 0,7,false);

     /* Clear DMA interrupt for the channel */
     LPC_DMA->DMACOMMON[0].INTA = 1;
}





     /***
      *      ____  __  __    _
      *     |  _ \|  \/  |  / \
      *     | | | | |\/| | / _ \
      *     | |_| | |  | |/ ___ \
      *     |____/|_|  |_/_/   \_\
      *     / ___|  ___| |_ _   _ _ __
      *     \___ \ / _ \ __| | | | '_ \
      *      ___) |  __/ |_| |_| | |_) |
      *     |____/ \___|\__|\__,_| .__/
      *                          |_|
      */
void DMA_Steup(void)
{
        DMA_CHDESC_T Initial_DMA_Descriptor;
        
        ADC_TransferDescriptors[0].source = (uint32_t)&LPC_ADC->SEQ_GDAT[0];
     ADC_TransferDescriptors[1].source = (uint32_t)&LPC_ADC->SEQ_GDAT[0];
     ADC_TransferDescriptors[2].source = (uint32_t)&LPC_ADC->SEQ_GDAT[0];
     ADC_TransferDescriptors[3].source = (uint32_t)&LPC_ADC->SEQ_GDAT[0];


     ADC_TransferDescriptors[0].dest = (uint32_t)&CapturedData[(0+1)*DMA_TRANSFER_SIZE-1];
     ADC_TransferDescriptors[1].dest = (uint32_t)&CapturedData[(1+1)*DMA_TRANSFER_SIZE-1];
     ADC_TransferDescriptors[2].dest = (uint32_t)&CapturedData[(2+1)*DMA_TRANSFER_SIZE-1];
     ADC_TransferDescriptors[3].dest = (uint32_t)&CapturedData[(3+1)*DMA_TRANSFER_SIZE-1];

     //The initial DMA desciptor is the same as the 1st transfer descriptor.   It
     //Will link into the 2nd of the main descriptors.

     ADC_TransferDescriptors[0].next = (uint32_t)&ADC_TransferDescriptors[1];
     ADC_TransferDescriptors[1].next = (uint32_t)&ADC_TransferDescriptors[2];
     ADC_TransferDescriptors[2].next = (uint32_t)&ADC_TransferDescriptors[3];

     //Link back to the 1st descriptor
     ADC_TransferDescriptors[3].next = (uint32_t)&ADC_TransferDescriptors[0];

     //For a test,  stop the transfers here.   The sine wave will look fine.
     //ADC_TransferDescriptors[3].next = 0;

     ADC_TransferDescriptors[0].xfercfg = (DMA_XFERCFG_CFGVALID |
                               DMA_XFERCFG_RELOAD  |
                               DMA_XFERCFG_SETINTA |
                               DMA_XFERCFG_WIDTH_16 |
                               DMA_XFERCFG_SRCINC_0 |
                               DMA_XFERCFG_DSTINC_1 |
                               DMA_XFERCFG_XFERCOUNT(DMA_TRANSFER_SIZE));

     ADC_TransferDescriptors[1].xfercfg = ADC_TransferDescriptors[0].xfercfg;
     ADC_TransferDescriptors[2].xfercfg = ADC_TransferDescriptors[0].xfercfg;

     ADC_TransferDescriptors[3].xfercfg = (DMA_XFERCFG_CFGVALID |
                               DMA_XFERCFG_RELOAD  |
                               DMA_XFERCFG_SETINTA |
                              DMA_XFERCFG_WIDTH_16 |
                              DMA_XFERCFG_SRCINC_0 |
                              DMA_XFERCFG_DSTINC_1 |
                              DMA_XFERCFG_XFERCOUNT(DMA_TRANSFER_SIZE));

     Initial_DMA_Descriptor.source = ADC_TransferDescriptors[0].source;
     Initial_DMA_Descriptor.dest =   ADC_TransferDescriptors[0].dest;
     Initial_DMA_Descriptor.next =  (uint32_t)&ADC_TransferDescriptors[1];
     Initial_DMA_Descriptor.xfercfg = ADC_TransferDescriptors[0].xfercfg;

     /* DMA initialization - enable DMA clocking and reset DMA if needed */
     Chip_DMA_Init(LPC_DMA);

     /* Enable DMA controller and use driver provided DMA table for current descriptors */
     Chip_DMA_Enable(LPC_DMA);
     Chip_DMA_SetSRAMBase(LPC_DMA, DMA_ADDR(Chip_DMA_Table));

     /* Setup channel 0 for the following configuration:
        - High channel priority
        - Interrupt A fires on descriptor completion */
     Chip_DMA_EnableChannel(LPC_DMA, DMA_CH0);
     Chip_DMA_EnableIntChannel(LPC_DMA, DMA_CH0);
     Chip_DMA_SetupChannelConfig(LPC_DMA, DMA_CH0,     //(DMA_CFG_PERIPHREQEN     |
                                   (DMA_CFG_HWTRIGEN        |
                                    DMA_CFG_TRIGBURST_BURST |
                                                         DMA_CFG_TRIGTYPE_EDGE   |
                                       DMA_CFG_TRIGPOL_LOW    |    //DMA_CFG_TRIGPOL_HIGH
                                       DMA_CFG_BURSTPOWER_1    |
                                    DMA_CFG_CHPRIORITY(0)
                                         )
                                       );


     //make sure ADC Sequence A interrupts is selected for for a DMA trigger
     LPC_INMUX->DMA_ITRIG_INMUX[0] = 0;

     /* Enable DMA interrupt */
     NVIC_EnableIRQ(DMA_IRQn);

     // The 1st descriptor is set up through the registers.

     /* Setup transfer descriptor and validate it */
     Chip_DMA_SetupTranChannel(LPC_DMA, DMA_CH0, &Initial_DMA_Descriptor);

     //Use the transfer configuration for our 4 main descriptors
     Chip_DMA_SetupChannelTransfer(LPC_DMA, DMA_CH0,     ADC_TransferDescriptors[0].xfercfg);
     Chip_DMA_SetValidChannel(LPC_DMA, DMA_CH0);      
}

void SCT_PWM_Generate(void)
{
         /* Initialize the SCT as PWM and set frequency */
     Chip_SCTPWM_Init(SCT_PWM);
     Chip_SCTPWM_SetRate(SCT_PWM, SCT_PWM_RATE);

     /* Setup Board specific output pin */
     Chip_IOCON_PinMuxSet(LPC_IOCON, 1, 14, IOCON_FUNC3 | IOCON_MODE_INACT | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);
     /* Use SCT0_OUT7 pin */
     Chip_SCTPWM_SetOutPin(SCT_PWM, SCT_PWM_OUT, SCT_PWM_PIN_OUT);

        
     /* Start with 50% duty cycle */
     Chip_SCTPWM_SetDutyCycle(SCT_PWM, SCT_PWM_OUT, Chip_SCTPWM_PercentageToTicks(SCT_PWM, 10));
     Chip_SCTPWM_Start(SCT_PWM);    
}


     /***
           *         _    ____   ____
           *        / \  |  _ \ / ___|
           *       / _ \ | | | | |
           *      / ___ \| |_| | |___
           *     /_/__ \_\____/ \____|
           *     / ___|  ___| |_ _   _ _ __
           *     \___ \ / _ \ __| | | | '_ \
           *      ___) |  __/ |_| |_| | |_) |
           *     |____/ \___|\__|\__,_| .__/
           *                          |_|
           */
void ADC_Steup(void)
{
    /*Set Asynch Clock to the Main clock*/
    LPC_SYSCON->ADCCLKSEL = 0;
    //Set the divider to 1 and enable.  note,  the HALT bit (30) and RESET (29) are not in the manual
    LPC_SYSCON->ADCCLKDIV = 0;
     /* Initialization ADC to 12 bit and set clock divide to 1 to operate synchronously at System clock */
    Chip_ADC_Init(LPC_ADC, ADC_CR_RESOL(3) | ADC_CR_CLKDIV(0)| ADC_CR_ASYNC_MODE);   
    //select ADC Channel 1 as input
    Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 30, IOCON_FUNC0 | IOCON_ANALOG_EN| IOCON_INPFILT_OFF);   
    LPC_ADC->INSEL = 0x01;
    Chip_ADC_SetupSequencer(LPC_ADC,ADC_SEQA_IDX,                                            
                              ADC_SEQ_CTRL_SEQ_ENA |
                              ADC_SEQ_CTRL_CHANNEL_EN(ADC_INPUT_CHANNEL) |
                                                ADC_SEQ_CTRL_TRIGGER(2) |
                              ADC_SEQ_CTRL_HWTRIG_POLPOS |
                                                ADC_SEQ_CTRL_HWTRIG_SYNCBYPASS |
                              ADC_SEQ_CTRL_MODE_EOS |
                                                ADC_SEQ_CTRL_SEQ_ENA);
    /* Enable Sequence A interrupt */
    Chip_ADC_EnableInt(LPC_ADC, ADC_INTEN_SEQA_ENABLE);
    
    /* Calibrate ADC */
    if(Chip_ADC_Calibration(LPC_ADC) == LPC_OK) {
        /* Enable ADC SeqA Interrupt */
        NVIC_EnableIRQ(ADC_SEQA_IRQn);
    }
    else {
        DEBUGSTR("ADC Calibration Failed \r\n");
        return ;
    }
}

int main(void)
{
  
    SystemCoreClockUpdate();
    Board_Init();
    
    DMA_Steup();
    ADC_Steup();
    SCT_PWM_Generate();

    
    while(1)
    {}
    
}
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

 验证

  1.     构建项目,然后点击pastedImage_25.png进行调试;
  2.        生成正弦波:1 kHz,幅度:0~2 V,通过J9_1(P0_30-ADC1)将波形输入至ADC;
  3.        设置断点(图4),用于观察ADC转换值CapturedData[32];

pastedImage_26.png

图4

                       4. 为了验证结果,我收集了多个数据组,并使用Excel将这些数据制成图表进行检查。图6是一个示例。

pastedImage_32.png

图5

pastedImage_33.png

图6

pastedImage_34.png

图7

pastedImage_35.png

图8

LPC54xxxLPCOpen回复:DMA Ping-Pong 应用程序

您好@jeremyzhou

我遵循您的实现并进行了修改,以更新LPC54102上SCT块的匹配寄存器。我正在向该寄存器输入正弦波的振幅值以生成脉宽调制(SPWM)。


程序有些正常运行,但我注意到程序忽略了查找表(LUT)中的一些值。您对如何解决这个问题有什么建议吗?


我将添加部分代码。

/*****************************************CODE************************************************/

#include "board.h"
 
#define SCT_PWM LPC_SCT
#define DMA_TRANSFER_SIZE 64
 
#define SCT_PWM_RATE  10000          /* PWM frequency 10 KHz */
#define SCT_PWM_PIN_OUT 4 /* COUT7 生成方波 */
#define SCT_PWM_OUT 1 /* OUT PWM 的索引 */
 
 
static CHIP_SYSCON_PLLCLKSRC_T curr_src=SYSCON_PLLCLKSRC_RTC;
static volatile bool dmaDone = false;static int fmode;
static int fmode;
 
 
 
#define TABLE_SIZE 128
uint16_t sine_table[TABLE_SIZE] __attribute__((aligned(16))) = {
610, 610, 610, 610, 610, 610, 610, 610,
859, 859, 859, 859, 859, 859, 859, 859,
1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064,
1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191,
1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139,
969, 969, 969, 969, 969, 969, 969, 969,
737, 737, 737, 737, 737, 737, 737, 737,
483, 483, 483, 483, 483, 483, 483, 483,
252, 252, 252, 252, 252, 252, 252, 252,
82, 82, 82, 82, 82, 82, 82, 82,
3, 3, 3, 3, 3, 3, 3, 3,
30, 30, 30, 30, 30, 30, 30, 30,
157, 157, 157, 157, 157, 157, 157, 157,
362, 362, 362, 362, 362, 362, 362, 362,
610, 610, 610, 610, 610, 610, 610, 610
 
};
 
 
ALIGN(512) DMA_CHDESC_T SCT_TransferDescriptors1,SCT_TransferDescriptors2;
uint16_t CapturedData[32];
uint16_t DMA_Sum=0;



void DMA_IRQHandler(void)
{
  
     /* Rrror interrupt on channel 0? */
     if ((Chip_DMA_GetIntStatus(LPC_DMA) & DMA_INTSTAT_ACTIVEERRINT) != 0)
     {
          /* This shouldn't happen for this simple DMA example, so set the LED
             to indicate an error occurred. 这是清除的正确方法
中止。*/
          Chip_DMA_DisableChannel(LPC_DMA, DMA_CH0);
          while ((Chip_DMA_GetBusyChannels(LPC_DMA) & (1 << DMA_CH0)) != 0) {}
          Chip_DMA_AbortChannel(LPC_DMA, DMA_CH0);
          Chip_DMA_ClearErrorIntChannel(LPC_DMA, DMA_CH0);
          Chip_DMA_EnableChannel(LPC_DMA, DMA_CH0);
          Board_LED_Set(0, true);
     }
 
 
 
     /* Clear DMA interrupt for the channel */
LPC_DMA->DMACOMMON[0].INTA = 1;
}
 
 
void DMA_Setup(void)
{
    SCT_TransferDescriptors1.source = (uint32_t)(&sine_table[TABLE_SIZE-1]);
    SCT_TransferDescriptors1.dest = (uint32_t)(&(LPC_SCT->MATCHREL[1].U));
SCT_TransferDescriptors1.next = (uint32_t)(&SCT_TransferDescriptors2);
SCT_TransferDescriptors1.xfercfg = DMA_XFERCFG_CFGVALID | DMA_XFERCFG_SETINTA |
                                      DMA_XFERCFG_WIDTH_16 | DMA_XFERCFG_SRCINC_1 | DMA_XFERCFG_DSTINC_0 |
                                      DMA_XFERCFG_XFERCOUNT((TABLE_SIZE)) | DMA_XFERCFG_RELOAD;
 
    // Configuración del segundo descriptor (igual que el primero, pero enlazando de regreso al primero)
SCT_TransferDescriptors2.source = (uint32_t)(&sine_table[(TABLE_SIZE-1)]);
    SCT_TransferDescriptors2.dest = (uint32_t)(&(LPC_SCT->MATCHREL[1].U));
SCT_TransferDescriptors2.next = (uint32_t) (&SCT_TransferDescriptors1);
SCT_TransferDescriptors2.xfercfg = DMA_XFERCFG_CFGVALID | DMA_XFERCFG_SETINTA |
                                      DMA_XFERCFG_WIDTH_16 | DMA_XFERCFG_SRCINC_1 | DMA_XFERCFG_DSTINC_0 |
                                      DMA_XFERCFG_XFERCOUNT((TABLE_SIZE)) | DMA_XFERCFG_RELOAD;
 
 
 
 
    /* DMA initialization - enable DMA clocking and reset DMA if needed */
    Chip_DMA_Init(LPC_DMA);
 
    /* Enable DMA controller and use driver provided DMA table for current descriptors */
    Chip_DMA_Enable(LPC_DMA);
    Chip_DMA_SetSRAMBase(LPC_DMA, DMA_ADDR(Chip_DMA_Table));
 
    /* Setup channel for the given configurations */
    Chip_DMA_EnableChannel(LPC_DMA, DMA_CH0);
    Chip_DMA_EnableIntChannel(LPC_DMA, DMA_CH0);
Chip_DMA_SetupChannelConfig(LPC_DMA, DMA_CH0, (DMA_CFG_HWTRIGEN | DMA_CFG_TRIGBURST_BURST | DMA_CFG_TRIGTYPE_LEVEL | DMA_CFG_TRIGPOL_LOW  | DMA_CFG_CHPRIORITY(0)));
 
 
 
    /* Set ADC Sequence A interrupts for a DMA trigger */
    LPC_INMUX->DMA_ITRIG_INMUX[0] = DMATRIG_SCT0_DMA0;
 
    /* Enable DMA interrupt */
    NVIC_EnableIRQ(DMA_IRQn);
 
    /* Setup the initial descriptor */
    Chip_DMA_SetupTranChannel(LPC_DMA, DMA_CH0, &SCT_TransferDescriptors1);
 
    /* Use the transfer configuration for our descriptors */
Chip_DMA_SetupChannelTransfer(LPC_DMA,DMA_CH0,SCT_TransferDescriptors1.xfercfg);
    Chip_DMA_SetValidChannel(LPC_DMA, DMA_CH0);
}
 
void SCT_PWM_Generate(void)
{
         /* Initialize the SCT as PWM and set frequency */
     Chip_SCTPWM_Init(SCT_PWM);
     Chip_SCTPWM_SetRate(SCT_PWM, SCT_PWM_RATE);
 
     /* Setup Board specific output pin */
     Chip_IOCON_PinMuxSet(LPC_IOCON, 1, 1, IOCON_FUNC3 | IOCON_MODE_INACT | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);
     /* Use SCT0_OUT7 pin */
     Chip_SCTPWM_SetOutPin(SCT_PWM, SCT_PWM_OUT, SCT_PWM_PIN_OUT);
 
        
/* 从50%占空比开始 */
     Chip_SCTPWM_SetDutyCycle(SCT_PWM, SCT_PWM_OUT, Chip_SCTPWM_PercentageToTicks(SCT_PWM, 10));
     Chip_SCTPWM_Start(SCT_PWM);    
}
 
 
int main(void)
{
  
    SystemCoreClockUpdate();
Board_Init();
    SystemCoreClockUpdate();
 
 
SCT_PWM_Generate();
    DMA_Setup();
    
 
    
    while(1)
    {}
    
}
回复:DMA Ping-Pong 应用程序<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

一个小问题。

该示例使用 SCT 触发 ADC。

对于我的代码,我使用了 CTIMER(match event)来触发 ADC 序列,这种方法似乎更简单,也更容易理解。

使用 SCT 有什么优势吗?

回复:DMA Ping-Pong 应用程序<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

能否将描述符定义为常量,并在编译时进行设置,即放在闪存而不是RAM中?

回复:DMA Ping-Pong 应用程序<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

Hi dingelen,

感谢您的回复。
根据上述描述,我仍然不清楚“struck”问题的实际情况,因此建议您进行更多测试并提供更详细的信息。

祝您有美好的一天。

BR,

Jeremy

回复:DMA Ping-Pong 应用程序<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

Hi Jeremy,

感谢您的快速回复。我认为使用LPC55也可以实现相同的功能,但我在这一部分遇到了一些困难:

     /* DMA initialization - enable DMA clocking and reset DMA if needed */
     Chip_DMA_Init(LPC_DMA);

     /* Enable DMA controller and use driver provided DMA table for current descriptors */
     Chip_DMA_Enable(LPC_DMA);
     Chip_DMA_SetSRAMBase(LPC_DMA, DMA_ADDR(Chip_DMA_Table));

     /* Setup channel 0 for the following configuration:
        - High channel priority
        - Interrupt A fires on descriptor completion */

     Chip_DMA_EnableChannel(LPC_DMA, DMA_CH0);
     Chip_DMA_EnableIntChannel(LPC_DMA, DMA_CH0);
     Chip_DMA_SetupChannelConfig(LPC_DMA, DMA_CH0,     //(DMA_CFG_PERIPHREQEN     |
                                   (DMA_CFG_HWTRIGEN        |
                                    DMA_CFG_TRIGBURST_BURST |
                                                         DMA_CFG_TRIGTYPE_EDGE   |
                                       DMA_CFG_TRIGPOL_LOW    |    //DMA_CFG_TRIGPOL_HIGH
                                       DMA_CFG_BURSTPOWER_1    |
                                    DMA_CFG_CHPRIORITY(0)
                                         )
                                       );


     //make sure ADC Sequence A interrupts is selected for for a DMA trigger
     LPC_INMUX->DMA_ITRIG_INMUX[0] = 0;

     /* Enable DMA interrupt */
     NVIC_EnableIRQ(DMA_IRQn);

     // The 1st descriptor is set up through the registers.

     /* Setup transfer descriptor and validate it */
     Chip_DMA_SetupTranChannel(LPC_DMA, DMA_CH0, &Initial_DMA_Descriptor);

     //Use the transfer configuration for our 4 main descriptors
     Chip_DMA_SetupChannelTransfer(LPC_DMA, DMA_CH0,     ADC_TransferDescriptors[0].xfercfg);
     Chip_DMA_SetValidChannel(LPC_DMA, DMA_CH0)

所有这些功能似乎在LPC55 SDK中都不可用。SDK 中的示例也仅使用某种轮询式启动/停止方式,而非自动运行的设置。(请参见 lpcxpresso55s69_lpadc_dma 示例)

如果这最后一部分能够被移植,那就太好了。

谢谢!

Tom

回复:DMA Ping-Pong 应用程序<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

Hi dingelen,

感谢您对演示的兴趣。
1) 是否有适用于 LPC55 系列的相同示例?
--在审查了RM后,我发现LPC55xx系列也支持Ping-Pong功能,因此该示例可以移植到该系列。

pastedImage_1.png

祝您有美好的一天。

BR,

Jeremy

回复:DMA Ping-Pong 应用程序<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

超级示例。比SDK里的好多了... 谢谢!

LPC55系列是否有相同的示例可用?与LPC54系列相比,DMA的设置方式似乎有一些不同。

Tags (1)
No ratings
Version history
Last update:
‎01-05-2026 02:06 AM
Updated by: