{
init();
SLEEP();
while (1);
}
The compiler of choice is the HI-TECH C Compiler for
PIC10/12/16 MCUs. The init() function disables the
PIC16(L)F1507’s analog-to-digital module and sets up the
CLC registers. I’ve put the PIC16LF1507 to sleep to show
that the CLC can operate while the CPU is in sleep mode.
The CLC is also capable of using internally generated
signal sources. Screenshot 5 depicts a CLC configuration
that substitutes the NCO (Numerically Controlled Oscillator)
output for our pushbutton. We already know that whatever
the NCO emits as a signal will appear at the CLC1 output.
Before we can see the NCO output, we must configure the
NCO to generate a signal for us.
NUMERICALLY CONTROLLED
OSCILLATOR PRIMER
The NCO module consists of a clock source, a 16-bit
increment register, and a 20-bit accumulator. The 16-bit
increment value is loaded into the accumulator on every clock
cycle. The raw NCO signal is generated when the accumulator
overflows with a carry. Since the NCO period changes in discrete
steps, the resulting raw NCO signal is an average frequency.
In Fixed Duty Cycle (FDC) mode, the raw NCO signal is
gated to a D flip-flop wired in divide by 2 mode. The output
of the D flip-flop is a signal with a 50% duty cycle that has a
frequency of one half of the input signal. The final NCO
signal can be routed internally to the CLC or out to a
PIC16(L)F1507 I/O pin. The 16-bit increment value is
determined by manipulating this formula:
FOVERFLOW
NCO Clock Frequency x Increment Value
n = Accumulator width in bits
2”
Where: FOVERFLOW = Accumulator Overflow Frequency
NCO Clock Frequency = 16 MHz
Increment Value = 16-bit Increment Value
n = 20
2n = 1,048,756
For this discussion, we will use the maximum frequency
of the PIC16(L)F1507’s internal oscillator which is 16 MHz.
We want to solve for Increment Value. So, we can do a little
algebraic manipulation to arrive at this:
Increment Value = (2n x (2 x FOVERFLOW)) / NCO
Clock Frequency
Just in case you’re wondering why FOVERFLOW is
multiplied by 2, remember that we need to double the
accumulator overflow count which becomes our NCO out
frequency. To verify our math, let’s set up our NCO to
output a frequency of 1.0 kHz:
56 February 2012
Increment Value = (1,048,576 x (2 x 1000))
/ 16,000,000
Increment Value = 131.072 or 0x83
Now that we have an increment value, let’s apply it
with some PIC16(L)F1507 C code. We’ll begin by enabling
the NCO output I/O pin:
//Turn off ADC
ADCON0bits.ADON = 0;
ANSELA = 0;
ANSELB = 0;
ANSELC = 0;
TRISA = 0b11111011;
TRISB = 0b11111111;
//Set NCO output pin (RC1)
TRISC = 0b11111101;
In that we are relying on the PIC16(L)F1507’s internal
oscillator, let’s make sure it is configured to run at 16 MHz:
OSCCONbits.SCS1 = 0;
OSCCONbits.SCS0 = 0;
OSCCONbits.IRCF3 = 1; //Set IRCF0-3 to run
//16 MHz
OSCCONbits.IRCF2 = 1; //
OSCCONbits.IRCF1 = 1; //
OSCCONbits.IRCF0 = 1; //
To run in FDC mode, we must clear the NCO1CON’s
N1PFM bit. To let the NCO signal out of the
PIC16(L)F1507’s RC1 I/O pin, we must set the N1OE bit in
the NCO1CON register. The NCO module is enabled and
its output polarity is also controlled by bits in the
NCO1CON register:
//Enable the NCO
//Enable the NCO
//output on RC1
NCO1CONbits.N1POL = 1; //Set polarity
NCO1CONbits.N1PFM = 0; //Enable FDC mode
Here’s how we select the PIC16LF1507’s HFINTOSC
and set our NCO clock rate at 16 MHz:
NCO1CONbits.N1EN = 1;
NCO1CONbits.N1OE = 1;
NCO1CLKbits.N1CKS1 = 0; //Select the HFINTOSC
//(16 MHz)
NCO1CLKbits.N1CKS0 = 0;
Loading the NCO increment register with our
calculated value of 0x83 produced an average NCO output
frequency of 998 Hz. So, I decided to load 0x84:
NCO1INCH = 0x00;
NCO1INCL = 0x84;
The NCO code we’ve just written was added to the
original init() function. The NCO module is also capable of
running independently of the CPU. So, I used the same
main() code that we used to run the CLC. With the
PIC16(L)F1507’s CPU sleeping, I used the Electronics
Explorer’s oscilloscope functionality to capture the NCO’s
output signal in Screenshot 6.
The NCO output is linear with respect to the increment
value. Now that we’ve calculated the 1 kHz increment
value, to get 2 kHz out of the NCO we simply double the 1