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);
}

	

Testing an LCD with the PIC 16F1509 and the XC8 compiler

Nuts and Volts, January 2014 had an article named “The (Nearly) Universal Process Monitor”. The whole magazine had a number of Microchip PIC based articles which is rare these days, as the articles win out to other platforms such as MSP430, Propeller, and Arduino. The article is a pretty nice project but I went to download the code and it’s just a HEX file. Lame! I’ve been guilty of this and I promise never to do it again.

If you’re as disenchanted with building something without modifiable code as I am here is a starting block! I don’t normally program in C but I’m trying to force myself so I can get better. You can trim down many timing delays, and certainly shouldn’t be a problem to optimize my code as I made no effort to do so myself.

LCD+A/D test on the PIC

 

When writing the A/D math for this I found some interesting issues; here is one of those: (in pseudo code)

int_Var1 = 8-bit A/D conversion
long_int_Var2 = int_Var1 * 5000

given int_Var1 = 17  long_int_Var2 should equal 85000 but it didn’t; It came out 19,464 (roll over from 65,536).

However:

long_int_Var2 = int_Var1
long_int_Var2 = long_int_Var2 * 5000  //works like a charm.

Weird? I tried this in an ANSI C compiler and the first equation worked okay; I guess this is just a quirk about XC8. I somewhat understand why it would act that way and caught it quick but it could easily have been a difficult bug to hunt down.

There is obviously not the greatest amount of resolution in an 8-bit conversion but I was really just testing an LCD I just got off eBay and through this would be a fun way to do so, work on my C skills, and help out anyone wanting a head-start on building their own metering application. If you don’t want to do the math yourself you’ll find you get about 20mV/step resolution (5000mV/256) at 8-bit.

 

The thousands position is moot and could be dropped. The resolution of the A/D being used in 8-bit doesn't allow for reliable usage in the thousandths.
The thousands position is moot and could be dropped. The resolution of the A/D being used in 8-bit doesn’t allow for reliable usage in the thousandths.

 

Notes: Refresh is slow, clearing the LCD line #2 is slow because I didn’t like the flash of clearing the whole display… it could have also been made more quick had I not written 16 spaces and just written enough to cover my 7 digits of output. I also should have dropped the LSB of my number because it’s a worthless bit considering my resolution. I will if this gets used on anything other than a breadboard test.

I used a standard 44780 16×2 LCD, a Tautic development board, and a PIC 16F1509 (happens to come with the dev board). For programming I used MPLAB X IDE v1.95 and XC8 v1.21 (free version) and the PICkit 3 programmer. The code is commented enough to figure out the hardware setup.

code (with whatever fixes since wiring the blog) can be found at : https://github.com/chasxmd/iradan.com-2014

at writing it looks like:

/* 
 * File: main.c
 * Author: Charles M Douvier
 * Contact at: http://iradan.com
 *
 * Created on January 18, 2014, 9:42 AM
 *
 * Target Device:
 * 16F1509 on Tautic 20 pin dev board
 *
 * Project:
 * A/D --> LCD Test
 * 8-bit resolution across Vdd to Vref (0-5V)
 * for 3.3V operation adjust A/D math
 *
 * LCD (44780 type) Test with XC8 compiler
 * LCD code ported from Mike Pearce's 2001 LCD code for HI-TECH C
 * as found on http://www.microchipc.com/
 */
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <plib.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 an9_value; //value for a/d
 char buf[10]; //buff for iota
 long int fvar; //long for format math
 long int ones; //left of decm
 long int decm; //decimal places
 int tempi; //to add leadign zeros..
/*
 * LCD RS LATA.5
 * LCD EN LATA.4
 * LCD DATA4 LATC.0
 * LCD DATA5 LATC.1
 * LCD DATAT6 LATC.2
 * LCD DATA7 LATC.3
 * LED LATA.0 for scan rate/heartbeat
 */
void lcd_strobe (void) //TOGGLE LCD_EN
{
 LATAbits.LATA4 = 0;
 __delay_ms(20);
 LATAbits.LATA4 = 1;
}
/* write a byte to the LCD in 4 bit mode */
void lcd_write(unsigned char c)
{
 LATC = c >> 4;
 lcd_strobe();
 LATC = c;
 lcd_strobe();
 __delay_us(100);
}
/*
 * Clear and home the LCD
 */
void lcd_clear(void)
{
 LATAbits.LATA5 = 0;
 lcd_write(0x1);
 __delay_ms(2);
}
/* write a string of chars to the LCD */
void lcd_puts(const char * s)
{
 LATAbits.LATA5 = 1; // write characters
 while(*s)
 lcd_write(*s++);
}
/*
 * Go to the specified position
 */
void lcd_goto(unsigned char pos)
{
 LATAbits.LATA5 = 0;
 lcd_write(0x80+pos);
}
/*
 * Write 16 spaces on LCD 2 to avoid blanking, (ugly CLEAR effect)
 * this is slow but work for my needs
 */
void lcd_clrline2(void)
{
 lcd_goto(40);
 lcd_puts(" ");
 lcd_goto(40);
}
/* initialise the LCD - put into 4 bit mode */
void lcd_init(void)
{
 LATAbits.LATA5 = 0; // write control bytes
 LATC = 0x03;
 __delay_ms(150); //power on delay
 lcd_strobe();
 __delay_ms(5);
 lcd_strobe();
 __delay_ms(5);
 lcd_strobe();
 __delay_ms(5);
 LATC = 0x02; // set 4 bit mode
 __delay_ms(5);
 lcd_strobe();
 __delay_ms(5);
 lcd_write(0x28); // 4 bit mode, 1/16 duty, 5x8 font
 lcd_write(0x08); // display off
 lcd_write(0x0C); // display on cursor+blink off
 lcd_write(0x06); // entry mode
}
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
TRISCbits.TRISC0 = 0; // output
 TRISCbits.TRISC1 = 0; // output
 TRISCbits.TRISC2 = 0; // output
 TRISCbits.TRISC3 = 0; // output
 TRISAbits.TRISA0 = 0; // output
 TRISAbits.TRISA4 = 0; // output
 TRISAbits.TRISA5 = 0; // output
 TRISCbits.TRISC7 = 1; //analog input
 ANSELCbits.ANSC7 = 1; //...setup on PORTC.7/AN9
 LATAbits.LATA0 = 0; //LED Im-Alive test
__delay_ms(250); //let the power settle
lcd_init();
 __delay_ms(10);
 lcd_clear();
//display test message
 lcd_puts("Testing the LCD.");
 lcd_goto(40);
ADCON0 = 0b00100101; //select AN9 and enable
/* ADCON1
 * bit 7 ADFM: ADC Result Format Select bit
 * 0 = Left justified. Six Least Significant bits of ADRESL are set to ?0? when the conversion result is loaded.
 * bit 6-4 ADCS<2:0>: ADC Conversion Clock Select bits
 * 110 = FOSC/64
 * bit 3-2 Unimplemented: Read as ?0?
 * bit 1-0 ADPREF<1:0>: ADC Positive Voltage Reference Configuration bits
 * 00 = VREF+ is connected to VDD
 */
 ADCON1 = 0b01100000; //left justified, FOSC/64 speed Vref=Vdd
while(1)
 {
 LATAbits.LATA0 = 0; //debugging

 lcd_clrline2(); //clear LCD line 2 by writting " " and return
__delay_us(5); 
 GO = 1;
 while (GO) continue; //wait for conversion
 an9_value = ADRESH; //AN9 value
 //format value for LCD read out
 //value = AD_value * 5000 (because 5000mV is Vref)
 //value = value / 256 (8 bit number)
 fvar = an9_value;
 fvar = fvar * 5000;
 fvar = fvar / 256;
 ones = fvar / 1000;
 ones = ones % 10;
 decm = fvar % 1000;
LATAbits.LATA0 = 1; //LED Im-Alive test. I made it through conversion
//page 366 of XC8 user guide
 itoa(buf,ones,10); //int conv to buffer
 lcd_puts(buf); //outputs "1s" place to LCD.
 lcd_puts(".");
 //page 374 of XC8 user guide
 ltoa(buf,decm,10); //long conversion to buffer
 tempi=strlen(buf); //uh, adding leading zeros..
 tempi=3-tempi; //probably a better way of doing thing
 while (tempi) //first figure out how many zeros
 {
 lcd_puts("0"); //missed 3-string length
 tempi=tempi-1; //then send them until done
 }
 lcd_puts(buf); //output buffer to LCD
lcd_puts(" V"); //attach some units for display
 //delay
 __delay_ms(999); //LCD refresh rate
 }
 return (EXIT_SUCCESS);
}

Quickstart guide to a basic PIC based robots – Part 1

While browsing for “goodies” on eBay I ran across a $9 robot chassis. How can you go wrong for $9? I haven’t built a robot since Talus my sumo Roomba, so I thought why not.

If you’re looking for something like the model I purchased, check out eBay and do a search for “Robot Chassis”.  Adam Fabio of TheRegnineer.com mentioned he has almost completed working on a product that is similar. I’m guessing you can look for Adam’s product at his Tindie Store once he has finished it.

.. Fast forward three weeks for shipping from China.

None of my sensors have arrived but you’ll end up wanting to customize you robot for whatever sensor pack you are interested in anyhow. With that said I haven’t written any code for handling any sensors and at the end of the day this robot is just going to drive straight forward all day long. You can follow the code at the repository I set up for it on github to get the latest updates at…

The software:

https://github.com/chasxmd/16F1509_Rover_Robot

The hardware:

I’m using the TAUTIC 20 pin PIC development board as it’s only $10 and takes care of the reset switch capacitor and comes on a nice plug-in board if you solder the connectors the same way I did. Use whatever you like but notice I’m using an internal oscillator so you don’t have to worry about getting a specific development board or having a crystal.

I’m also using the Pololu Quick 2s9v1 Dual Serial Motor Controller which is cost me $25, a little on the high side, but I had one from another project so I’m just re-using it and it makes life a lot easier for development.

Check out the photo at the bottom of the post for the basic schematic.

Beginners:

If you don’t already have MPLABX you’re looking at an upwards battle. However if you don’t mind watching a few YouTube videos it’s not up a creek.

1. Download and install MPLABX and the HI-TECH C compiler.

2. Start a project within MPLABX; selecting PIC 16F1509 and choosing the HI-TECH compiler, and create a main file.

3. Copy my code off the github site and drop it into your main file and compile.

You can download the free version of HI-TECH C and MPLABX which is also free. They are both obtained from http://www.microchip.com. MPLABX is an IDE (integrated development environment) which means it’s a program for programming, compiling and loading your software. HI-TECH is a C compiler which works with MPLABX. There are other programming language options such as BASIC and even assembly (I use assembly most of the time). I don’t know of any free BASIC compilers but I’m guessing someone has one. Google might be your best friend if  you’re looking to go that route.

If you don’t have MPLABX you probably don’t have a PICKit 3 (or other hardware programming tool). I like the PICKit 3 because it will program all the newer Microchip PICs and it’s just about the most affordable tool for PICs. PICKit3 comes from Microchip or Digi-key. There are alternatives.

The Build:

It took me about 30 minutes to put the chassis kit together last night. It was pretty obvious how it went together which was good because there were no directions. The encoder wheels don’t really attach other than compression, I see issues with that if I end up using them… that’s what you get for $9?

The code I put together this morning in about an hour or two after reviewing the manual for the motor driver online; you should also review this document. The idea with the code was just to test the motors and motor driver. I also selected a high/half/normal speed which you can adjust for your motor’s needs. I believe the highest speed setting you can select is 0x7F, I chose 0x4F for my high speed based on my anticipated desire. Adjust as needed.. but keep in mind your low speed should be set so it doesn’t stall on carpet or whatever you want your robot to be driving around on.

That’s about it for now. Once I get some sensors in I’ll add them and then write the code. I’m still new to C programming but I felt it was a better choice since it seems most popular; I usually write everything in assembler. Check out the photo I posted as it has a basic layout of the circuit and how I set mine up on a breadboard until I receive some prototyping PCBs I ordered.

First step of my cheap chassis robot build... getting the motors turning.
First step of my cheap chassis robot build… getting the motors turning.

 

…. to be continued

WWVB Time Signal Generator Test w/ HEX

[Edit: I’ve added the .asm code in the “Code” page in the menu above. Below you can find the .HEX file for easy programming]

A successful test on my WWVB signal generator. I’m going to shy away from calling it a transmitter because I don’t think there is any allowances for any broadcasting on 60KHz, so to stay legal I would imagine you’d need to conform to part 15, shield everything, use an attenuator and dump the signal into a shielded box with the clock? I somehow doubt the FCC checks up on sub-mW transmissions on 60KHz though.

The concept is simple, 1 baud rate transmission of a 60 frame packet. The amplitude shift keying (ASK) system WWVB transmits is recreated using a CMOS CD4066 switch. Dump a 60KHz sine wave (keeping in mind maximum input/output signal specifications) into one of the switch ports. Use the output on PORTB.0 of the PIC to control the switch and the other side of the switch goes to you device under test (I used a couple feet of wire as an antenna and just placed the wire in the neighborhood of the clock receiver). It’s a no brainer. Check out the NIST site on WWVB if you want more details. I’ll probably re-port the code to a 12F629 when I get my new PICKit3 in and I’ll likely build a board with a 60KHz generator.. maybe I’ll even sell it on Tindie if I’m feeling ambitious.

The Test! I was getting my ass kicked earlier this week as my circuit was not working and it seemed like everything was just right. It did force me to really tweak my timing to make it within my range of error on being able to measure the exact pulse widths, I don’t know how precise it has to be but I assume that’s up to the algorithm decoding the signal. Turns out it wasn’t my code or circuit.. My $15 Fred Meyer “black friday special” atomic clock doesn’t work. It won’t receive the real WWVB (set up aligned with Boulder, CO away from electronics, blah blah). I was getting the proper signals out of the module, so I yanked the module out of the clock and hooked it up to a receiver designed by N0QBH. I mirrored his project here. He has a website for the project here. I used his schematic, ditched the need for the LCD and just grabbed my data off the RS232. Done! You can see a before and after output screenshot in the photos below.

My WWVB signal generator code (HEX) for a 16F628A is found here . Is it lame of my just to provide the HEX? yeah…. but all you need to do is hook up PORTB.0 to switching input of a 4066 with a signal generator feeding a 60KHz sine wave and you’re in business. (And a resistor pulling /MCLR (PORTA.5) up as well if that wasn’t obvious? I’m using the internal oscillator; no xtal needed).  You are stuck with my fixed date of course.. which is why you want my assembly code right? No problem. Just ask… really (comment or e-mail). I don’t want to post it because I don’t really like comment trolls. This code is super BETA but at an acceptable starting point. Lots of opportunity for optimizing it as well.  Why didn’t I improve on this code? Because I don’t need to. I’m just using it to test receivers I’ve purchased from the UK and I’ll be working on a project with those in a little while.

My time/date is static here is a snippet of the main line code:

    CALL    MARKER                      ;MARKER FRAME REFERENCE BIT
    CALL    ONE                         ;40min
    CALL    ZERO                        ;20min
    CALL    ZERO                        ;10min
    CALL    ZERO                        ;Reserved
    CALL    ZERO                        ;8mins
    CALL    ZERO                        ;4mins
    CALL    ONE                         ;2mins
    CALL    ZERO                        ;1mins
    CALL    MARKER                      ;MARKER 1

… and so for some photos

signal from PIC before ASK modulation accomplished by switching a CMOS CD4066 with a 60KHz sine wave from a frequency generator.
signal from PIC before ASK modulation accomplished by switching a CMOS CD4066 with a 60KHz sine wave from a frequency generator.

 

WWVB receiver module removed from clock

The clock with the module removed, luckily they printed the pin diagram on the board. 5V, Gnd, PON, and TCO

WWVB Signal Generator and Receiver on Breadboard

Both the generator and receiver on the breadboard. The transistors form the RS-232 driver for the receiver.

Before and after on the RS232 output of the WWVB receiver
Before and after on the RS232 output of the WWVB receiver

 

PWM on the PIC16F1509 in ASM

[Edit: If you’re looking for NCO (numerically controlled oscillator) usage instead of the PWM module take a look here instead. However note the code is in C (for XC8) not ASM]

Another lazy Sunday… A lot of OT the last few weeks at work and Sunday about the only day I have for relaxation so to clear my mind I wrote some test code for Pulse Width Modulation on a development board I purchased from @TINDE made by @TAUTIC . I’ll attach the code for anyone to use.

MPLAB on the laptop with a @TAUTIC / @TINDE dev board with a PWM test output.
MPLAB on the laptop with a @TAUTIC / @TINDE dev board with a PWM test output.

The code outputs on PWM1 (RC5) at about 1Khz at just under 50% duty cycle but that easy to change if you read the Microchip 16F1508/9 spec sheet section 23.

;*******************************************************************************
;                                                                              *
;    Microchip licenses this software to you solely for use with Microchip     *
;    products. The software is owned by Microchip and/or its licensors, and is *
;    protected under applicable copyright laws.  All rights reserved.          *
;                                                                              *
;    This software and any accompanying information is for suggestion only.    *
;    It shall not be deemed to modify Microchip?s standard warranty for its    *
;    products.  It is your responsibility to ensure that this software meets   *
;    your requirements.                                                        *
;                                                                              *
;    SOFTWARE IS PROVIDED "AS IS".  MICROCHIP AND ITS LICENSORS EXPRESSLY      *
;    DISCLAIM ANY WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING  *
;    BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS    *
;    FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL          *
;    MICROCHIP OR ITS LICENSORS BE LIABLE FOR ANY INCIDENTAL, SPECIAL,         *
;    INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, HARM TO     *
;    YOUR EQUIPMENT, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR    *
;    SERVICES, ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY   *
;    DEFENSE THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER      *
;    SIMILAR COSTS.                                                            *
;                                                                              *
;    To the fullest extend allowed by law, Microchip and its licensors         *
;    liability shall not exceed the amount of fee, if any, that you have paid  *
;    directly to Microchip to use this software.                               *
;                                                                              *
;    MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF    *
;    THESE TERMS.                                                              *
;                                                                              *
;*******************************************************************************
;                                                                              *
;    Filename:      main.asm                                                   *
;    Date:          Sept 29 2013                                               *
;    File Version:  1.0                                                        *
;    Author:        Charles Douvier                                            *
;    Company:                                                                  *
;    Description:   Test of PWM1                                               *
;
;    Device 16F1509
;
;
;
;
; PIN DIAGRAM
;
;   RA0                             RC0
;   RA1                             RC1
;   RA2                             RC2     STATUS LED
;                                   RC3
;   RA4             RB4             RC4
;   RA5             RB5             RC5     PWM1
;                   RB6             RC6
;                   RB7             RC7
;
;------------------------------------------------------------           *
;*******************************************************************************
;                                                                              *
;    Notes: In the MPLAB X Help, refer to the MPASM Assembler documentation    *
;    for information on assembly instructions.                                 *
;                                                                              *
;*******************************************************************************
;                                                                              *
;    Known Issues: This template is designed for relocatable code.  As such,   *
;    build errors such as "Directive only allowed when generating an object    *
;    file" will result when the 'Build in Absolute Mode' checkbox is selected  *
;    in the project properties.  Designing code in absolute mode is            *
;    antiquated - use relocatable mode.                                        *
;                                                                              *
;*******************************************************************************
;                                                                              *
;    Revision History:
;           2013-09-28  Initial                                                *
;                                                                              *
;*******************************************************************************

;*******************************************************************************
; Processor Inclusion
;
;*******************************************************************************
    errorlevel -230, -302, -303, -313
    LIST R=DEC
#include "p16f1509.inc"
;*******************************************************************************
;
; Word Setup
;
;
;*******************************************************************************
    __CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _CLKOUTEN_OFF
    __CONFIG _CONFIG2, _LVP_OFF & _STVREN_ON
;*******************************************************************************
;
;  Variable Definitions
;
;*******************************************************************************
; TODO PLACE VARIABLE DEFINITIONS GO HERE
;*******************************************************************************
; Reset Vector
;*******************************************************************************
RES_VECT  CODE    0x0000            ; processor reset vector
    GOTO    START                   ; go to beginning of program
;*******************************************************************************
; TODO INSERT ISR HERE
;*******************************************************************************
; MAIN PROGRAM
;*******************************************************************************
MAIN_PROG CODE                      ; let linker place main program
INIT:
                            ;RC5 = PWM1
    BANKSEL LATA            ;Data Latch
    CLRF LATA               ;
    BANKSEL ANSELC          ;
    CLRF ANSELC             ;Digital IO
    BANKSEL PORTC           ;
    BCF PORTC,5             ;Clear PWM1
    BANKSEL TRISC           ;Set all PORTC to outputs
    CLRF TRISC
    BANKSEL PORTC
    BSF PORTC,2
    BANKSEL OSCCON
    MOVLW   0x78            ;16MHZ Clock
    MOVWF   OSCCON
    BANKSEL PWM1CON         ;
    CLRF PWM1CON            ;Disable PWM bits
    BANKSEL PR2
    MOVLW 0xFF
    MOVWF PR2               ;Load PR2 with 0xFF
                            ;Timer/PR set up is 973Hz
    BANKSEL PWM1DCH
    CLRF PWM1DCH
    BANKSEL PWM1DCL
    CLRF PWM1DCL
    BSF PORTC,2
    BANKSEL PWM1DCH
    MOVLW   0x6F
    MOVWF   PWM1DCH

                            ;copied code, havent check this yet.
    ;ENABLE INTERRUPT
    BANKSEL PIE1
    BSF PIE1,1
    bcf        PIR1,2
                    ;-----------------------------------
                    ;Configure and start Timer2
;CONFIGURE TIMER.. copied code review.
    BANKSEL T2CON
    MOVLW B'00000110'   ;MOVLW B'00000110'
    MOVWF T2CON
                    ;Enable PWM output pin and wait until Timer2
                    ;overflows, TMR2IF bit of the PIR1 register is set.
                    ;See note below.
    btfss    PIR1,1                ;Test for T2 interrupt
    goto    $-1
                    ;Enable the PWMx pin output driver(s) by clearing
                    ;the associated TRIS bit(s) and setting the
                    ;PWMxOE bit of the PWMxCON register.
                    ;Configure the PWM module by loading the
                    ;PWMxCON register with the appropriate values.
    BANKSEL TRISC          ;Enable Outputs
    CLRF    TRISC
    BANKSEL PWM1CON        ;Enable PWM1
    MOVLW    B'11000000'
    MOVWF    PWM1CON
    RETURN
START
    CALL INIT
    BANKSEL PORTC            ;select PORTC for heatbeat
LOOP:
    BSF PORTC,2              ;heart beat
    MOVLW 0x55
    NOP                      ;future code
    BCF PORTC,2
    GOTO LOOP                ;loop forever
    END

 

 

TAUTIC’s 20 Pin Development Kit

I am a sucker for development kits/boards; they are cheap and if you have the room in your project they shave tons of room off your development time. Semi-recently, I was looking for a 18 or 20 PIC development board to plug into a main board. There are tons of boards that have various relays and switches and such but I wanted a bare-bones board that was good for bread-boarding and then could be plugged into my Sumo Roomba bot. These are shockingly hard to find for some reason? While I was sniffing around I ran into Jayson Tautic’s website which led me to purchase his 20-pin PIC development board on tinde. This thing was dirt cheap, and came remarkably fast! I put the thing together in a few moments and it sat in my “do-something-with-this-stuff” pile for a a few weeks. This kit comes with a 16F1509 which was great for what I was working on; it’s not-so-great if you still are rocking a PICKit2, it’s time to upgrade to the 3! I build out the “hello world” circuit shown below but in the end I went in a different direction and used a different board with an 18F2331. Did the board end up in the bottom of a drawer soon to be forgotten? (whats in there these days??: Cymbet energy harvesting stuff, a few 8 pin & 14 pin boards from piccircuit & micrcocontrollershop, a little 5/3.3V switcher kit, MMA7361, a few PICKit demo boards.. hmmm some other random stuff lower down)  Nope! While hiking I decided it was destined for a greater purpose. I wanted to build my own barometer for “storm warning” while hiking the cascades this summer. I dug a BMP085 development board I purchased from Sparkfun earlier on this year and went to work; That code is coming along but isn’t quite finished. While working with this TAUTIC board I can say it is very clean, looks nice, and it’s rock solid. I highly recommend this dev board if you want to plop something down on your breadboard and hack away at.

Yeah, I know, another annoying blinking LED. This was just a 'hello world' test before I was going to get serious to make sure I had my osc and such set up right.
Yeah, I know, another annoying blinking LED. This was just a ‘hello world’ test before I was going to get serious to make sure I had my osc and such set up right.

 

 

 

 

 

 

 

 

 

 

If you’re interested in some of the basic code just to get it going, here is what I consider to be the important stuff to get you might like to use:

#include “p16f1509.inc”

__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _CLKOUTEN_OFF
__CONFIG _CONFIG2, _LVP_OFF & _STVREN_ON

and…

INIT: ;General Init
BANKSEL ANSELA ;All Digital Pins
CLRF ANSELA
CLRF ANSELB
CLRF ANSELC

BANKSEL OSCCON
MOVLW 0x78 ;16MHZ Clock
MOVWF OSCCON

BANKSEL TRISC
CLRF PORTC
CLRF TRISC

BANKSEL 0x00
RETURN