PIC 16F1509 NCO code sample

I didn’t read a forum post all the way through (or maybe I was just tired) and I accidentally responded to question about PWM; however the question was specifically about using the numerically controlled oscillator (NCO). I decided to take a look at this module and wrote some quick code. I also have been testing hardware for isolating PWM signals… so I married them together despite not being how I would use this in a real world application.

The NCO code worked great and was easy to set up. I used a simple loop to have it sweep a frequency… dumped the output of NCO1 (RC1) into a optoisolator which originally I was driving it way to fast… well unfortunately my isolation circuitry wasn’t quite up to the challenge of the speed but in the lower end of my sweep I got adequate results and ultimately the NCO test was very successful. While I was reading up on the NCO in the 16F1509 manual I started reading the configurable logic cell (CLC) module section. What a surprise to find this block in a 16F series microcontroller! The CLC is definitely going to get some more attention from me in the future. As always sample code follows below…

 

I had answered a question about a PWM signal a while back and responded with some PWM code ... well I didn't read it all and they were wanting to use NCO. I hadn't used it... so I just hacked some stuff together to check it out.
I had answered a question about a PWM signal a while back and responded with some PWM code … well I didn’t read it all and they were wanting to use NCO. I hadn’t used it… so I just hacked some stuff together to check it out.

 

So the important stuff! The code written for the Microchip XC8 compiler:

No warrantee and don’t assume it’s free of bugs. It free to steal; enjoy. Code fix recommendations in the comments please.

Download: 16F1509_NCO.c

* File: main.c
 * Author: Charles M Douvier
 * Contact at: http://iradan.com
 *
 *
 * Target Device:
 * 16F1509 on Tautic 20 pin dev board
 *
 * Project:
 *
 *
 * Version:
 * 1.0
 *
 */
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 4000000 //4Mhz FRC internal osc
#define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))
#endif
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//config bits
#pragma config FOSC=INTOSC, WDTE=OFF, PWRTE=OFF, MCLRE=ON, CP=OFF, BOREN=ON, CLKOUTEN=OFF, IESO=OFF, FCMEN=OFF
#pragma config WRT=OFF, STVREN=OFF, LVP=OFF
#define _XTAL_FREQ 4000000 //defined for delay
int count;
/*
 *
 *
 *
 * NCOxCON: NCOx CONTROL REGISTER
 * bit 7 NxEN: NCOx Enable bit
 * 1 = NCOx module is enabled
 * 0 = NCOx module is disabled
 * bit 6 NxOE: NCOx Output Enable bit
 * 1 = NCOx output pin is enabled
 * 0 = NCOx output pin is disabled
 * bit 5 NxOUT: NCOx Output bit
 * 1 = NCOx output is high
 * 0 = NCOx output is low
 * bit 4 NxPOL: NCOx Polarity bit
 * 1 = NCOx output signal is active low (inverted)
 * 0 = NCOx output signal is active high (non-inverted)
 * bit 3-1 Unimplemented: Read as ‘0’
 * bit 0 NxPFM: NCOx Pulse Frequency Mode bit
 * 1 = NCOx operates in Pulse Frequency mode
 * 0 = NCOx operates in Fixed Duty Cycle mode
 *
 * NCOxCLK: NCOx INPUT CLOCK CONTROL REGISTER
 * bit 7-5 NxPWS<2:0>: NCOx Output Pulse Width Select bits(1, 2)
 * 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
 * bit 4-2 Unimplemented: Read as ‘0’
 * bit 1-0 NxCKS<1:0>: NCOx Clock Source Select bits
 * 11 = NCO1CLK pin
 * 10 = LC1_out
 * 01 = FOSC
 * 00 = HFINTOSC (16 MHz)
 * Note 1: NxPWS applies only when operating in Pulse Frequency mode.
 * 2: If NCOx pulse width is greater than NCO_overflow period, operation is undeterminate.
 *
 */
int main(void) {
 // set up oscillator control register, using internal OSC at 4MHz.
 OSCCONbits.IRCF = 0x0d; //set OSCCON IRCF bits to select OSC frequency 4MHz
 OSCCONbits.SCS = 0x02; //set the SCS bits to select internal oscillator block
 OPTION_REGbits.nWPUEN = 0; // enable weak pullups (each pin must be enabled individually)
TRISCbits.TRISC0 = 0; // output
 TRISCbits.TRISC1 = 0; // NCO1
 TRISCbits.TRISC2 = 0; // output
 TRISCbits.TRISC3 = 0; // output
 TRISCbits.TRISC6 = 1; // input
 TRISCbits.TRISC7 = 1; // input
ANSELC = 0x00; // all port C pins are digital I/O
NCO1INCH = 0x00; // has to be set before INCL
 NCO1INCL = 0x4F; // low accumulator register
NCO1CLK = 0xE1; // 0xE1 = PW 128 clk 0x41 [010][000][01] 8 CLK PER, INT OSC,
 NCO1CON = 0xE1; // Enable, Ouput On, PWF Mode
count = 0;
while(1)
 {
 count = count+1; //just a little test code
 if (count < 1) //LED didn't like the low freq
 count=10;
 NCO1INCH = 0x00; //has to be set before INCL
 NCO1INCL = count;
 __delay_ms(50);
 }
 return (EXIT_SUCCESS);
}


					
					

Leave a Reply