Here's some pwm code I found on the internet for the M4 Feather that compiles but it doesn't seem to work on my M4 airlift lite my fan doesn't adjust speed. Any idea what I'm missing? I did play with the numbers and tried to figure out out.
Code: Select all
// Adafruit feather m4 express: Set-up digital pin D12 and D13 to 25KHz variable duty cycle
// PWM frequency = (selected clock source / DIV) / (PRESCALER_DIV * (PERIOD + 1))
// ( GCLK_GENCTRL_SRC_DPLL0 / GCLK_GENCTRL_DIV(0) ) / (TC_CTRLA_PRESCALER_DIV2
#define PERIOD 2399
#define PWMPin 12
int led = 13;
void setup()
{
pinMode(led, OUTPUT);
// Set up the generic clock (GCLK7) to clock timer TCC1
GCLK->GENCTRL[7].reg = GCLK_GENCTRL_DIV(0) | // Divide the clock source
GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW "square wave"
GCLK_GENCTRL_GENEN | // Enable GCLK7
//GCLK_GENCTRL_SRC_DFLL; // Select 48MHz DFLL clock source
//GCLK_GENCTRL_SRC_DPLL1; // Select 100MHz DPLL clock source
GCLK_GENCTRL_SRC_DPLL0; // Select 120MHz DPLL clock source
while (GCLK->SYNCBUSY.bit.GENCTRL7); // Wait for synchronization
// http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
// page 169
GCLK->PCHCTRL[25].reg = GCLK_PCHCTRL_BANNED | // Enable the TCC0/TCC1 perhipheral channel
GCLK_PCHCTRL_GEN_GCLK7; // Connect generic clock 7 to TCC0 and TCC1
// Enable the peripheral multiplexer on pin D12
PORT->Group[g_APinDescription[PWMPin].ulPort].PINCFG[g_APinDescription[PWMPin].ulPin].bit.PMUXEN = 1;
// http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
// page 35
// Set the D12 (PORT_PA22 TCC1/WO[6]) peripheral multiplexer to peripheral (EVEN port number) F(0x5): TCC1, Channel 0
PORT->Group[g_APinDescription[PWMPin].ulPort].PMUX[g_APinDescription[PWMPin].ulPin >> 1].reg |= PORT_PMUX_PMUXE(5);
TCC1->CTRLA.reg = TCC_CTRLA_PRESCALER_DIV2 | // Set prescaler to 2, 120MHz/2 = 60MHz
TCC_CTRLA_PRESCSYNC_PRESC; // Set the reset/reload to trigger on prescaler clock
TCC1->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM; // Set-up TCC1 timer for Normal (single slope) PWM mode (NPWM)
while (TCC1->SYNCBUSY.bit.WAVE) // Wait for synchronization
//pwm resolution
//log(PER.reg 2399) / log(2) = 2^11 steps (2048)
TCC1->PER.reg = PERIOD; // Set-up the PER (period) register for 25KHz
while (TCC1->SYNCBUSY.bit.PER); // Wait for synchronization
TCC1->CC[2].reg = PERIOD; // D12??? all the way on
while (TCC1->SYNCBUSY.bit.CC2); // Wait for synchronization
TCC1->CTRLA.bit.ENABLE = 1; // Enable timer TCC1
while (TCC1->SYNCBUSY.bit.ENABLE); // Wait for synchronization
}
void changeDutyCycle(float newVal) {
float fperiod = newVal * (PERIOD / 100.00);
int period = constrain(fperiod, 0, PERIOD);
// http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
//page 43-44 table 6-29
TCC1->CCBUF[2].reg = period; //per can equal 0-2399 (+1) microseconds?
}
void loop()
{
for (int ii = 0; ii <= 10; ii++)
{
changeDutyCycle(ii * 10);
for (int xx = 0; xx < ii; xx++)
{
digitalWrite(led, HIGH);
delay(500);
digitalWrite(led, LOW);
delay(500);
}
delay(5000);
}
}