dlloyd:
A while back, while learning Arduino on the Due, I tested the complimentary PWM (PWMC) using 4 channels (8 signals). It worked great ... tested at 1.281 kHz PWM frequency with dead-time control and full 16-bit duty cycle control.
//declare variables
unsigned short duty0 = 15000;
unsigned short duty1 = 30000;
unsigned short duty2 = 45000;
unsigned short duty3 = 60000;
void setup() {
pwmc_setup();
}
void loop() {
pwmc_duty(duty0, duty1, duty2, duty3); //set pwm duty cycle
}
void pwmc_setup()
{
//Configure PWM channels 0,1,2,3 (PWML0,PWMH0,PWML1,PWMH1,PWML2,PWMH2,PWML3,PWMH3), (port C.2,C.3,C.4,C.5,C.6,C.7,C.8,C.9), (pins P34,P35,P36,P37,P38,P39,P40,P41)
REG_PIOC_PDR = 0x3FC; //B1111111100, PIO Disable Register
REG_PIOC_ABSR = REG_PIOC_ABSR | 0x3FCu; //B1111111100, Peripheral AB Select Register
REG_PMC_PCER1 = REG_PMC_PCER1 | 16; //Peripheral Clock Enable Register 1 (activate clock for PWM, id36, bit5 of PMC_PCSR1)
REG_PWM_ENA = REG_PWM_SR | B1111; //PWM Enable Register | PWM Status Register (activate channels 0,1,2,3)
REG_PWM_CMR0 = 0x10000; //Channe0 Mode Register: Dead Time Enable DTE=1
REG_PWM_CMR1 = 0x10000; //Channe1 Mode Register: Dead Time Enable DTE=1
REG_PWM_CMR2 = 0x10000; //Channe2 Mode Register: Dead Time Enable DTE=1
REG_PWM_CMR3 = 0x10000; //Channe3 Mode Register: Dead Time Enable DTE=1
REG_PWM_DT0 = 0xA800A8; //Channe0 Dead Time Register (168=2us for outputs PWML0,PWMH0)
REG_PWM_DT1 = 0xA800A8; //Channe1 Dead Time Register (168=2us for outputs PWML1,PWMH1)
REG_PWM_DT2 = 0xA800A8; //Channe2 Dead Time Register (168=2us for outputs PWML2,PWMH2)
REG_PWM_DT3 = 0xA800A8; //Channe3 Dead Time Register (168=2us for outputs PWML3,PWMH3)
REG_PWM_CPRD0 = 65535; //Channe0 Period Register (84mhz/65535=1.281khz=780.64us period)
REG_PWM_CPRD1 = 65535; //Channe1 Period Register (84mhz/65535=1.281khz=780.64us period)
REG_PWM_CPRD2 = 65535; //Channe2 Period Register (84mhz/65535=1.281khz=780.64us period)
REG_PWM_CPRD3 = 65535; //Channe3 Period Register (84mhz/65535=1.281khz=780.64us period)
}
//Set the PWM duty-cycle
inline void pwmc_duty(unsigned short duty0, unsigned short duty1, unsigned short duty2, unsigned short duty3) {
REG_PWM_CDTY0 = duty0;
REG_PWM_CDTY1 = duty1;
REG_PWM_CDTY2 = duty2;
REG_PWM_CDTY3 = duty3;
}
Hi, I wam trying to modify the above code so that I use 6 channels instead of 4. How should I do this? I I have tried to modify the REG_PIOC_PDR, REG_PIOC_ABSR, REG_PMC_PCER1.
Please help me out.
Thanks
Here is the code
//#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <PID_v1.h>
#include<math.h>
unsigned short duty0; // pin 34 and inverted on pin 35
unsigned short duty1; // pin 36 and inverted on pin 37
unsigned short duty2; // pin 38 and inverted on pin 39
unsigned short duty3; // pin 40 and inverted on pin 41
unsigned short duty4; // pin 09 and inverted on pin no comp
unsigned short duty5; // pin 08 and inverted on pin 44
const int sinePWM_P[335]PROGMEM= {0,79,158,237,316,394,473,551,630,708,785,863,940,1017,1093,1169,1245,1320,1395,1469,1543,1616,1689,1761,1832,1903,1973,2043,2111,2179,2246,2313,2378,2443,2507,2570,2632,2693,2753,2812,2870,2928,2984,3039,3093,3146,3198,3248,3298,3346,3393,3439,3484,3527,3570,3611,3650,3689,3726,3762,3796,3829,3861,3892,3921,3948,3974,3999,4023,4045,4065,4084,4102,4118,4133,4146,4158,4169,4178,4185,4191,4195,4198,4200,4200,4198,4195,4191,4185,4178,4169,4158,4146,4133,4118,4102,4084,4065,4045,4023,3999,3974,3948,3921,3892,3861,3829,3796,3762,3726,3689,3650,3611,3570,3527,3484,3439,3393,3346,3298,3248,3198,3146,3093,3039,2984,2928,2870,2812,2753,2693,2632,2570,2507,2443,2378,2313,2246,2179,2111,2043,1973,1903,1832,1761,1689,1616,1543,1469,1395,1320,1245,1169,1093,1017,940,863,785,708,630,551,473,394,316,237,158,79,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
const int sinePWM_N[335]PROGMEM = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,79,158,237,316,394,473,551,630,708,785,863,940,1017,1093,1169,1245,1320,1395,1469,1543,1616,1689,1761,1832,1903,1973,2043,2111,2179,2246,2313,2378,2443,2507,2570,2632,2693,2753,2812,2870,2928,2984,3039,3093,3146,3198,3248,3298,3346,3393,3439,3484,3527,3570,3611,3650,3689,3726,3762,3796,3829,3861,3892,3921,3948,3974,3999,4023,4045,4065,4084,4102,4118,4133,4146,4158,4169,4178,4185,4191,4195,4198,4200,4200,4198,4195,4191,4185,4178,4169,4158,4146,4133,4118,4102,4084,4065,4045,4023,3999,3974,3948,3921,3892,3861,3829,3796,3762,3726,3689,3650,3611,3570,3527,3484,3439,3393,3346,3298,3248,3198,3146,3093,3039,2984,2928,2870,2812,2753,2693,2632,2570,2507,2443,2378,2313,2246,2179,2111,2043,1973,1903,1832,1761,1689,1616,1543,1469,1395,1320,1245,1169,1093,1017,940,863,785,708,630,551,473,394,316,237,158,79,0};
int vq, i;
void setup() {
// put your setup code here, to run once:
pwmc_setup();
pinMode(22,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
pwmc_duty(duty0, duty1, duty2, duty3, duty4, duty5);
//delayMicroseconds(46);
i++;
if (i<168)
{
digitalWrite(22,HIGH);
}
else
{
digitalWrite(22,LOW);
if (i==333) i=0;
}
}
//VERIFY PIOC_PDR = 0x3FC
void pwmc_setup()
{
//Configure PWM channels 0,1,2,3 (PWML0,PWMH0,PWML1,PWMH1,PWML2,PWMH2,PWML3,PWMH3), (port C.2,C.3,C.4,C.5,C.6,C.7,C.8,C.9), (pins P34,P35,P36,P37,P38,P39,P40,P41)
REG_PIOC_PDR = 0x3FC; //B1111111100, PIO Disable Register
REG_PIOC_ABSR = REG_PIOC_ABSR | 0x3FCu; //B1111111100, Peripheral AB Select Register
REG_PMC_PCER1 = REG_PMC_PCER1 | 16; //Peripheral Clock Enable Register 1 (activate clock for PWM, id36, bit5 of PMC_PCSR1)
REG_PWM_ENA = REG_PWM_SR | B111111; //PWM Enable Register | PWM Status Register (activate channels 0,1,2,3,4,5)
// Use 0x100000 to enable dead time
REG_PWM_CMR0 = 0x00000; //Channe0 Mode Register: Dead Time Enable DTE=1
REG_PWM_CMR1 = 0x00000; //Channe1 Mode Register: Dead Time Enable DTE=1
REG_PWM_CMR2 = 0x00000; //Channe2 Mode Register: Dead Time Enable DTE=1
REG_PWM_CMR3 = 0x00000; //Channe3 Mode Register: Dead Time Enable DTE=1
REG_PWM_CMR4 = 0x00000; //Channe2 Mode Register: Dead Time Enable DTE=1
REG_PWM_CMR5 = 0x00000; //Channe3 Mode Register: Dead Time Enable DTE=1
// available range is same as duty and depends on PWM frequency (see datasheet)
REG_PWM_DT0 = 0x000000; //Channe0 Dead Time Register for pins 34,35 (PWML0,PWMH0)
REG_PWM_DT1 = 0x000000; //Channe1 Dead Time Register for pins 36,37 (PWML1,PWMH1)
REG_PWM_DT2 = 0x000000; //Channe2 Dead Time Register for pins 38,39 (PWML2,PWMH2)
REG_PWM_DT3 = 0x000000; //Channe3 Dead Time Register for pins 40,41 (PWML3,PWMH3)
REG_PWM_DT4 = 0x000000; //Channe4 Dead Time Register for pins 09,xx (PWML2,PWMH2)
REG_PWM_DT5 = 0x000000; //Channe5 Dead Time Register for pins 08,xx (PWML3,PWMH3)
REG_PWM_CPRD0 = 4200; //Channe0 Period Register (84mhz/4200=20KHz)
REG_PWM_CPRD1 = 4200; //Channe1 Period Register (84mhz/4200=20KHz)
REG_PWM_CPRD2 = 4200; //Channe2 Period Register (84mhz/4200=20KHz)
REG_PWM_CPRD3 = 4200; //Channe3 Period Register (84mhz/4200=20KHz)
REG_PWM_CPRD4 = 4200; //Channe2 Period Register (84mhz/4200=20KHz)
REG_PWM_CPRD5 = 4200; //Channe3 Period Register (84mhz/4200=20KHz)
}
//Set the PWM duty-cycle
inline void pwmc_duty(unsigned short duty0, unsigned short duty1, unsigned short duty2, unsigned short duty3, unsigned short duty4, unsigned short duty5)
{
static int num01, num23, num45;
if(num01>=223) num23= num01 - 223;
else num23 = num01+112;
if(num01>=112) num45 = num01-112;
else num45 = num01 + 223;
if(++num01>=335) num01 = 0;
duty0 = sinePWM_P[num01];
duty1 = sinePWM_N[num01];
duty2 = sinePWM_P[num23];
duty3 = sinePWM_N[num23];
duty4 = sinePWM_P[num45];
duty5 = sinePWM_N[num45];
REG_PWM_CDTY0 = duty0;
REG_PWM_CDTY1 = duty1;
REG_PWM_CDTY2 = duty2;
REG_PWM_CDTY3 = duty3;
REG_PWM_CDTY4 = duty4;
REG_PWM_CDTY5 = duty5;
delayMicroseconds(47);
}