0
\$\begingroup\$

In the below code I am trying to get the clock frequency to show up on the CLKOUT pin which should be pinA7. But for some reason I don't get anything when measuring pinA7 on an oscillicope. I do see my pinF2 toggle appropriately so I know that I am setting the correct registers to change the clock frequency.

shouldn't the line CLKCTRL.MCLKCTRLA = CLKCTRL_CLKOUT_bm set pinA7 as CLKOUT?

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>

#ifdef F_CPU
#undef F_CPU
#endif
#define F_CPU 10000000UL

// Define Functions
// Initializes the ms Timer
void TCA0_init(void);

// Initializes the Watchdog Timer
void watchdogSetup(void);

// Initializes the Clock frequency
void CLKSetup(void);

// Initializes I/O pins
void initialSetup(void);

// Returns the ms time since power-on
unsigned long millis(void);

// Runs the System Status outputs
void blinky(unsigned int onTime, unsigned int offTime);
    

// Initialize Timing Variables
volatile uint64_t milliVal = 0;

// Initialize Status Light Variables
unsigned long blinkTime = 0;
char isOn = 1;


int main(void)
{
    initialSetup();
    
    /* Replace with your application code */
    while (1)
    {
        blinky(1000,1000);
    }
    
}

void CLKSetup(void)
{
    //CPU_CCP = 0xD8;
    //CLKCTRL.MCLKCTRLA = CLKCTRL_CLKOUT_bm;
    //CLKCTRL.MCLKCTRLA = CLKCTRL_CLKSEL0_bm;//the system clock is set to internal OSC20M 20Mhz oscillator
    //CLKCTRL.MCLKCTRLB = CLKCTRL_PEN_bm; // allow prescaling of main clk
    //CLKCTRL.MCLKCTRLB = CLKCTRL_PDIV2_bm;//divide 20Mhz Main Clock with prescaler of 2 = 10Mhz
    
    // Clock setting 10MHz(20/2)  
    CPU_CCP = 0xD8;  
    CLKCTRL.MCLKCTRLB = CLKCTRL_PDIV_2X_gc | CLKCTRL_PEN_bm;
    CLKCTRL.MCLKCTRLA = CLKCTRL_CLKOUT_bm | CLKCTRL_CLKSEL_OSC20M_gc;
    CLKCTRL.MCLKCTRLA = CLKCTRL_LOCKEN_bm;//Lock the Clock from further adjustments
    CLKCTRL.MCLKCTRLB = CLKCTRL_LOCKEN_bm;//Lock the Clock from further adjustments
    
    
    //CPU_CCP = 0xD8;
}

// Setup of the Watchdog Timer
//
void watchdogSetup(void)
{
    wdt_reset();
    CPU_CCP = 0xD8;
    WDT.CTRLA = 0xA;
}

// Setup of the ms Timer
//
void TCA0_init(void)
{
    // Enable the overflow interrupt
    TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm;
    
    // Set Normal mode
    TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_NORMAL_gc;
    
    // Disable event counting
    TCA0.SINGLE.EVCTRL &= ~(TCA_SINGLE_CNTEI_bm);
    
    // Set the period, Main Clock / Main Clock Prescaler * 0.001
    TCA0.SINGLE.PER = 0x03E8; //10MHz / 1000 = interrupt service routine every 100us  // old value: 0x0D05;
    TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV1_gc; //select main clk without dividing
    TCA0.SINGLE.CTRLA = TCA_SINGLE_ENABLE_bm; //enable single shot mode of counter
}

// Millisecond Timer Interrupt
//
ISR(TCA0_OVF_vect)
{
    PORTF.OUTTGL = PIN2_bm;
    //PORTF = PORTF ^ 0x02;  // testing timer
    
    milliVal++;
    TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm;
}


// Returns the time since power-on in ms
//
unsigned long millis(void)
{
    return milliVal; // now 0.1 milli second
}

// Delays execution for so many ms (placeholder)
//
void delay(unsigned int delayTime)
{

}

void initialSetup(void)
{
    // Set All Port Directions
    PORTF.DIRSET = PIN5_bm;// set LED direction.
    PORTF.OUTCLR = PIN5_bm;// turn off LED.
    
    //Configure test pin as output
    PORTF.DIRSET = PIN2_bm;
    PORTF.OUTCLR = PIN2_bm;


    PORTA.DIRSET = PIN7_bm; // set clk output pin as output
    //PORTA.DIRCLR = PIN7_bm; // clear clock output pin

    CLKSetup();
    
    // Initialize and start global ms timer
    //
    TCA0_init();
    sei();
    
    while (5000 > millis())
    {
        blinky((millis() / 1000), ((5000 - millis()) / 1000));
    }

    PORTF.OUTSET = PIN5_bm;// turns on LED
    
}

void blinky(unsigned int onTime, unsigned int offTime)
{
    if ((isOn == 1) && ((blinkTime + onTime) <= millis()))
    {
        isOn = 0;
        PORTB.OUTCLR = PIN5_bm;
        PORTF.OUTSET = PIN5_bm;
        blinkTime = millis();
    } else if ((isOn == 0) && ((blinkTime + offTime) <= millis()))
    {
        isOn = 1;
        PORTB.OUTSET = PIN5_bm;
        PORTF.OUTCLR = PIN5_bm;
        blinkTime = millis();
    }
}

Ch1: PinA7
Ch2: PinF2

oscilloscope readings

Picture of setup: enter image description here

\$\endgroup\$
2
  • \$\begingroup\$ For ballparking I make a program with nothing but delay for loops to toggle LEDs every 0.5, 1, or 2 seconds. Something slow that needs many many loops to drown out one-time overhead that is human countable. I kind of look at the loop and guess how many instructions it looks like it will take. Then I adjust clock settings and see if it actually responds by double or halving. \$\endgroup\$ Commented Feb 3, 2022 at 15:14
  • \$\begingroup\$ Try to use _PROTECTED_WRITE(reg, value) macro to enable CLK on A7 pin. \$\endgroup\$ Commented Feb 3, 2022 at 16:21

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.