PIC Micro Controller C Input / Output Routine

LED dimmer. Software PWM, A2D from Potentiometer. Written in CCS C

Andre Abelian [aabelian@mason-electric.com]

I needed software PWM and I used Scott Dattalo's software PWM idea and I can tell he is a genus. The test I did on my demo board I only had 2 leds and 1 pot. The pot is dimming one of the led and the other PWM is fixed number entered manually before compiling. The resolution is 10 bit and the result is excellent. see attachment file. It is written in CCS C. Note that there are some extra unused stuff. I am using timer 0 interrupt. Also thanks to CCS for making nice compiler.

Andre

//
// Scott Dattalo's Software PWM idea
// Thanks to him 
//
#include <18F4550.h>
#rom int 0xf00000={0x19,0x11,0x09,0x00}  // write to eeprom project number
#device ADC=10
#define DEBUG // comment this line (to program): Remove comment (to debug)
#ifdef DEBUG                      
#fuses HS,NOWDT,NOPROTECT,NOLVP,MCLR                // use this line to debug
#else
#fuses NOMCLR,STVREN,BORV20,WDT2048,HS,PROTECT,NOLVP  // use this line to programmer
#endif
#use delay(clock=20000000)
#use rs232(DEBUGGER)
#use rs232(baud=57600,xmit=PIN_B5,bits=8,invert)
#ZERO_RAM                                        //  clear all variables
#define pwm_output1_on output_high(PIN_B5);
#define pwm_output1_off output_low(PIN_B5);
#define pwm_output2_on output_high(PIN_B4);
#define pwm_output2_off output_low(PIN_B4);
#define pwm1 1023
#define pwm2 1023
#define cycle_t0 0xFF5a

       
     long int duty_cycle1,rising_edge1,falling_edge1;
     long int duty_cycle2,rising_edge2,falling_edge2;

/////////////////////////////////////////////////////
// Main Program 
/////////////////////////////////////////////////////
   void main (void)
   {
      set_tris_a (0xFF); // make all output no use for now
      set_tris_b (0b11111111); // make all input
      set_tris_c (0xff); // all output
      set_tris_d (0b00010000); //
      set_tris_e (0xff); // make all output
      OUTPUT_D (0xff); //
      OUTPUT_C (0xff); // turn off all
      setup_adc( ADC_CLOCK_INTERNAL);            //
      setup_counters (RTCC_INTERNAL, RTCC_DIV_1);
      enable_interrupts (int_RTCC);
      enable_interrupts (GLOBAL);
      set_timer0(cycle_t0);                // adjust timer0
      
      pwm_output1_on;
      rising_edge1= 0;
 //     falling_edge1 = pwm1 - duty_cycle1;

      pwm_output2_on;
      rising_edge2= 0;
//      falling_edge2 = pwm2 - duty_cycle2;

      while (TRUE)
      {
      set_adc_channel(0);
      delay_ms(1);
      duty_cycle1 = read_ADC();
 //     set_adc_channel(1);
 //     delay_ms(1);
 //     duty_cycle2 = read_ADC();
      }
}

#int_rtcc 
void pwm_isr()
   {
           set_timer0(cycle_t0);                // adjust timer0
            if (rising_edge1 ++ > pwm1)
                   {
            rising_edge1= 0;
            pwm_output1_on;
            falling_edge1 = pwm1 - duty_cycle1;
                   }

          if (falling_edge1 ++ > pwm1)
                  {
            falling_edge1 = 0;
            pwm_output1_off;
                  }
  
             if (rising_edge2 ++ > pwm2)
                   {
            rising_edge2 = 0;
            pwm_output2_on;
            falling_edge2 = pwm2 - 900;
                   }

          if (falling_edge2 ++ > pwm2)
                  {
            falling_edge2 = 0;
            pwm_output2_off;
                  }
          
  
  
   }
  

Comments:

Questions: