This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Generation of PWM using Extrenal Interrupts and Timers

Hi everybody,

I'm a beginner trying to generate a PWM wave on a C8051F330 micro controller using C programming language. I have many doubts regarding this exercise. It would be really helpful if someone clarifies my doubtswhich will eventually get me going.

Can anybody please explain me roughly the flow of the following program...??

// Include Files //
// Global constants //
// Function Prototypes //
// Main Routine //

void main (void)
{ PCA0MD &= ~0x40; Oscillator_Init (); Port_Init (); External_Interrupt_Init (); Timer2_Init (); PCA_Init (); EA = 1; while (1);
}

// Oscillator Initialisation //
void Oscillator_Init (void)
{ //do something//
}

//Port Initialisation //
void Port_Init (void)
{ //do something//
}

//External Interrupt Initialisation //
void External_Interupt_Init (void)
{ //do something//
EX0 = 1;
}

//Timer2 Initialisation //
void Timer2_Init (void)
{ TMR2CN=0x00;
TMR2RL= RELOAD_VALUE;
TMR2 = 0xFFFF; // Set to reload immediately //
}

//PCA Initialisation //
void PCA_Init (void)
{ //do something//
}

//Interrupt Service Routine (ISR) //
INTERRUPT(INT0_ISR, INTERRUPT_INT0)
{ TR2 = 1;
}

This program is in C. I'm here trying to understand the program flow. I know that the "main()" is the first function that gets executed here. And then the line "PCA0MD &= ~0x40" followed by Osillator_Init function. The program control actually goes into the called Oscillator_Init function (below main()) and executes it,.and so on...

In case of External_Interrupt_Init(),I have enabled /INT0 interrupt using "EX0=1". Where does the program flow control go from here...??

And in ISR where does the program control go after executing TR2 = 1,.

Please folks help me find answers to my doubts.

Parents
  • Hello,

    Thanks very much for your reply. I understand what you mean exactly by a wild loop now. I have made the following changes in the main() and tried to execute the code. But I still don't see any waveform generated. Please help find bugs if there are any...
    This is what I'm trying to do exactly. The external interrupt should trigger/start a timer (16-bit timer2 with auto reload functionality). Every time the timer overflows from all FFFF's to 0000's a new value (starting from 0 to 65534) should be put in the PCA register.

    
    //-----------------------------------------------------------------------------
    // Include Files
    //-----------------------------------------------------------------------------
    
    #include <compiler_defs.h>                           // Macro definitions for 8051 Compiler //
    #include <C8051F336_defs.h>                  // SFR declarations //
    
    //-----------------------------------------------------------------------------
    // Global Constants
    //-----------------------------------------------------------------------------
    
    #define SYSCLK             24500000/12             // Clock speed in Hz //
    
    
    SBIT (SW2, SFR_P0, 7);                         // SW2==0 means switch depressed //
    
    
    //-----------------------------------------------------------------------------
    // Function Prototypes
    //-----------------------------------------------------------------------------
    
    void Oscillator_Init (void);             // Configure the system clock //
    void Port_Init (void);                       // Configure the Crossbar and GPIO //
    void Timer2_Init (int counts);           // Configure Timer2 //
    void PCA_Init (void);                    // Configure PCA for PWM mode //
    void Ext_Interrupt_Init (void);             // Configure External Interrupts (INT0) //
    
    
    INTERRUPT_PROTO (INT0_ISR, INTERRUPT_INT0);
    
    
    //-----------------------------------------------------------------------------
    // MAIN Routine
    //-----------------------------------------------------------------------------
    void main (void)
    {
       PCA0MD &= ~0x40;                       // Disable Watchdog timer //
       int RELOAD_VALUE = 0;
    
       Oscillator_Init();                  // Initialize the system clock //
       Port_Init ();                           // Initialize crossbar and GPIO //
       Timer2_Init(SYSCLK/100);// Initialize Timer2 to generate interrupts at a 20kHz rate//
       PCA_Init ();                    // Initialize PCA for PWM //
       Ext_Interrupt_Init();              // Initialize External Interrupts //
    
       EA = 1;
    
       while(1)                           // Infinite while loop //
    {
                     if(TF2H == 1)
                     {
                             if (RELOAD_VALUE<65535)
                                            {
                                                    TF2H = 0;
                                                    PCA0CP0 = RELOAD_VALUE;
                                                    RELOAD_VALUE ++;
                                            }
                             else
                                            {
                                                    TF2H = 0;
                                                    RELOAD_VALUE =0;
                                            }
                            }
    
    }
    
    }
    
    
    //-----------------------------------------------------------------------------
    // Oscillator_Init
    //-----------------------------------------------------------------------------
    // This routine initializes the system clock to use the precision internal
    // oscillator as its clock source.
    //-----------------------------------------------------------------------------
    void Oscillator_Init (void)
    {
            CLKSEL = 0x00;    // Clock Select. SYSCLK is derived from the Internal High Frequency Oscillator and scaled per IFCN bits in register OSCICN //
            OSCICN = 0x83;            // Internal H-F Oscillator enabled and SYSCLK derived from Internal H-F Oscillator divided by 1 //
    }
    
    
    //-----------------------------------------------------------------------------
    // Port_Init
    //-----------------------------------------------------------------------------
    
    void Port_Init (void)
    {
    
       XBR1      = 0x40;            // Enable crossbar and weak pull ups //                    P0SKIP    = 0x7F;                    // Skip unused pins on P0 and P1 //
       P1SKIP    = 0xFF;
    
    }
    
    
    //-----------------------------------------------------------------------------
    // Timer2_Init
    //-----------------------------------------------------------------------------
    
    void Timer2_Init (int counts)
    {
    
       TMR2CN  = 0x00;                 // Stop Timer2. Clear T2SPLIT.
                                   // Use SYSCLK/12 as timebase, 16-bit auto-reload
       CKCON  |= 0x30;                // Timer2 High and Low byte uses the SYSCLK //
       TMR2RL  = -counts;           // Initialize reload value
       TMR2    = 0xFFFF;               // Set to reload immediately
    
    }
    
    
    //-----------------------------------------------------------------------------
    // PCA_Init
    //-----------------------------------------------------------------------------
    
    void PCA_Init(void)
    {
    
            PCA0MD    = 0x00;             // PCA Counter/Timer Idle Control enabled, Watchdog timer disabled, Watchdog timer enable unlocked, Unused, System clock divided by 12, Disable CF Interrupt //
            PCA0CPM0  = 0x82;             // PWM 16, ECOM, TOG, PWM, ECCF bits set //
             PCA0PWM        &= ~0x80;
    }
    
    
    //-----------------------------------------------------------------------------
    // Ext_Interrupt_Init
    //-----------------------------------------------------------------------------
    
    void Ext_Interrupt_Init (void)
    {
    
       TCON   = 0x01;                   // INT 0 is edge triggered //
       IT01CF = 0x07;                   // INT0 active low; INT0 on P0.7 //
       EX0 = 1;                         // Enable INT0 interrupts //
    
    }
    
    
    //-----------------------------------------------------------------------------
    // Interrupt Service Routines
    //-----------------------------------------------------------------------------
    
    INTERRUPT(INT0_ISR, INTERRUPT_INT0)
    {
       TR2  = 1;            // Start Timer2 //
    }
    
    

Reply
  • Hello,

    Thanks very much for your reply. I understand what you mean exactly by a wild loop now. I have made the following changes in the main() and tried to execute the code. But I still don't see any waveform generated. Please help find bugs if there are any...
    This is what I'm trying to do exactly. The external interrupt should trigger/start a timer (16-bit timer2 with auto reload functionality). Every time the timer overflows from all FFFF's to 0000's a new value (starting from 0 to 65534) should be put in the PCA register.

    
    //-----------------------------------------------------------------------------
    // Include Files
    //-----------------------------------------------------------------------------
    
    #include <compiler_defs.h>                           // Macro definitions for 8051 Compiler //
    #include <C8051F336_defs.h>                  // SFR declarations //
    
    //-----------------------------------------------------------------------------
    // Global Constants
    //-----------------------------------------------------------------------------
    
    #define SYSCLK             24500000/12             // Clock speed in Hz //
    
    
    SBIT (SW2, SFR_P0, 7);                         // SW2==0 means switch depressed //
    
    
    //-----------------------------------------------------------------------------
    // Function Prototypes
    //-----------------------------------------------------------------------------
    
    void Oscillator_Init (void);             // Configure the system clock //
    void Port_Init (void);                       // Configure the Crossbar and GPIO //
    void Timer2_Init (int counts);           // Configure Timer2 //
    void PCA_Init (void);                    // Configure PCA for PWM mode //
    void Ext_Interrupt_Init (void);             // Configure External Interrupts (INT0) //
    
    
    INTERRUPT_PROTO (INT0_ISR, INTERRUPT_INT0);
    
    
    //-----------------------------------------------------------------------------
    // MAIN Routine
    //-----------------------------------------------------------------------------
    void main (void)
    {
       PCA0MD &= ~0x40;                       // Disable Watchdog timer //
       int RELOAD_VALUE = 0;
    
       Oscillator_Init();                  // Initialize the system clock //
       Port_Init ();                           // Initialize crossbar and GPIO //
       Timer2_Init(SYSCLK/100);// Initialize Timer2 to generate interrupts at a 20kHz rate//
       PCA_Init ();                    // Initialize PCA for PWM //
       Ext_Interrupt_Init();              // Initialize External Interrupts //
    
       EA = 1;
    
       while(1)                           // Infinite while loop //
    {
                     if(TF2H == 1)
                     {
                             if (RELOAD_VALUE<65535)
                                            {
                                                    TF2H = 0;
                                                    PCA0CP0 = RELOAD_VALUE;
                                                    RELOAD_VALUE ++;
                                            }
                             else
                                            {
                                                    TF2H = 0;
                                                    RELOAD_VALUE =0;
                                            }
                            }
    
    }
    
    }
    
    
    //-----------------------------------------------------------------------------
    // Oscillator_Init
    //-----------------------------------------------------------------------------
    // This routine initializes the system clock to use the precision internal
    // oscillator as its clock source.
    //-----------------------------------------------------------------------------
    void Oscillator_Init (void)
    {
            CLKSEL = 0x00;    // Clock Select. SYSCLK is derived from the Internal High Frequency Oscillator and scaled per IFCN bits in register OSCICN //
            OSCICN = 0x83;            // Internal H-F Oscillator enabled and SYSCLK derived from Internal H-F Oscillator divided by 1 //
    }
    
    
    //-----------------------------------------------------------------------------
    // Port_Init
    //-----------------------------------------------------------------------------
    
    void Port_Init (void)
    {
    
       XBR1      = 0x40;            // Enable crossbar and weak pull ups //                    P0SKIP    = 0x7F;                    // Skip unused pins on P0 and P1 //
       P1SKIP    = 0xFF;
    
    }
    
    
    //-----------------------------------------------------------------------------
    // Timer2_Init
    //-----------------------------------------------------------------------------
    
    void Timer2_Init (int counts)
    {
    
       TMR2CN  = 0x00;                 // Stop Timer2. Clear T2SPLIT.
                                   // Use SYSCLK/12 as timebase, 16-bit auto-reload
       CKCON  |= 0x30;                // Timer2 High and Low byte uses the SYSCLK //
       TMR2RL  = -counts;           // Initialize reload value
       TMR2    = 0xFFFF;               // Set to reload immediately
    
    }
    
    
    //-----------------------------------------------------------------------------
    // PCA_Init
    //-----------------------------------------------------------------------------
    
    void PCA_Init(void)
    {
    
            PCA0MD    = 0x00;             // PCA Counter/Timer Idle Control enabled, Watchdog timer disabled, Watchdog timer enable unlocked, Unused, System clock divided by 12, Disable CF Interrupt //
            PCA0CPM0  = 0x82;             // PWM 16, ECOM, TOG, PWM, ECCF bits set //
             PCA0PWM        &= ~0x80;
    }
    
    
    //-----------------------------------------------------------------------------
    // Ext_Interrupt_Init
    //-----------------------------------------------------------------------------
    
    void Ext_Interrupt_Init (void)
    {
    
       TCON   = 0x01;                   // INT 0 is edge triggered //
       IT01CF = 0x07;                   // INT0 active low; INT0 on P0.7 //
       EX0 = 1;                         // Enable INT0 interrupts //
    
    }
    
    
    //-----------------------------------------------------------------------------
    // Interrupt Service Routines
    //-----------------------------------------------------------------------------
    
    INTERRUPT(INT0_ISR, INTERRUPT_INT0)
    {
       TR2  = 1;            // Start Timer2 //
    }
    
    

Children
No data