Go Down

Topic: Due Help on direct port access with PWM (Read 209 times) previous topic - next topic

btt92

Hello everyone,

This is my first time posting on this forum. So, recently I purchased the Arduino Due after months of tinkering with the Uno. When using the Uno, port manipulation was a bit easier using DDR and PORTx. When I made the jump from an AVR board to an ARM, I was stuck on how to do port manipulation for the Due. I first started with a simple blinking LED program to understand how to set and clear bits. The simple code is shown below.

Code: [Select]
void setup() {
 
  REG_PIOB_PER = (1<<25);  //Can also use bit mask - 0x1<<25
  REG_PIOB_OER = (1<<25);  //Can also use REG_PIOB_OER = PIO_OER_P25
 
}

void loop() {

  REG_PIOB_SODR = (1<<25);
  delay(2000);
  REG_PIOB_CODR = (1<<25);
  delay(2000);

}


Now I want to write a program that will use PWM on the LED. After a little research, I found that each I/O pin can have be multiplexed to have two functions. What is multiplexing and how can it be done in a simple example? Also, how can I write a program to set up PWM using low-level programming?

ard_newbie

Hello btt92

[quote ]

 I found that each I/O pin can have be multiplexed to have two functions[/quote]

You have the explanation of this chap 9.3 of Sam3x datasheet.

For PWM programming, here is an example :

Code: [Select]

void setup () {
 
  // PWM Set-up on pin PC7 (Arduino Pin 39): see Datasheet chap. 38.5.1
  // Select Instance=PWM; Signal=PWMH2 (channel 2); I/O Line=PC7 (P7, Arduino pine 39, see pinout diagram) ; Peripheral=B

  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                   // PWM on

  REG_PIOC_ABSR |= PIO_ABSR_P7;                        // Set PWM pin perhipheral type B

  REG_PIOC_PDR |= PIO_PDR_P7;                          // Set PWM pin to an output

  REG_PWM_ENA = PWM_ENA_CHID2;                         // Enable the PWM channel 2 (see datasheet page 973)
 
  REG_PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(42);    // Set the PWM clock rate to 2MHz (84MHz/42). Adjust DIVA for the resolution you are looking for
                                                     
  REG_PWM_CMR2 = PWM_CMR_CALG |PWM_CMR_CPRE_CLKA;      // The period is left aligned, clock source as CLKA on channel 2

  REG_PWM_CPRD2 = 1000000;                             // Channel 2 : Set the PWM frequency 2MHz/(2 * CPRD) = F ; 1< CPRD < 2exp24  -1 ; here CPRD = 10 exp 6

  REG_PWM_CDTY2 = 200000;                              // Channel 2: Set the PWM duty cycle to x%= (CDTY/ CPRD)  * 100 % , CDTY = 2 * 10 exp 5

 // Alternatively, you can use this format :  PWM->PWM_CH_NUM[2].PWM_CPRD = 1000000 ;                   
 // In this example, Frequency is 1 HZ with a DT of 20% so you can see it with an LED attached to pin 39 with a resistor 
 
}


void loop() {
}





btt92

So, from my understanding, all the pins on the due are controlled by the PIO controllers that are capable of controlling 32 lines(pins). Each pin ( or line) can do two functions which are chosen from the start and once a peripheral function is chosen, you can not reset to the other function. Is that pretty much how it is? Thank you for the reply, the example worked well!

Go Up