7 April 2008

5. Your first pic program

Okay, so let’s get some leds flashing. First we’ll get a virtual led flashing – then go for the real thing.

Open up the flash project in adventures\flash. Add a led from the plugins menu, configure it to use portb. Pics have a concept of ports – really it’s just a way of distinguishing all the pins from one another. Instead of having IO pins 1 through 24, they’re broken up into “ports”. Nothing magic about them, other than the fact you can write to a whole port at once if you want (ie, change or read all 8 pins in one instruction.

Compile the program by pressing F7. Hit the debug button (it looks like a little bug) Hit F5 to run the program. And watch, in astonishment as the led flashes. Very. Slowly.

Actually the real hardware runs a lot faster. Before we get some hardware going, lets have a look at what this program does. Pull up flash.c.

/* Flasher!

A good little test program that flashes leds..

*/

#include "pic_utils.h"

Pic_utils.h includes a bunch of handy stuff, and I include it every time.

#pragma CLOCK_FREQ 8000000

This tells the compiler how fast you expect the clock to be running. This is so the linker can generate a “delay” routine for you that matches your clock speed. Delays are really carefully crafted loops. We really only know how long 250ms is by knowing the clock rate and how make clock cycles a given set of instructions take to execute.

#define flash_port PORTB
#define flash_pin 0

Get into the habit using #defines wherever and whenever you can. It means that you can make simple hardware changes (like using port a instead of port b) by doing equally simple software changes (changing the #define) instead of having to find every instance of port b when you are referring to your flashing led pin, and changing them. Believe me, you’ll be thanking me for this later.

void interrupt () {
}

Pics have at least one, if not two, interrupt routines that are executed upon certain events happening, like a timer going off or a serial character being received or a pin changing level. We don’t do anything with it here – but I include so that if we’re using a bootloader, everything will be at the right location in memory. More on this later.

void flash() {
toggle_pin(flash_port, flash_pin);
}

This is where the heavy lifting is done. We just flip the output of this pin to high if it’s low and low if it’s high every time this function is called. Toggle_pin is a pic_utils routine, which we’ll explore more a little later.

void main() {

turn_off_analog_inputs();
make_output(flash_port, flash_pin);

while (1) {
flash();

delay_ms(250);
delay_ms(250);

}

}

The main routine has a couple of interesting things in it. Firstly, some ports can be analog inputs or digital inputs, and by default they start out life when booted as analog inputs. So this nifty routine fixes that for our purposes. Then we set the flash port / pin combination to be a digital output (the default, once it’s no longer an analogue input, is a digital input). Mind you, not all pins can be an analogue input, but just turning them all into digital pins at the start means we don’t have to do datasheet hunting at this stage of the game.

Finally, in our main loop we flip the led, then wait 500ms before doing it all again. Forever. Seeing that the led should light every second or so, you get a feeling how much slower the hardware emulator is running than the real hardware.

No comments: