Select Page

The last post we wrote some code to get an Astable output on the PIC10F322. However the PIC10F322 has a NCO – (Numerically Controlled Oscillator).

What this does – and without too much hair pulling – you can get an astable output on PORT.A2 up to 500khz using the internal clock.

How the NCO works.

The NCO is composed of an Adder, Increment Register, and Accumulator.

On the rising edge of the input clock. The value stored in the increment register(s) 16bits in size is added to the value in the Accumulator 20bits in size. When the Accumulator overflows a selectable action happens, you can output a fixed duty cycle, a pulsed frequency, or cause an interrupt to occur.

In this case we will use it to generate a 500Khz clock signal on Port.A2.

By selecting the clock source:
NCO1CONbits.N1PFM to fixed duty cycle

We get a 500Khz, output.

So, how do we change it to some other frequency.

Here is the math {Desired Freq in hz} x 2 x 2^20 / {CPU Frequency}
2^20 is 1048576 – which is the max value that the Accumulator can store.

For a 330Khz output it would be.
330,000 x 2 = 660,000
660,000 x 048576 = 692,060,160,000
692,060,160,000 / 16000000 = 43,253.76
Round 43,253.76 to 43,254 convert it to HEX (0xA8F6)

We replace – 0xFFFF value we are setting the NCO1INC with 0xA8F6 – to get… very very close to 330Khz

Some other things to keep in mind..

Apparently some datasheets are wrong – this is the correct NCO clock source select bits below.

bit 1-0 NxCKS<1:0>: NCOx Clock Source Select bits
11 = LC1OUT
10 = HFINTOSC (16 MHz)
01 = FOSC
00 = NCO1CLK pin

You can also use the NCO1CLK pin – as a clock input and provide your own clock source and use the NCO to divide this clock.

Also, which I haven’t experimented with it yet, NCO1CONbits.N1PFM can be set to operate in Pulse Frequency mode. When the overflow of the Accumulator happens, it will generate a pulse – the width of the pulse is defined by

N1PWS<2:0>: NCO1 Output Pulse Width Select bits
111 = 128 NCOx clock periods
110 = 64 NCOx clock periods
101 = 32 NCOx clock periods
100 = 16 NCOx clock periods
011 = 8 NCOx clock periods
010 = 4 NCOx clock periods
001 = 2 NCOx clock periods
000 = 1 NCOx clock periods

The Code

 * File:  NCO_example.c
 * Author: Jamie Starling - 
 * Created on:  September 10, 2021, 7:45 PM
 * Code/Circuit provided as-is.

#include <xc.h>
#include <stdint.h>

//Device Configuration
#pragma config FOSC = INTOSC  // Oscillator Selection 
#pragma config BOREN = ON    // Brown-out Reset
#pragma config WDTE = OFF    // Watchdog Timer
#pragma config PWRTE = ON    // Power-up Timer
#pragma config MCLRE = OFF   // MCLR Pin Function Select bit->MCLR pin function is digital input, MCLR internally tied to VDD
#pragma config CP = OFF      // Code Protection 
#pragma config LVP = OFF     // Low-Voltage Programming 
#pragma config LPBOR = ON    // Brown-out Reset Selection bits
#pragma config BORV = LO    // Brown-out Reset Voltage Selection
#pragma config WRT = OFF    // Flash Memory Self-Write Protection

//Used to calculate the delay time - Change depending on processor Speed
#define _XTAL_FREQ 16000000  //16Mhz

void setup(void);

void main(void)

void setup(void)
    //Set the System Clock - You can change this to match the setting you are looking for
    OSCCONbits.IRCF = 0b111;  //Set System Clock to 16Mhz FOSC/4 = 4Mhz
    TRISAbits.TRISA2 = 0; //Make sure to Set A2 to output - otherwise does not work.
    NCO1CLKbits.N1CKS = 0b01; //Clock Source Select bits - Set to FOSC
    NCO1INC  = 0xFFFF; //Adder value
    NCO1CONbits.N1PFM = 0; //NCO operates in Fixed Duty Cycle mode
     NCO1CONbits.N1EN = 1; //Enable NCO
     NCO1CONbits.N1OE = 1; //Enable Output     

Let’s talk!

I am always looking for oppunities to put my skills to work.
I am always looking to connect with like minded people.

Want to connect – drop me an email