Bus Pirate v3 PIC 24FJ blinking LED programming tutorial
From DP
Contents |
Overview
The Bus Pirate is a handy debugging tool, but it's also a 16 bit PIC 24FJ64GA002 development board. You don't even need a programmer to try your hand at PIC programming, just upload the firmware over USB using the Bus Pirate's nearly-impossible-to-brick bootloader. Grab Microchip's free (but not open) IDE and C30 compiler, then dive in.
This demo is step one. It shows how to setup the chip to run from the internal clock, and blink the MODE LED. The code is broken up and explained section by section.
Stuff to get
Old (windows only)
- MPLAB8 IDE
- C30 compiler for 16bit PICs
New (Linux, Mac, Windows)
- MPLAB X IDE
- XC compiler
The source
((PIC))
After installing an IDE and compiler, open the blink MODE LED demo project. Look for a list of files included in the project and click main.c to open it.
Basic Configuration
#include <p24fxxxx.h>The very first line of main.c includes the C30 compiler's basic definitions for the PIC hardware.
_CONFIG1( JTAGEN_OFF & //JTAG port is disabled GCP_OFF & //GSP Memory Code Protection OFF GWRP_OFF & //GCC Flash Write Protection OFF COE_OFF & // FWDTEN_OFF & //Watchdog Timer OFF ICS_PGx1) //debug over PGD1 and PGC1
Various default settings are used when a PIC is first powered on. The initial setup is defined by the config words, sometimes also called config fuses. Here are the most meaningful options in CONFIG1:
- JTAG debug mode is off - this is a secondary debugging mode we won't use and would waste pins
- Watchdog Timer is off - this is an alarm that resets the PIC if there are problems. We won't use it in this demo
- Debugging is handled by the PGD1 and PGC1 pins, the default for the Bus Pirate hardware. If you're debugging custom hardware using a different set of pins then change this setting
CONFIG2( FNOSC_FRCPLL & //Internal FRC with PLL OSCIOFNC_ON & //RA3 is clk out (fosc/2) POSCMOD_NONE & //Primary oscillator disabled I2C1SEL_PRI) //Use default SCL1/SDA1 pins
CONFIG2 settings determine what clock runs the PIC at startup. We need to set the internal oscillator or our code will never run.
- The 8MHz internal oscillator is selected, this is multiplied by 4 using an internal PLL
- The Bus Pirate has no external crystal so we disable the primary external oscillator circuit and score a few extra IO pins
Do some setup
#pragma codeThis tells the compiler that the next section is code, as opposed to configuration. This is not strictly required.
int main(void) { unsigned long i; //a 32 bit variable to use as a timer CLKDIVbits.RCDIV0=0; //clock divider to 0 AD1PCFG = 0xFFFF; // Default all pins to digital OSCCONbits.SOSCEN=0; //Disables the secondary oscilator
This is the main function, it is the starting function every processor executes.
First we declare variable i, a 32 bit number that we'll use in a delay function later.
Next we change a few default startup settings. C30 bit variables are accessed with this syntax [name of register]bits.[name od bit]. The names are the same as in the PIC 24FJ64GA002 !!!!LINK!!!! datasheet.
Initially the PIC starts with a slow clock. To get the full 16MIPs we need to set the clock divider to 0. This is done by setting the RCDIV0 bit of the CLKDIV registrar to 0.
The PIC starts with all pins in analog to digital conversion mode, the pins use the least power in analog mode. We make all the pins digital by setting AD1PCFG register to all 1s.
We disable the secondary oscillator by clearing the SOSCEN bit in the OSCCON register. This ensures that the pins on the real-time clock oscillator are available for digital IO.
TRISAbits.TRISA1 = 0; //sets the Mode LED pin RA1 as output LATAbits.LATA1 = 0; //turns LED off
Check the Bus Pirate schematic and note that the MODE LED is connected to PORTA pin #1, or A1.
First we set the direction of the pin to output. The TRIS register controls the pin direction. 1 is input, 0 is output. To control the LED we need an output pin, so we write 0 to the TRISA1 bit of the TRISA register.
LATA sets the pin output to high (1) or low (0). Clear the LATA1 bit in the LATA register to start with the MODE LED off.
Blink the MODE LED
while(1) { LATAbits.LATA1 = ~LATAbits.LATA1; //toggles the MODE LED i =0xFFFFF; //sets i to 1048575 while (i--); //delay function } //decrements i until 0 }
Now let's get to the good stuff, blinken LEDs.
while(1) creates a continuous loop of the code inside the {} brackets. Here's what happens:
- The MODE LED is flipped to the opposite of the current value using the =~ operator. On the first run the MODE LED on the Bus Pirate lights, on the second it turns off, and so on
- Variable i is now set to 1048575 (0xFFFFF)
- The while(i--) loop simply subtracts one until i hits 0. When i equals 0 the program returns to the beginning, flips the LED (#1), resets the counter (#2), and starts counting again (#3)
This never ending loop blinks the LED.
Using the bootloader to upload your demos
There are two ways to get code on the Bus Pirate.
- Load it over USB with the bootloader and (Pirate-Loader or ds30 Loader
- Connect a PIC programmer to the ICSP pins (we recommend ICD2, ICD3, PICkit2, PICkit3, or clones)
This demo will work with either method.
Exporting firmware for the bootloader
If you plan on using a programmer to upload your demo firmware into the Bus Pirate you can skip this part.
The Bus Pirate comes with its own bootloader, which can be used to program the demo firmware. To do this add this linker script to your demo project by:
- Downloading the p24FJ64GA002.gld file into your project folder.
- Adding this file to the Linker Script folder in your MPLAB 8 project.
Now you can proceed to build your project. After compiling is completed go to File/Export:
- Check the Program Memory checkbox
- Uncheck the Configuration Bits checkbox
- Enter the End memmory address as 0xa7f
- Hit OK
- Save the *.hex file where you can find it later
Uploading the firmware
Follow these guides to upload your firmware through the boot loader.
C30 Source Code
#include <p24fxxxx.h> _CONFIG1( JTAGEN_OFF & //JTAG port is disabled GCP_OFF & //GSP Memory Code Protection OFF GWRP_OFF & //GCC Flash Write Protection OFF COE_OFF & // FWDTEN_OFF & //Watchdog Timer OFF ICS_PGx1) //debug over PGD1 and PGC1 _CONFIG2( FNOSC_FRCPLL & //Internal FRC with PLL OSCIOFNC_ON & //RA3 is clk out (fosc/2) POSCMOD_NONE & //Primary oscillator disabled I2C1SEL_PRI) //Use default SCL1/SDA1 pins #pragma code int main(void) { CLKDIVbits.RCDIV0=0; //clock divider to 0 AD1PCFG = 0xFFFF; // Default all pins to digital OSCCONbits.SOSCEN=0; //Disables the secondary oscilator TRISAbits.TRISA1 = 0; //sets the Mode LED pin RA1 as output LATAbits.LATA1 = 0; //turns LED off unsigned long int i; ////////////////////////////////////////////////////////////////// ///FOREVER LOOP/////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// while(1) { i =0xFFFFF; //sets i to 1048575 LATAbits.LATA1 = ~PORTAbits.RA1; //togles the MODE LED while (i--); //delay function } //decrements i until 0 }
