Enabling pin output from ISR

Doing something simple wrong here...
Code below essentially sets up single phase PWM and when there is a match, enables a signal on pin 6. There is commented out code, that allows pin 5 to be used as well. All worked.
I changed the code so that instead of using a match/compare to set pin 5, I tried to output a HIGH/LOW signal on the pin from within the ISR. This did not work.

I 'fixed' it by setting up the pin by calling pinMode(5, OUTPUT) first, which is OK, but I thought setting up the pins and peripherals in the code below did that. I don't understand why a match/compare can toggle the pin to generate a signal but I cannot do it directly from code by calling digitalWrite.

Code follows:

unsigned long CPUTime;
unsigned long CPUSpeed = F_CPU;
unsigned int mytest = 0;

#define ledPin 13
void setup()
{

  //************************************** Clock Setting ********************************************************//

  // Feed GCLK0 at 48MHz to TCC0 and TCC1
  REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN |           // Enable GCLK0 as a clock source
                     GCLK_CLKCTRL_GEN_GCLK0 |      // Select GCLK0 at 48MHz
                     GCLK_GENDIV_DIV(3) |          // Divide clock by 3 yielding 16Mhz
                     GCLK_CLKCTRL_ID_TCC0_TCC1;    // Route GCLK0 to TCC0 and TCC1

  //************************************** PORT Enabling ********************************************************//


//I thought the code immediately below also setup the pins for OUTPUT...
  // Enable the port multiplexer for pins D6
  PORT->Group[g_APinDescription[6].ulPort].PINCFG[g_APinDescription[6].ulPin].bit.PMUXEN = 1;
  PORT->Group[g_APinDescription[5].ulPort].PINCFG[g_APinDescription[5].ulPin].bit.PMUXEN = 1;

  // D6 is on EVEN port pin PA04, D5 is on the odd port of E
  PORT->Group[g_APinDescription[6].ulPort].PMUX[g_APinDescription[6].ulPin >> 1].reg = PORT_PMUX_PMUXO_E | PORT_PMUX_PMUXE_E;


  //************************************** TIMER Setting ********************************************************//

  //Fast PWM

  REG_TCC0_WAVE = TCC_WAVE_WAVEGEN_NPWM | TCC_WAVE_POL0 | TCC_WAVE_POL1 ;        // Setup dual slope PWM on TCC0, inverting signal
  while (TCC0->SYNCBUSY.bit.WAVE);                  // Wait for synchronization

  REG_TCC0_CTRLA |= TCC_CTRLA_PRESCALER_DIV16;      // Divide timer clock by 16, yielding 1MHz.

  REG_TCC0_PER = 1000000;                           // PER = 1M; this equals 1 second / 1Hz
  while (TCC0->SYNCBUSY.bit.PER);                   // Wait for synchronization

  //CC0 aligns to pin 6
  REG_TCC0_CC0 = REG_TCC0_PER / 2;                // TCC0 CC0 - 50% duty cycle - 1/2 second
  while (TCC0->SYNCBUSY.bit.CC0);                 // Wait for synchronization

  //CC1 aligns to pin 5
  //REG_TCC0_CC1 = 150000;                          // TCC0 CC1 - 65% duty cycle
  //while (TCC0->SYNCBUSY.bit.CC1);                 // Wait for synchronization

  TCC0->INTENSET.reg = 0;                          // disable all interrupts
  TCC0->INTENSET.bit.OVF = 1;                      // enable overfollow

  // Enable InterruptVector
  NVIC_EnableIRQ(TCC0_IRQn);

  TCC0->CTRLA.bit.ENABLE = 1;                     // Enable the TCC0 counter
  while (TCC0->SYNCBUSY.bit.ENABLE);              // Wait for synchronization

  //I added this code and now Pin 5 can be set HIGH/LOW
  pinMode(ledPin, OUTPUT);
  pinMode(5, OUTPUT);
  digitalWrite(ledPin, LOW);
  digitalWrite(5, LOW);

  Serial.begin(115200);
  while (!Serial);
  Serial.println("Starting...");
}

void loop()
{
  static long InterruptCount = 1000000;
  static bool first = true;
  if (first)
  {
    Serial.print("\nCPU Speed: ");
    Serial.println(CPUSpeed);
    Serial.print("Ticks in period: ");
    Serial.println(REG_TCC0_PER);     //Ticks in the period
    Serial.print("Ticks level when CC0 is toggled: ");
    Serial.println(REG_TCC0_CC0);     //Ticks when port is toggled
    Serial.print("Ticks level when CC1 is toggled: ");
    Serial.println(REG_TCC0_CC1);     //Ticks when port is toggled
    Serial.print("Sizeof CC0: ");
    Serial.println(sizeof(REG_TCC0_CC0));
    first = false;
  }

  InterruptCount++;
  if (InterruptCount >= 1000000)
  {
    InterruptCount = 1;
    first = true;
  }
}

void TCC0_Handler()
{
  Tcc* TC = (Tcc*) TCC0;       // get timer struct
  static bool bVal = false;

  Serial.println("TCC0 Handler");
  if (TC->INTFLAG.bit.OVF == 1)            // An overflow caused the interrupt
  {
    Serial.println("OVF");
    TC->INTFLAG.bit.OVF = 1;               // writing a one clears the flag ovf flag
    if (bVal)
    {
      Serial.println("HIGH");
      digitalWrite(5, HIGH);
      digitalWrite(ledPin, HIGH);
    }
    else
    {
      Serial.println("LOW");
      digitalWrite(5, LOW);
      digitalWrite(ledPin, LOW);
    }
    bVal = !bVal;
  }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.