Arduino Nano IOT PWM Pin 9 8MHz

Hi All
I am trying to get a high frequency (8MHz) PWM signal from pin 9 on a Nano IOT board. I have narrowed down a bigger problem I am having to a too slow clockspeed on this pin from a library I am using.

code from library:

inline void Tlc5948::startBuiltinGsclk() {
    // On Arduino Nano
    // timer 0 -> A: 6 B: 5 
    // timer 1 -> A: 9 B: 10 * using this timer
    // timer 2 -> A: 3 B: 11

    // From https://withinspecifications.30ohm.com/2014/02/20/Fast-PWM-on-AtMega328/
    // and atmega328p datasheet

    // To set appropriate mode for PWM we need three settings enabled:
    // TCCRXA - PWM mode + output CLEAR invert/non-invert
    // Fast Pwm Mode(counts up and resets to 0, and changes output on OCR0X val)
    // \- We do this by settings WGM0[1:0] in TCCR0A to 1 and WGM02 TCCR0B to 1
    // \- WGM02 in TCCR0B also specifies that reset to 0 happens at OCR0A value
    // \- and not at TOP (255 for timer 0, 65536 for timer 1)
    // set COM0X1 bits to 1
    // \- sets output to clear on match and start from BOTTOM (non-inverting)
    ICR1 = 1; // according to datasheet this works well for static duty as TOP
              // using 1 as TOP gives 1 bit resolution but 8Mhz max frequency

    // enable A and B, using OCR1A TOP
    //TCCRXA = _BV(COM1A1) | _BV(COM1B1) | _BV(WGM11) | _BV(WGM10);
    //enable just A, using ICR1 as TOP (leave WGM10 as 0)
    TCCR1A = _BV(COM1A1) | _BV(WGM11);

    // TCCRXB - Timer control Reg b
    // controls: clock prescaler (and upper bits of WGM)
    // for timer1: CS0[2:0] = 001 -> prescaler = 1 (produces 8Mhz signal)
    //       note: WGM02   =  1 -> set Fast PWM mode
    //       other prescalers: 010 -> prescaler = 8 (produces 1Mhz signal, cleaner than the 8Mhz)
    
    // Using _BV(CS11) produces slower 1Mhz signal, but it's cleaner than the 8Mhz one
    // this signal can be used if the ESPWM mode
    TCCR1B =  _BV(WGM13) | _BV(WGM12) | _BV(CS10);

    OCR1A = 0;
}

This stuff really messes with my head, so any help is greatly appreciated. I am hoping for a basic setup and loop program similar to below, but works and explains what it does.
Thank you

Definitely not working code, probably for an UNO



void setup()
{
  pinMode(9,OUTPUT);
  TCCR1A = _BV(COM1A0); // toggle OC1A on Compare Match
  TCCR1B = _BV(WGM12) | _BV(CS10); // CTC, no prescaler
  OCR1A = 7; // 1 MHz

}


void loop()
{
  
}

Same applies for the code above. A Nano IoT is driven by a SAMD21 MCU at 48MHz. This article shows you how to setup PWM correctly on that MCU.

Thank you for that link. I'll look into these parts and post back what I find for future people

what special purpose is this that you need a 8 Mega-Hertz PWM?

Thank you for pointing that out. I don't need PWM, I just need 8MHz. It is for the GSClk, or greyscale clock. The chip that connects to this wire counts a bunch of them, and does its own greyscaling based on it. I just need to provide it with this signal greater than 1MHz, and less than 33MHz. I am still lost trying to get any to work, even the example code is not working. No errors, just no output

I googled
and found this

seems to be a pretty complex setup

Thank you for that code! That one works on Pin 8, I should be able to tweak to pin 9 using the datasheet now!

Here is the code for pin 9

// Number to count to with PWM (TOP value). Frequency can be calculated by
// freq = GCLK4_freq / (TCC0_prescaler * (1 + TOP_value))
// With TOP of 47, we get a 1 MHz square wave in this example

//freq = 48 / (1 * (1+top))
//freq out should be 8
//8 = 48 / (1 * (1+top))
//8 * (1 + top) = 48
//1 + top = 6
//top = 5

uint32_t period = 6 - 1;
 
void startClk(){
  // Because we are using TCC0, limit period to 24 bits
  period = ( period < 0x00ffffff ) ? period : 0x00ffffff;

  // Enable and configure generic clock generator 4
  GCLK->GENCTRL.reg = GCLK_GENCTRL_IDC |          // Improve duty cycle
                      GCLK_GENCTRL_GENEN |        // Enable generic clock gen
                      GCLK_GENCTRL_SRC_DFLL48M |  // Select 48MHz as source
                      GCLK_GENCTRL_ID(4);         // Select GCLK4
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

  // Set clock divider of 1 to generic clock generator 4
  GCLK->GENDIV.reg = GCLK_GENDIV_DIV(1) |         // Divide 48 MHz by 1
                     GCLK_GENDIV_ID(4);           // Apply to GCLK4 4
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization
  
  // Enable GCLK4 and connect it to TCC0 and TCC1
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |        // Enable generic clock
                      GCLK_CLKCTRL_GEN_GCLK4 |    // Select GCLK4
                      GCLK_CLKCTRL_ID_TCC0_TCC1;  // Feed GCLK4 to TCC0/1
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

  // Divide counter by 1 giving 48 MHz (20.83 ns) on each TCC0 tick
  TCC0->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV1_Val);

  // Use "Normal PWM" (single-slope PWM): count up to PER, match on CC[n]
  TCC0->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM;         // Select NPWM as waveform
  while (TCC0->SYNCBUSY.bit.WAVE);                // Wait for synchronization

  // Set the period (the number to count to (TOP) before resetting timer)
  TCC0->PER.reg = period;
  while (TCC0->SYNCBUSY.bit.PER);

  // Set PWM signal to output 50% duty cycle
  // n for CC[n] is determined by n = x % 4 where x is from WO[x]
  TCC0->CC[2].reg = period / 2;
  while (TCC0->SYNCBUSY.bit.CC2);

  // Configure PA20 (D9 on Arduino Nano) to be output
  PORT->Group[PORTA].DIRSET.reg = PORT_PA20;      // Set pin as output
  PORT->Group[PORTA].OUTCLR.reg = PORT_PA20;      // Set pin to low

  // Enable the port multiplexer for PA18
  PORT->Group[PORTA].PINCFG[20].reg |= PORT_PINCFG_PMUXEN;

  // Connect TCC0 timer to PA18. Function F is TCC0/WO[2] for PA18.
  // Odd pin num (2*n + 1): use PMUXO
  // Even pin num (2*n): use PMUXE
  PORT->Group[PORTA].PMUX[10].reg = PORT_PMUX_PMUXE_F;

  // Enable output (start PWM)
  TCC0->CTRLA.reg |= (TCC_CTRLA_ENABLE);
  while (TCC0->SYNCBUSY.bit.ENABLE);              // Wait for synchronization
}

void setup() {
  startClk();
  
}

void loop() {
  // Do nothing
}

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