PIC18F4550 – Coding a Variable Delay

This example creates a function called “wait_ms( )” in C-code. It makes use of a for-loop that decrements a variable to achieve a fixed delay. The value of the variable to achieve an accurate delay needs to be determined by measurement.

The instruction cycle for this micro-controller is 83.3 ns. Assign 1200 as the initial count for the variable in the loop (10*1200*83.3ns = 1ms). This should be reasonably close to the needed value. Connect an LED to an output port and put it in a loop to flash every 1000 ms. Check to see if it is flashing at a 1000 ms rate by observation. View the Program Memory in assembly language to see how many instructions the compiler generated (the image below shows how to access the machine code listing).

Configure TMR0 as a counter and count the number of instruction cycles used for a 3 ms delay. Preload the timer registers with zero. Start the counter. call the wait_ms() function and pass the value 3. With out using a prescaler the most TMR0 can time is about 5 ms. The XC8 compiler generated code that came back with a count of TMR0H/L = B73A which translates to 3.9 ms instead of the expected 3. Check the math: {(11*4096+7*256+3*16+10) * 83.3ns = 46906 * 83.3ns = 3.907ms}. That’s 3.907/3 = 1.302 too high. So, 1200/1.302 = 921 yields a TMR0H/L count of 8CB9 which translates to 3.001 ms which is pretty close. {(8*4096+12*256+11*16+9) * 83.3ns = 36025 * 83.3ns = 3.001ms}. Assign 921 as the loop variable and verify the performance.


#include #include "p18f4550_hw_config.h" // configures for 20MHz crystal and Fcy of 12MHz
#include "p18f4550_LCD.h" // control a 2x16 character LCD display

#define LED LATCbits.LATC7 // an LED with 470 ohm Rs attached to port C bit 7

void wait_ms(unsigned int time) // function for delay in ms
{ // an instruction cycle takes 83.3 ns, so 12,000 cycles will create a 1 ms delay
int i = 0;
const int cCycles_Per_ms = 921; // This variable will need to be adjusted to calibrate the function for 1 ms delay
while(time){
for( i = 0; i < cCycles_Per_ms ; i ++){ } time--; // decrement the time unit, repeat till time = 0 } } void main(void) { // Hardware Configuration // LED Config TRISCbits.TRISC7 = 0; // RC7 pin 26 set for output LED = 0; // led off // LCD Display LCD_init(); // check the wait_ms() function for accuracy // setup timer 0 and turn it on // ON 8B Src Edg PSA PS2 PS1 PS0 T0CON = 0x88; // 1 0 0 0 1 0 0 0 -> 16 bit, PS = 1
TMR0H = 0x00; TMR0L = 0x00; // count up from 0
wait_ms(3); // expect 3 ms delay
T0CON = 0x08; // Stop the timer
LCD_byte(TMR0L); // display TMRO count low byte (must be read first)
LCD_cmd(0xC0); // move to line 2 of the LCD
LCD_byte(TMR0H); // display TMRO count high byte

while(1){ // infinite loop to blink an led
LED = 0; // led off
wait_ms(800);
LED = 1; // led on
wait_ms(200);
} // verify that the LED blinks at a 1 sec rate
}