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:
NCO1CLKbits.N1CKS to FOSC
NCO1INC to 0xFFFF
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 - GizoFoundry.com
*
* 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

//Prototypes
void setup(void);

void main(void)
{
setup();

while(1)
{
}
}

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
NCO1CONbits.N1PFM = 0; //NCO operates in Fixed Duty Cycle mode

NCO1CONbits.N1EN = 1; //Enable NCO
NCO1CONbits.N1OE = 1; //Enable Output
}
``````