Go Down

Topic: 16bit PWM on Due (Read 281 times) previous topic - next topic

BenediktSch

Oct 17, 2018, 10:00 am Last Edit: Oct 17, 2018, 10:03 am by BenediktSch
Hello there,

I want a 16bit PWM for LED controls, I choose the Due because it has more than the four needed PWM outputs.
I tried to configure the registers to my needs but I am not really sure about the CPRD and CDTY register.
As far as I understand I give a maximum to the CPRD register (e.g. for 16bit 65535) and then define how long the LED is set to on by writing another number in the CDTY register (e.g 32768 for 50% on and 50% off) is that thought right or did I misunderstand anything?

Edit: I choose serial command to read the serial port because I only need to switch PWM values once every few seconds. Does this work like this or do I need to go to registers here as well?
Here is my code so far:
Code: [Select]
//define output pins
#define darkb 6 //PC24 & PWML7
#define blue 7  //PC23 & PWML6
#define yello 8 //PC22 & PWML5
#define green 9 //PC21 & PWML4

//define variables
int number = 0;
int incomingNumber;
int tik = 1;
int color[4];


void setup() {
  Serial.begin(115200);

  pinMode(darkb, OUTPUT);
  pinMode(blue, OUTPUT);
  pinMode(yello, OUTPUT);
  pinMode(green, OUTPUT);

  //PWM setup
  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                                            //enable PWM

  PWM->PWM_DIS = PWM_DIS_CHID4 | PWM_DIS_CHID5 | PWM_DIS_CHID6 | PWM_DIS_CHID7; //diable all PWM-registers

  PIOC->PIO_PDR |= PIO_PDR_P21 | PIO_PDR_P22 | PIO_PDR_P23 | PIO_PDR_P24;       //disable GPIO

  PIOC->PIO_ABSR |= PIO_PC24B_PWML7 | PIO_PC23B_PWML6 | PIO_PC22B_PWML5 | PIO_PC21B_PWML4; //enable PWM at PINs

  PWM->PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(1) ; // Set PWM clock rate to 84MHz (MCK)

  //PWM->PWM_CH_NUM[4].PWM_CMR =
  //PWM->PWM_CH_NUM[5].PWM_CMR =
  //PWM->PWM_CH_NUM[6].PWM_CMR =
  //PWM->PWM_CH_NUM[7].PWM_CMR =

  PWM->PWM_CH_NUM[4].PWM_CPRD = 65535;            //Set PWM frequency of 1.28KHz = 84MHz / 65535
  PWM->PWM_CH_NUM[5].PWM_CPRD = 65535;
  PWM->PWM_CH_NUM[6].PWM_CPRD = 65535;
  PWM->PWM_CH_NUM[7].PWM_CPRD = 65535;

  PWM->PWM_CH_NUM[4].PWM_CDTY = 65535;            //Set PWM duty cycle to CDTY/CPRD , here 0usec
  PWM->PWM_CH_NUM[5].PWM_CDTY = 65535;
  PWM->PWM_CH_NUM[6].PWM_CDTY = 65535;
  PWM->PWM_CH_NUM[7].PWM_CDTY = 65535;

  PWM->PWM_ENA = PWM_ENA_CHID4 | PWM_ENA_CHID5 | PWM_ENA_CHID6 | PWM_ENA_CHID7;   //Enable PWM
}

void loop() {
  while (Serial.available()) {

    incomingNumber = Serial.read() - 48; //ASCII to DEC

    if (incomingNumber >= 0 && incomingNumber <= 9) {

      number = number * 10 + incomingNumber;

    } else {

      color[tik] = number; //0-65535
      tik++;
      number = 0;

      if (tik == 4) {                                     //When all four numbers are submitted, sumbit them to the LEDs

        Serial.println(color[1]);
        Serial.println(color[2]);
        Serial.println(color[3]);
        Serial.println(color[4]);

        PWM->PWM_CH_NUM[4].PWM_CDTY = color[1];            //Set PWM duty cycle to desevered brightness
        PWM->PWM_CH_NUM[5].PWM_CDTY = color[2];
        PWM->PWM_CH_NUM[6].PWM_CDTY = color[3];
        PWM->PWM_CH_NUM[7].PWM_CDTY = color[4];

        tik = 1;
      }

    }


  }

}

ard_newbie

#1
Oct 17, 2018, 10:20 am Last Edit: Oct 17, 2018, 10:25 am by ard_newbie
As far as I understand I give a maximum to the CPRD register (e.g. for 16bit 65535) and then define how long the LED is set to on by writing another number in the CDTY register (e.g 32768 for 50% on and 50% off) is that thought right or did I misunderstand anything?
That's right.

Program PWM_CMR too, you have plenty of example sketches with PWM in this sub forum.

Once PWM channels have been enabled at the end of setup(), update CDTY (or CPRD) in loop() with PWM_CDTYUPD for CDTY Up Date (or PWM_CPRDUPD) to set automatically the new values exactly at the beginning of a new period.

BenediktSch

Thanks a lot! So I am gonna change CPRD to CPRDUPD in my loop.

Program PWM_CMR too, you have plenty of example sketches with PWM in this sub forum.
But why should I program the register when I need a 0 all over the register?



ard_newbie


In this particuliar case this is not compulsary, but you need to know :
_ That the register is at zero and when you are using header files names (which is the right way to do), you are not supposed to know their equivalent "magic" number,
_ After a reset, the register must be set to zero by the uc, check for this.

BenediktSch

So just in case right?
Will do! Thank you very much!

Go Up