PIC16f887 start and start pwm

JohnInTX

Joined Jun 26, 2012
4,787
OK! 'Works' is the word we are looking for.

While you were working on the auto-shutdown method I was detailing the PWM control as I saw it (turn it on and off by shutting it down in firmware). In doing so, I pulled your code from an earlier post and modified it, adding some notes in the comments of things I didn't like (doing TRIS in single bits etc.) as well as adding some comments and formatting to make the code easier to read. Its posted below for your examination. Key points towards improving the code include:

Better formatting- it helps you read and understand the code. Indents and lined-up brackets help lots.

Breaking actions into functions so that the action (initIO, startPWM etc) are self-contained and perform their function regardless of what the system was doing at the time of the call. This is an important concept in programming. Break things down to simple, single task functions that always work, then use these 'tools' to build bigger programs. Try to avoid monolithic blocks of code like your early main. (Don't feel bad - everyone does it starting out..).

Keep main() simple. If you can write on the back of an envelope what your program does, that's what main should do - no more, no less.

Comments. You may know what something is supposed to do - at least today - but what about others reading your code, for help and maybe after you get promoted? Your code is actually better commented than many who post for help but I've added some to indicate what things should do, where more work is needed etc.

Anyway, here's the code. As I said, its a couple of generations old but hopefully it will help with some ideas.

Have fun.

Code:
// PWM code from post #15 with control loop  and updated PWM controls
// PWM control is by polling an input - not using the later shutdown control

// Initialized arrays can be on multiple lines..
unsigned char sin_table[64]={
         0, 6, 12, 18, 24, 30, 36, 42, 48, 53, 59, 64, 69,
         74, 79, 84, 88, 93, 97, 100, 104, 107, 110, 113, 115, 118,
         120, 121, 123, 124, 124, 125, 125, 125, 124, 124, 123, 121,
         120, 118, 115, 113, 110, 107, 104, 100, 97, 93, 88, 84, 79,
         74, 69, 64, 59, 53, 48, 42, 36, 30, 24, 18, 12, 6
         };  //100% duty cycle

// Each of these variables should have a comment telling what it is
unsigned int TBL_POINTER_NEW, TBL_POINTER_OLD, TBL_POINTER_SHIFT, SET_FREQ;
unsigned int TBL_temp;
unsigned char DUTY_CYCLE;
unsigned int temp;

//------------------ INTERRUPT HANDLER  --------------------------------
void interrupt()
{
     if (TMR2IF_bit == 1){
        TBL_POINTER_NEW = TBL_POINTER_OLD + SET_FREQ;
        if (TBL_POINTER_NEW < TBL_POINTER_OLD){
           CCP1CON.P1M1 = ~CCP1CON.P1M1; //Reverse direction of full-bridge
        }
        TBL_POINTER_SHIFT = TBL_POINTER_NEW >> 10;
        DUTY_CYCLE = TBL_POINTER_SHIFT;
        CCPR1L = sin_table[DUTY_CYCLE];
        TBL_POINTER_OLD = TBL_POINTER_NEW;
        TMR2IF_bit = 0;
     }
}

// Both start and stop PWM must be able to completely configure PWM
// for start or stop at power up and in response to switch control

//---------------------- START PWM  ----------------------
// Configure and start PWM under interrupt control
void RunPWM()
{
  PORTC.F2 = 0;
  PORTD.F5 = 0;
  PORTD.F6 = 0;
  PORTD.F7 = 0;
  SET_FREQ = 1024;
  TBL_POINTER_SHIFT = 0;
  TBL_POINTER_NEW = 0;
  TBL_POINTER_OLD = 0;
  DUTY_CYCLE = 0;
  PR2 = 124; //124
  CCP1CON = 0b01001100; // duty lowest bits + PWM mode

  TMR2IF_bit = 0;
  T2CON = 4; //TMR2 on, prescaler and postscaler 1:1
  while (TMR2IF_bit == 0);
  TMR2IF_bit = 0;

  TMR2IE_bit = 1;
  GIE_bit = 1;
  PEIE_bit = 1;
}

//------------------- STOP PWM  -----------------------------
// Stop PWM - fix this up to complete a power on init stopping the PWM
void StopPWM()
{
GIE_bit = 0;      // stop interrupts
PEIE_bit = 0;
TMR2IE_bit = 0;
CCP1CON = 0;         // kill the PWM
T2CON = 0;           // kill timer 2
// fix up any outputs that you need to here
}

//------------------ INITIALIZE PIC IO  ------------------------------
// Set up all ports on PIC. Start with PWM off

void initIO(void)
{
// Initialize system from reset
  ANSEL = 0;          //Disable ADC
  ANSELH =  0x00;
  CM1CON0 = 0;        //Disable Comparator
  CM2CON0 = 0;

// Initialize IO and TRIS
// Re do this to set values by byte. Initialize ALL ports on the PIC
// .. not just the ones you are using.  Need to add that code here
  PORTC.F2 = 0;      // set port values first to avoid glitches on outputs
  PORTD.F5 = 0;
  PORTD.F6 = 0;
  PORTD.F7 = 0;
  PORTB.F0 = 0;
  PORTD.F0 = 0;
                     // Then set TRIS but:
  TRISD.F0 = 1;      // do !NOT! set TRIS bit by bit - use TRISx=0xdd
  TRISC.F2 = 0;      // to set TRISx as a byte.  Bit by bit can cause problems
  TRISD.F5 = 0;      // in execution.   Do the same with ports above.
  TRISD.F6 = 0;
  TRISD.F7 = 0;
  TRISB.F0 = 0;

  TRISC = 0;         // port C all outputs
  StopPWM();
}

//================== MAIN  ===============================
// Main is short and sweet - it only contains top-level controls

void main()
{
   GIE_bit = 0;      // in case main is not executed from hard reset..
                     // disable interrupts
                 
   initIO();         // init PIC IO, PWM is stopped after this
                     // any other inits here then on to main loop
                 
  //--------------- MAIN CONTROL LOOP  ---------------------
  // First time: look at switch input and start or stop PWM
  // Then follow switch.
   do{
      if(PORTD.F0 == 0){        // if switch is 0,
        StopPWM();              // stop PWM then..
        while(PORTD.F0==0);     // wait as long as switch is still 0
      }
      if(PORTD.F0 == 1){        // if switch is 1,
        RunPWM();               // startPWM then.
        while(PORTD.F0 == 1);   // wait as long as switch is still 1
       }
   }while(1); // do - sample switch and control PWM
}//main
 
Top