PWM VARIABLE DUTY CYCLE

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

PWM VARIABLE DUTY CYCLE

7,029 Views
leonidshigris
Contributor III

Hello,

I'm running the IMXRT1050-EVKB.

My target: build PWM variable duty cycle with DMA.

My  reference: SDK_2.6.0_EVKB-IMXRT1050,

example: inputcapture_outputpwm_dma. This examples describes, how to prepare the PWM with static duty cycle.

I can't find any info or example, how I  send to DMA the buffer ( includes array of different duty cycles ). I have to use DMA.

Also should config Counter repetition (Each x Update Requests, the TMR Channel X Duty Cycle changes to the next new value defined by the buffer). 

1. Is possibility to config PWM  with variable duty cycle with DMA ? If yes, what is the way to config this option?

2. Counter repetition.  Is there a part of timer configuration? Is there such an option at all? 

Best Regards,

Leon.

22 Replies

6,071 Views
farid_mabrouk
Contributor II

Hi Kerry,

I finally managed to solve my issue. I can tell you this Qtimer is the most confusing peripheral I had to use.

In the meantime, I need your input this thread https://community.nxp.com/thread/528579

Thank you!

0 Kudos

6,071 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Andre marcus,

   Thanks a lot for your effort.

   Could you please also share your solution? Do you use one DMA channel now?

   My method is using the Variable-Frequency PWM Mode, then configure the CMPLD1 and CMPLD2 in pair, then keep the different PWM has the same frequency.  The original customer wants to change the PWM duty for each continous PWM, that's why I use two channel to trigger and load the CMPLD1 and CMPLD2 seperated.

AT_NONCACHEABLE_SECTION_INIT(volatile uint16_t g_Cmpld1buf[10]) = {338, 300, 263, 225, 188, 150, 112, 75, 37, 188};//10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%,90%, 50%
AT_NONCACHEABLE_SECTION_INIT(volatile uint16_t g_Cmpld2buf[10]) = {37 , 75 , 112, 150, 187, 225, 263, 300, 338, 187};//10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%,90%, 50%

As the CMPLD1 and CMPLD2 is the different MUX channel, then I used two DMA mux channel:

pastedImage_1.png

Any updated information, please kindly let me know.

Best Regards,

Kerry

0 Kudos

6,086 Views
farid_mabrouk
Contributor II

hi Leonid and Kerry, 

How can your attached code for single Qtimer channel be modified and extended for two Qtimers GPIOs? Now I am using TMR1 timer0 and TMR1 timer1. I am having issues configuring both channels at the same time. The code below run normal only if a single channel is configured. I cant configure both channels in my code? any idea what the the issue below is?

Thank you in advance!

/* Qtimer configuration for PWM count*/
void QTimerPWM_Ch1config(void)
{
qtmr_config_t qtmrConfig;
edma_config_t userConfig2,userConfig1;

EDMA_Init(QTMR_DMA, &userConfig1);
EDMA_CreateHandle(&LED1_EDMA_Handle1, QTMR_DMA, 1);
EDMA_SetCallback(&LED1_EDMA_Handle1, EDMA_LED1_Callback1, NULL);

EDMA_Init(QTMR_DMA, &userConfig2);
EDMA_CreateHandle(&LED1_EDMA_Handle2, QTMR_DMA, 0);
EDMA_SetCallback(&LED1_EDMA_Handle2, EDMA_LED1_Callback2, NULL);

/*
* qtmrConfig.debugMode = kQTMR_RunNormalInDebug;
* qtmrConfig.enableExternalForce = false;
* qtmrConfig.enableMasterMode = false;
* qtmrConfig.faultFilterCount = 0;
* qtmrConfig.faultFilterPeriod = 0;
* qtmrConfig.primarySource = kQTMR_ClockDivide_2;
* qtmrConfig.secondarySource = kQTMR_Counter0InputPin;
*/

//added
QTMR_GetDefaultConfig(&qtmrConfig);
qtmrConfig.primarySource = kQTMR_ClockDivide_1;

DMAMUX_Init(QTMR_DMA_MUX);
DMAMUX_SetSource(QTMR_DMA_MUX, 1, QTMR_EDMA_REQUEST_LED1CMPLD2_SOURCE);
DMAMUX_EnableChannel(QTMR_DMA_MUX, 1);

DMAMUX_SetSource(QTMR_DMA_MUX, 0, QTMR_EDMA_REQUEST_LED1CMPLD1_SOURCE);
DMAMUX_EnableChannel(QTMR_DMA_MUX, 0);

QTMR_Init(QTMR_BASEADDR, QTMR_PWM_CHANNEL1, &qtmrConfig);

/* Generate a 800Khz PWM signal with 0% dutycycle */
QTMR_SetupPwm(QTMR_BASEADDR, QTMR_PWM_CHANNEL1, 800000, 0, false, QTMR_SOURCE_CLOCK / 1);

/* Enable comparator preload register 1 DMA */
QTMR_EnableDma(QTMR_BASEADDR, QTMR_PWM_CHANNEL1, kQTMR_ComparatorPreload1DmaEnable);
/* Enable comparator preload register 2 DMA */
QTMR_EnableDma(QTMR_BASEADDR, QTMR_PWM_CHANNEL1, kQTMR_ComparatorPreload2DmaEnable);
/* Start the counter */
QTMR_StartTimer(QTMR_BASEADDR, QTMR_PWM_CHANNEL1, kQTMR_PriSrcRiseEdge);

}


/* Qtimer configuration for PWM count*/
void QTimerPWM_Ch2config(void)
{
qtmr_config_t qtmrConfig;
edma_config_t userConfig2,userConfig1;


EDMA_Init(QTMR_DMA, &userConfig1);
EDMA_CreateHandle(&LED2_EDMA_Handle1, QTMR_DMA, 0);
EDMA_SetCallback(&LED2_EDMA_Handle1, EDMA_LED2_Callback1, NULL);

EDMA_Init(QTMR_DMA, &userConfig2);
EDMA_CreateHandle(&LED2_EDMA_Handle2, QTMR_DMA, 1);
EDMA_SetCallback(&LED2_EDMA_Handle2, EDMA_LED2_Callback2, NULL);

/*
* qtmrConfig.debugMode = kQTMR_RunNormalInDebug;
* qtmrConfig.enableExternalForce = false;
* qtmrConfig.enableMasterMode = false;
* qtmrConfig.faultFilterCount = 0;
* qtmrConfig.faultFilterPeriod = 0;
* qtmrConfig.primarySource = kQTMR_ClockDivide_2;
* qtmrConfig.secondarySource = kQTMR_Counter0InputPin;
*/

//added
QTMR_GetDefaultConfig(&qtmrConfig);
qtmrConfig.primarySource = kQTMR_ClockDivide_1;

DMAMUX_Init(QTMR_DMA_MUX);
DMAMUX_SetSource(QTMR_DMA_MUX, 0, QTMR_EDMA_REQUEST_LED2CMPLD2_SOURCE);
DMAMUX_EnableChannel(QTMR_DMA_MUX, 0);

DMAMUX_SetSource(QTMR_DMA_MUX, 1, QTMR_EDMA_REQUEST_LED2CMPLD1_SOURCE);
DMAMUX_EnableChannel(QTMR_DMA_MUX, 1);

QTMR_Init(QTMR_BASEADDR, QTMR_PWM_CHANNEL2, &qtmrConfig);

/* Generate a 800Khz PWM signal with 0% dutycycle */
QTMR_SetupPwm(QTMR_BASEADDR, QTMR_PWM_CHANNEL2, 800000, 0, false, QTMR_SOURCE_CLOCK / 1);

/* Enable comparator preload register 1 DMA */
QTMR_EnableDma(QTMR_BASEADDR, QTMR_PWM_CHANNEL2, kQTMR_ComparatorPreload1DmaEnable);
/* Enable comparator preload register 2 DMA */
QTMR_EnableDma(QTMR_BASEADDR, QTMR_PWM_CHANNEL2, kQTMR_ComparatorPreload2DmaEnable);
/* Start the counter */
QTMR_StartTimer(QTMR_BASEADDR, QTMR_PWM_CHANNEL2, kQTMR_PriSrcRiseEdge);

}

// a user function
void DataTransfer(uint8_t LEDport)
{

edma_transfer_config_t LED1transferConfig1, LED1transferConfig2;
edma_transfer_config_t LED2transferConfig1, LED2transferConfig2;


if(LEDport==1)
{
if((LED1_Transfer_Done1==true)&&(LED1_Transfer_Done2==true))
{

LED1_Transfer_Done1 = false;
LED1_Transfer_Done2 = false;

EDMA_PrepareTransfer(&LED1transferConfig1, (uint16_t *)&g_Cmpld1buf, 2,
(uint16_t *)&QTMR_BASEADDR->CHANNEL[QTMR_PWM_CHANNEL1].CMPLD1, 2, 2,484,
kEDMA_MemoryToPeripheral);
EDMA_SubmitTransfer(&LED1_EDMA_Handle1, &LED1transferConfig1);


EDMA_PrepareTransfer(&LED1transferConfig2, (uint16_t *)&g_Cmpld2buf, 2,
(uint16_t *)&QTMR_BASEADDR->CHANNEL[QTMR_PWM_CHANNEL1].CMPLD2, 2, 2,484,
kEDMA_MemoryToPeripheral);
EDMA_SubmitTransfer(&LED1_EDMA_Handle2, &LED1transferConfig2);


EDMA_StartTransfer(&LED1_EDMA_Handle2);
EDMA_StartTransfer(&LED1_EDMA_Handle1);
}
}
else if(LEDport==2)
{
if((LED2_Transfer_Done1==true)&&(LED2_Transfer_Done2==true))
{
LED2_Transfer_Done1 = false;
LED2_Transfer_Done2 = false;

EDMA_PrepareTransfer(&LED2transferConfig1, (uint16_t *)&g_Cmpld1buf, 2,
(uint16_t *)&QTMR_BASEADDR->CHANNEL[QTMR_PWM_CHANNEL2].CMPLD1, 2, 2,484,
kEDMA_MemoryToPeripheral);
EDMA_SubmitTransfer(&LED2_EDMA_Handle1, &LED2transferConfig1);


EDMA_PrepareTransfer(&LED2transferConfig2, (uint16_t *)&g_Cmpld2buf, 2,
(uint16_t *)&QTMR_BASEADDR->CHANNEL[QTMR_PWM_CHANNEL2].CMPLD2, 2, 2,484,
kEDMA_MemoryToPeripheral);
EDMA_SubmitTransfer(&LED2_EDMA_Handle2, &LED2transferConfig2);


EDMA_StartTransfer(&LED2_EDMA_Handle2);
EDMA_StartTransfer(&LED2_EDMA_Handle1);
}
}

}

0 Kudos

6,086 Views
farid_mabrouk
Contributor II

KerryHsu

I am trying to use same code you generated for above for a TMR1 channel2 (GPIO_B0_02), but apparently I am having issues with DMA configuration:

Here is how I defined my DMA:

#define QTMR_EDMA_REQUEST_LED1CMPLD2_SOURCE kDmaRequestMuxQTIMER1Cmpld1Timer2Cmpld2Timer3
#define QTMR_EDMA_REQUEST_LED1CMPLD1_SOURCE kDmaRequestMuxQTIMER1Cmpld1Timer3Cmpld2Timer2

#define QTMR_PWM_CHANNEL1                      kQTMR_Channel_2

/* Qtimer configuration for PWM count*/
void QTimerPWMconfig(void)
{
    qtmr_config_t qtmrConfig;
    edma_config_t userConfig2,userConfig1;

    EDMA_Init(QTMR_DMA, &userConfig1);
    EDMA_CreateHandle(&LED1_EDMA_Handle1, QTMR_DMA, 1);   
    EDMA_SetCallback(&LED1_EDMA_Handle1, EDMA_LED1_Callback1, NULL);

    EDMA_Init(QTMR_DMA, &userConfig2);
    EDMA_CreateHandle(&LED1_EDMA_Handle2, QTMR_DMA, 0);  
    EDMA_SetCallback(&LED1_EDMA_Handle2, EDMA_LED1_Callback2, NULL);

    /*
     * qtmrConfig.debugMode = kQTMR_RunNormalInDebug;
     * qtmrConfig.enableExternalForce = false;
     * qtmrConfig.enableMasterMode = false;
     * qtmrConfig.faultFilterCount = 0;
     * qtmrConfig.faultFilterPeriod = 0;
     * qtmrConfig.primarySource = kQTMR_ClockDivide_2;
     * qtmrConfig.secondarySource = kQTMR_Counter0InputPin;
     */

    //added
    QTMR_GetDefaultConfig(&qtmrConfig);
    qtmrConfig.primarySource = kQTMR_ClockDivide_1;

    DMAMUX_Init(QTMR_DMA_MUX);
    DMAMUX_SetSource(QTMR_DMA_MUX, 1, QTMR_EDMA_REQUEST_LED1CMPLD2_SOURCE);  
    DMAMUX_EnableChannel(QTMR_DMA_MUX, 1); //

    DMAMUX_SetSource(QTMR_DMA_MUX, 0, QTMR_EDMA_REQUEST_LED1CMPLD1_SOURCE);
    DMAMUX_EnableChannel(QTMR_DMA_MUX, 0);  //0

    QTMR_Init(QTMR_BASEADDR, QTMR_PWM_CHANNEL1, &qtmrConfig);

    /* Generate a 800Khz PWM signal with 0% dutycycle */
    QTMR_SetupPwm(QTMR_BASEADDR, QTMR_PWM_CHANNEL1, 800000, 0, false, QTMR_SOURCE_CLOCK / 1);

    /* Enable comparator preload register 1 DMA */
    QTMR_EnableDma(QTMR_BASEADDR, QTMR_PWM_CHANNEL1, kQTMR_ComparatorPreload1DmaEnable);
    /* Enable comparator preload register 2 DMA */
    QTMR_EnableDma(QTMR_BASEADDR, QTMR_PWM_CHANNEL1, kQTMR_ComparatorPreload2DmaEnable);
    /* Start the counter */
    QTMR_StartTimer(QTMR_BASEADDR, QTMR_PWM_CHANNEL1, kQTMR_PriSrcRiseEdge);

}

Can you please, let me know my configuration is wrong?

0 Kudos

6,075 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Andre marcus,

  What's the PWM wave on your related pin now?

Best Regards,

Kerry

0 Kudos

6,086 Views
leonidshigris
Contributor III

Hi Kerry,

Thank you for your support.

Currently I doesn't have an additional questions referred  to PWM issues.

Attached c file and snapshot. 

Best Regards,

Leon.

6,086 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Leonid Shigris,

   It's good to hear your problem is solved now.

  Thank you very much for your patience about this case, it really caused a lot of times.

  Now, could you please also tell your DFAE to mark the related case as resolved after the case is closed?  Thank you very much!


Have a great day,
Kerry

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

6,086 Views
farid_mabrouk
Contributor II

Thank you Kerry and Lionid for sharing the example code!

I tried using your code to generate variable duty cycle for my PWM. I some how managed to generate the desired duty cycles, but I have seen that the last duty cycle get repeated. Duty cycles should be 10%, 20% , 30 % and so on with an increment of 10% till it gets to 100%, but I noticed 100% get sent twice. Also I want to mention that I am using this GPIO only to output the PWM: IOMUXC_SetPinMux(
      IOMUXC_GPIO_AD_B1_00_QTIMER3_TIMER0,    /* GPIO_AD_B1_00 is configured as QTIMER3_TIMER0 */
      0U); 

Please see attached a copy of my source code and a snap shot of the wave form.

In the meantime, I have these questions about your code: I believe you set up two DMA sources here just to transfer one buffer for low count and the other buffer for high count? am I right? but in my case, I had only once source and was able to send one value at a time for both comp1 and comp2?

 DMAMUX_SetSource(EXAMPLE_QTMR_DMA_MUX, 0, QTMR_EDMA_REQUEST_CMPLD2_SOURCE);
 DMAMUX_EnableChannel(EXAMPLE_QTMR_DMA_MUX, 0);

 DMAMUX_SetSource(EXAMPLE_QTMR_DMA_MUX, 1, QTMR_EDMA_REQUEST_CMPLD1_SOURCE);
  DMAMUX_EnableChannel(EXAMPLE_QTMR_DMA_MUX, 1);

how the defines below are related to the QTIMER GPIO we select?

#define QTMR_EDMA_REQUEST_CMPLD2_SOURCE kDmaRequestMuxQTIMER3CaptTimer0Cmpld1Timer0Cmpld2Timer1
#define QTMR_EDMA_REQUEST_CMPLD1_SOURCE kDmaRequestMuxQTIMER3CaptTimer1Cmpld1Timer1Cmpld2Timer0

Thanks a lot!

0 Kudos

6,086 Views
leonidshigris
Contributor III

Hello Andre,

As I know, to implement PWM, we should config QTIMER with two channels ( each QTIMER has 4 channels
: timer0- timer3). If you want to implement using DMA, config two DMA channels, each channel corresponds to his own buffer. 

One buffer will hold values for Cmpld1 and second buffer will hold values for Cmpld2. 

Function: EDMA_PrepareTransfer  will combine the timer channel with relevant buffer.

how the defines below are related to the QTIMER GPIO we select?

1. Pay attention to file pin_mux.c ( configs the relevant pin as qtimer)

   Your configuration: IOMUXC_GPIO_AD_B1_00_QTIMER3_TIMER0 --> config QTIMER3 with timer 0 (channel 0)

2. kDmaRequestMuxQTIMER3CaptTimer0Cmpld1Timer0Cmpld2Timer1 --> it's cmpld1 in timer 0

3. kDmaRequestMuxQTIMER3CaptTimer1Cmpld1Timer1Cmpld2Timer0 --> it's cmpld2 in timer 0

4. function QTMR_SetupPwm sets up Quad timer module for PWM signal output.

Best Regards,

Leon.

0 Kudos

6,086 Views
leonidshigris
Contributor III

Hi Kerry,

Attached my scope snapshot. I see the duty cycle changing is working properly.

Best Regards,

Leon.

0 Kudos

6,086 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Leonid Shigris,

   That's good to hear the duty cycle changing is working on your side.

   I didn't find your attached scope snapshot, but I believe it works on your side, please also share your latest modified .c code, it will also be useful to other customers.

   Now, do you still have any question about this topic?

Have a great day,
Kerry

 

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

6,086 Views
leonidshigris
Contributor III

Hi Kerry,

Thank You a lot.

I tested your example. 

I see for a dma buffer to be circular, ,need add some configurations.

I added next configurations for each of buffers:

   

AT_NONCACHEABLE_SECTION_ALIGN(static edma_tcd_t s_emdaTcd1, 32);
AT_NONCACHEABLE_SECTION_ALIGN(static edma_tcd_t s_emdaTcd2, 32);
….

    EDMA_TcdSetTransferConfig(&s_emdaTcd1, &transferConfig1, &s_emdaTcd1);
    EDMA_TcdEnableInterrupts(&s_emdaTcd1, kEDMA_MajorInterruptEnable | kEDMA_HalfInterruptEnable);
    EDMA_InstallTCD(EXAMPLE_QTMR_DMA, g_EDMA_Handle1.channel, &s_emdaTcd1);
   
    EDMA_TcdSetTransferConfig(&s_emdaTcd2, &transferConfig2, &s_emdaTcd2);
    EDMA_TcdEnableInterrupts(&s_emdaTcd2, kEDMA_MajorInterruptEnable | kEDMA_HalfInterruptEnable);
    EDMA_InstallTCD(EXAMPLE_QTMR_DMA, g_EDMA_Handle2.channel, &s_emdaTcd2);

After adding this functions, the dma started as circular buffer.

Is there meaning to s_emdaTcd size ?

Pls review.

Best Regards,

Leon.

0 Kudos

6,086 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Leonid Shigris,

   After you add the new configuration, please also share your test result(PWM wave from the oscilloscope), is there any issue on your side?

   About the s_emdaTcd  size, actually, it is the TCD size, it is 32Bytes, you also can find it from the definition:

pastedImage_1.png

RM also give the TCD structure:

pastedImage_2.png

Wish it helps you!

If you still have questions about it, please kindly let me know.


Have a great day,
Kerry

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

6,086 Views
leonidshigris
Contributor III

Hi Kerry,

Thank you for update. 

Could you send me meanwhile the file with your current changes?

Best Regards,

Leon.

0 Kudos

6,086 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Leonid Shigris

   Thanks a lot for your patience and understanding.

   I get a large step today, please check the PWM result at first, I set it to output the duty as:

AT_NONCACHEABLE_SECTION_INIT(volatile uint16_t g_Cmpld1buf[10]) = {338, 300, 263, 225, 188, 150, 112,  75, 37, 188};//10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%,90%, 50%
AT_NONCACHEABLE_SECTION_INIT(volatile uint16_t g_Cmpld2buf[10]) = {37 , 75 , 112, 150, 187, 225, 263, 300, 338, 187};//10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%,90%, 50%

This is the result:

pastedImage_2.png

You can find the result PWM duty is really 10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%,90%, 50%

About the code, I use the GPIO_AD_B1_00_GPIO1_IO16 pin to trigger the oscilloscope to save the PWM picture, so in pin_mux.c,modify these code:

  IOMUXC_SetPinMux(
      IOMUXC_GPIO_AD_B1_00_GPIO1_IO16,    /* GPIO_AD_B1_00 is configured as QTIMER3_TIMER0 */
      0U);                                    /* Software Input On Field: Input Path is determined by functionality */

  IOMUXC_SetPinConfig(
      IOMUXC_GPIO_AD_B1_00_GPIO1_IO16,    /* GPIO_AD_B1_00 PAD functional properties : */
      0x10B0u);                               /* Slew Rate Field: Slow Slew Rate
                                                 Drive Strength Field: R0/6
                                                 Speed Field: medium(100MHz)
                                                 Open Drain Enable Field: Open Drain Disabled
                                                 Pull / Keep Enable Field: Pull/Keeper Enabled
                                                 Pull / Keep Select Field: Keeper
                                                 Pull Up / Down Config. Field: 100K Ohm Pull Down
                                                 Hyst. Enable Field: Hysteresis Disabled */

About the main code, I I enabled two DMA channels, one is for CMPLD1, another is for CMPLD2, then enable the QTIMR CMPLD1, CMPLD2 DMA EN bit, and start the DMA two channels, the DMA will transfer the data to CMPLD1, CMPLD2 when the condition happens.

Please still use this SDK code:

SDK_2.6.1_EVKB-IMXRT1050\boards\evkbimxrt1050\driver_examples\qtmr\inputcapture_outputpwm_dma

just use my attached qtmr_inputcapture_outputpwm_dma.c to replace the orginal files.

Then you can test it.

Wish it helps you!

If you still have questions about it, please kindly let me know.

Have a great day,
Kerry

 

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

6,086 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Leonid Shigris,

    Today, I just make the CMPLD2 output changed the duty with g_Cmpld2buf[10]) = {37 , 75 , 112, 150, 187, 225, 263, 300, 338, 187};  CMP1 is fixed. so the frequency is also changed, because high pulse is changed, but low pulse didn't changed accordingly.

pastedImage_1.png

So, I still need to consider more ways, how to make both the CMPLD1 and CMPLD2 change in pairs with DMA.

Anyway, any updated information, will let you know.

Best Regards,

Kerry

0 Kudos

6,085 Views
leonidshigris
Contributor III

 Hi Kerry,

PWM period is fixed. I added a buffer with different duty cycles. 

 

See attached file. ( based on example: \SDK_2.6.0_EVKB-IMXRT1050 (4)\boards\evkbimxrt1050\driver_examples\qtmr\inputcapture_outputpwm_dma\)

DMA takes only the first value from buffer.

What I miss?

Best Regards,

Leon.

0 Kudos

6,085 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Leon,

   Thanks for your feedback and effort, I will help you to check your project detail today, then give you reply.

Kerry

0 Kudos

6,085 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Leonid Shigris,

   I tested the QTIMR+DMA with the changed duty, I also meet some problems, should still in the code side, I find just the last duty data is sent to the PWM by DMA, so I already check more details with our internal side, and find the workaround.

   Please keep patient, any updated information, I will let you know.

Best Regards,

Kerry

0 Kudos

6,086 Views
leonidshigris
Contributor III

Hi Kerry,

Thank you for your reply,

I know this example. 

Func: QTMR_SetCmpldValue calculates the high and low values according to given dutycycle and frequency.

Prepare dma twice once for low value and once for high value.

After that sends out the wave with specific frequency and dutycycle.

My target is little different:

I have to send the wave, that every period changes the dutycycle. It's mean every period the timer CMPLD should update his value according to buffer index.

Example 'bubble' do similar what I want - it changes duty cycle. But it implemented via QTMR_IRQ_HANDLER.

I have to implement via DMA (not to stifle performance). 

Best Regards,

Leon.

0 Kudos