PIC Programming - Square Waves


Generating Square Waves

Mark Crosbie has a web page dealing with Linux PIC programming, along with some example projects. One of these is a test program which purports to generate a 100KHz square wave on a 4MHz PIC. In fact anyone trying this out will find it lumbers along at a mere 15.157 KHz. Looking at the code, it's not too hard to see why. A 4MHz PIC runs a 1 million instruction cycles per second, to generate 100 KHz, you need to toggle the state of a port twice in 10 microseconds. The delays in this code are far too long.

Replacing the main loop with this:

Loop
  comf PORTA
  nop
  nop
  goto Loop
Produces a 100KHz square wave. If you're desperate, you can do it with one less instruction:

Loop
  comf PORTA
  goto $+1
  goto Loop
By removing the delay thus:

Loop
  comf PORTA
  goto Loop
We can produce a square wave of 166.66 KHz, the fastest we can sustainably go with a 4MHz clock. It is possible to toggle a port at 500KHz, but only for a short period, as the two-cycle penalty of the jump instruction will mess things up.

This C code produces a 10-cycle burst at 500KHz followed by a 1 millisecond delay:

    asm __config _CP_OFF & _XT_OSC & _PWRTE_ON  & _WDT_OFF

main()
{
    set_bit( STATUS, RP0 );
    set_tris_a( 0 );
    clear_bit( STATUS, RP0 );
    output_port_a( 0 );

    while( 1 ) // Forever
    {
      delay_ms(1);
      asm comf PORTA
      asm comf PORTA
      asm comf PORTA
      asm comf PORTA
      asm comf PORTA
      asm comf PORTA
      asm comf PORTA
      asm comf PORTA
      asm comf PORTA
      asm comf PORTA
      asm comf PORTA
      asm comf PORTA
      asm comf PORTA
      asm comf PORTA
      asm comf PORTA
      asm comf PORTA
      asm comf PORTA
      asm comf PORTA
      asm comf PORTA
      asm comf PORTA
      delay_ms(1);
    }                
}
This code needs to be linked with delay.lib

Want to generate a sustained 500KHz? The simplest way is to use the 166 KHz code i.e.

Loop
  comf PORTA
  goto Loop
Instead of using a 4MHz crystal to clock the PIC, drop in a 12MHz, this will generate a 500KHz square wave [yes, even on a '4 MHz' PIC]. I have run '4 MHz' PICs with clocks as high as 16MHz.
By replacing the comf instruction with incf, you can generate square waves on the other outputs, with each higher order bit being half the frequency of the one below it. By moving from port A to port B, you can generate from 166KHz on bit 0, down to 1.3 KHz on bit 7. Up the crystal to 12MHz and you get a range of 500KHz to 3.91KHz, or 16 will give 667KHz to 5.2 KHz


Back Home