Now that we have ALL THAT STUFF out of the way, we are finally ready to write some meaningful code. As promised, we will blink an LED in a 50% duty cycle on / off style. We will do this using a simple loop in main, which as you might have guessed is where our application starts execution.
Since we are not using any timer or delay libraries yet, we will need to create a delay loop to slow things down a bit. We will place this loop into a function so we can call it when needed.
Copy and paste the code below into main.c and please remember to overwrite the previous code in there since the code below is the entire file. You can also download the file here and then place it in your project folder overwriting the old main.c in there.
/* Setting up a new C18 project and creating an application Tutorial Super simple LED blinker in C using Microchip C18 and MPLAB Written by Hop for digital-diy.com tutorials - May 13, 2009 Written for the 18F452 running at 40mhz specifically. Make changes as needed for other devices */ // Include the necessary device header file #include <p18f452.h> // Configuration Bit pragma directives (see device data sheet) #pragma config OSC = HSPLL, OSCS = OFF // HS-PLL Enabled, Internal External Osc. Switch Over OFF Disabled #pragma config PWRT = OFF // Power Up Timer: OFF Disabled #pragma config BOR = OFF, BORV = 25 // Brown Out Reset: OFF, Brown Out Voltage: OFF Disabled #pragma config WDT = OFF, WDTPS = 128 // Watchdog Timer: OFF Disabled, Watchdog Postscaler: 1:128 #pragma config CCP2MUX = OFF // CCP2 Mux: OFF Disabled (RB3) #pragma config STVR = OFF // Stack Overflow Reset: OFF Disabled #pragma config LVP = OFF // Low Voltage ICSP:OFF Disabled #pragma config DEBUG = OFF // Background Debugger Enable: OFF Disabled #pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF // Code Protection Block 0-3: OFF Disabled #pragma config CPB = OFF // Boot Block Code Protection: OFF Disabled #pragma config CPD = OFF // Data EEPROM Code Protection: OFF Disabled #pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF // Write Protection Block 0-3: OFF Disabled #pragma config WRTB = OFF // Boot Block Write Protection: OFF Disabled #pragma config WRTC = ON // Configuration Register Write Protection: OFF Disabled #pragma config WRTD = OFF // Data EEPROM Write Protection: OFF Disabled #pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF // Table Read Protection Block 0-3: OFF Disabled #pragma config EBTRB = OFF // Boot Block Table Read Protection: OFF Disabled // Function prototypes void delay1(void); // Main code section. Execution starts here. void main(void){ // First some setup code for the LED // The LED will be driven by port D, bit 0, driving the anode, cathode to ground // First we should clear the port D, bit 0 data latch LATDbits.LATD0=0; // We need to set port D, bit 0 as an output // Using TRISDbits instead of TRISD allows isolating a single bit leaving the other bits unchanged TRISDbits.TRISD0=0; // 0 = output, 1 = input // Set port D, bit 0 to off (driving the LED anode, cathode to ground) PORTDbits.RD0=0; // LED blinking loop that never ends since '1' never changes while(1){ PORTDbits.RD0=1; // turn the LED on delay1(); // call the delay function PORTDbits.RD0=0; // turn the LED off delay1(); // call the delay function } // end of main, but we will never get this far (endless loop) } // Start of our functions void delay1(void){ /* It is important to note that all variable declarations need to be placed before any code in a function or the build will fail. */ // declare a long integer and set it to zero long int loop1=0; // count from zero to 30,000 then continue on // Lower than 30000 for a faster blink, higher for a slower blink. for(loop1=0;loop1<=30000;loop1++){ /* FOR loops are pretty simple in C. There are three parameters in a FOR loop seperated by semicolons. The first parameter is what variable we want to use and what value to assign to it initially. The second parameter is the condition for the loop to continue looping. In this case, as long as loop1 is less than or equal to 30000 the loop will continue looping. The third parameter is what to do at each iteration of the loop. In this case, increment loop1 by 1 each iteration. Everything in between the curly braces is executed on each pass of the loop. When the test condition fails, IE: loop1 = 30001, then execution passes to the next statement after the close curly brace. */ } // The loop is done and execution has moved past the loop }
This simple application does one thing, turn a LED on and off repeatedly. I included some comments to help explain each line and to give you a little exposure to the C version of FOR loops. I plan to write a ton of tutorials on the various little C tricks that are out there.
We have so much revision to do with this simple application. PWM, interrupts, multiplexing, using RS232 and USB to control the LED flashing element, and using the Microchip C18 libraries. Together, we will take this simple task to the absolute LIMIT using peripheral hardware and software support. Through these adventures, we will learn how to take these skills and apply them to more complex tasks using C18. Tasks that will allow us to interface and interact with other devices, bringing our PIC MCU to a point where we are comfortable having it handle almost anything we can think of.
Please revisit this tutorial in the future and check for updates and revisions. We have laid out a great foundation to build on, and there is much more work to be done.
Have fun! I know I have.
Hop