Saturday, November 22, 2014

XMega - The Clock

The Clock

Most of the time the first tutorial article is the classic "Hello World" application, usually blinking an LED for microcontroller applications. This time, I want to start a little lower, I've found the Clock system to be especially difficult to understand when using the ASF (Atmel Software Framework). There are several steps in different areas and there are #define statements that are like bad magic because they either work or they don't. I also want to learn how to better use some test equipment that I've picked up. I buy cool tools but don't always use them to their best advantage.

XMega Programmer

  • Atmel-ICE Basic - Supports Hardware Debugging 
    • $49 - Pretty Case (The one I'm using)
    • $32 - Circuit Board (Less expensive alternative)

Test Equipment Used

  • Frequency Counter - Tektronix CFC250 100 MHz (circa 1988)

Experiment

As you can see my tools aren't expensive or fancy. 

The code for this first experiment will be pretty minimal. Just setting up a built-in feature that takes the System Clock and places its output on a physical pin. Adjust the code as needed depending on which pins are available on your board.

The Code

I'm not going to get caught up in the step by step. For this example, I created a new project with the "GCC C ASF Board Project" template and then selected my MicroController, then the "User Board template".
The files  to edit are a little scattered, so here are the changes I made.

src\ASF\common\boards\user_board\user_board.h
Add Line:  
#define FREQ_OUT  IOPORT_CREATE_PIN(PORTC, 7)
src\ASF\common\boards\user_board\init.c
inside the board_init function, add this line: 
ioport_set_pin_dir  (FREQ_OUT, IOPORT_DIR_OUTPUT);
src\main.c
Replace entire main()
int main(void)
{
     // Specifies that the Clock frequency is sent out on PortC Pin7.
     PORTCFG.CLKEVOUT = PORTCFG_CLKOUT_PC7_gc;
     sysclk_init();

     for (;;){}
}

The Result

The Frequency Counter* showed fluctuations between 2,033,386 and 2,032,973 Hz

What do those results really mean?

We have two different versions of accuracy.
  1. Frequency isn't exactly 2 MHz
  2. Variation between the high and low value
So how far off from 2 MHz is it?
Accuracy = (Measured Frequency - Expected Frequency) / Expected Frequency

0.0166 =  (2,033,386 - 2,000,000) / 2,000,000 = 1.66%
0.0168  = (2,032,973 - 2,000,000) / 2,000,000 = 1.68%

That's a bit sloppy. We can do better as we will see, but that is good information.

Next up is the "wiggle". Since we calculated the percentage for both the high and low value, we can subtract to find the difference 0.0002 or 0.02% which is a good number for a built in oscillator. 

How important is the accuracy?

If we are talking about buttons and LED's it is nothing. If we are talking about communication, it is very important. 

How to Improve Accuracy

The XMega includes a built in calibration feature. Lets see how much closer we can get to our goal.

\src\config\conf_clock.h
Add Line (or uncomment)
 
#define CONFIG_OSC_AUTOCAL_RC2MHZ_REF_OSC   OSC_ID_RC32KHZ
With that done the frequency counter is now showing 1,998,172 to 1,997,508.  Using the above formula:

0.001461 = (1,997,078 - 2,000,000) / 2,000,000 = 0.14%
0.001300 = (1,997,401 - 2,000,000) / 2,000,000 = 0.13%

While the frequency is now below 2,000,000 it is closer with a variation of 0.13% compared to 1.66%, which is a great improvement. The variation between the tested values is 0.01% which is a small change in the right direction compared to the 0.02% without the Calibration setting.

32 MHz Internal Oscillator

Here are some quick stats doing the same tests at 32 MHz.

Observed Values High: 32,449,486 and Low: 32,308,628.

0.009644 = (32,308,628 - 32,000,000) / 32,000,000 = 0.96%
0.014046 = (32,449,486 - 32,000,000) / 32,000,000 = 1.40%

Wiggle: 0.014046 - 0.009644 = 0.44%

32 MHZ Internal Oscillator w/Calibration 
\src\config\conf_clock.h
Add Line (or uncomment)
 
#define CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC  OSC_ID_RC32KHZ

Observed Values High: 31,932,746 and Low: 31,911,475.

0.002766 = (31,911,475 - 32,000,000) / 32,000,000 = 0.27%
0.002101 = (31,932,746 - 32,000,000) / 32,000,000 = 0.21%

Wiggle: 0.002766 - 0.002101 = 0.066%

Remember that manufacturing tolerances will affect these settings, so while this chip seems to have a more accurate 32 MHz oscillator that may not always be true.

See a future post for more examples, including external crystals!

Additional observations

During most of the debug process, the frequency counter showed 1,000,038 or 1,000,039. The frequency counter reading is very accurate so I doubt it's an internal clock. Since it showed those values when the Crystal wasn't used, I think it's a clock from the debugger.

It appears that when the debugger is connected and not in debug mode it's probably holding the microcontroller in reset, since the frequency counter shows 0.

*Frequency Counter Accuracy - It's not calibrated against anything official. I did compare the output of my 4 digit Function Generator and the 8 digits on the frequency counter and the first 4 digits match at 2 MHz so FG 2000 = FC _2000214. 

No comments:

Post a Comment