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
  • Well - the only reason to have individual initialization functions - and to have just initialization in them - is basically a question of maintenance.

    Having many small initialization functions makes it easy to enable/disable individual peripherials when trying to debug specific issues.

    And separate initialization code from action code means that all the initialization can be run first, before the program enters the main loop. Then the action code can do its thing based on whatever stimuli the program sees - keypresses, timers interrupting, ...

    Interrupts aren't magical. There are some minor differences between processor architectures. But you normally have nested interrupts or not. With nested interrupts, a higher-prio interrupt source may activate while the processor is already servicing a lower-prio interrupt source. Interrupt nesting is like a stack. When the high-prio interrupt ends, the processor drops back to the less prioritized interrupt and continues with the next instruction. When that interrupt handler, the program returns to the main loop code.

    If the processor doesn't support interrupt nesting, or the code doesn't enable interrupt nesting, then the first interrupt service routine (whatever prio it may have) must end, before a new interrupt service routine can get activated. Often, the processor manages to do maybe one instruction from the main loop before activating next pending interrupt service handler.

    Enabling interrupts doesn't mean an interrupt will happen. It only means that interrupts are globally allowed, or that interrupts from a specific peripherial is specifically allowed. There still needs to be an event of some kind for that peripherial to actually rise the interrupt service flag asking for an interrupt to happen. Such as the UART receiving a character. Sometimes the interrupt comes directly - like enabling UART transmit interrupts and instantly get a "I'm hungry - feed me" transmit interrupt.

    Anyway - the route to learn a new processor is to test one peripherial at a time. And only combine multiple peripherials as the individual modules have been tested. Easy to do when there is a separate function to initialize. A separate interrupt service handler. Individual "action" functions for interacting - like checking if data have been received from the UART or adding outgoing data to a send queue.

    While learning a new peripherial, it's also possible to test much of the code in polling mode directly from the main loop before upgrading the code to use interrupt handlers, separating the timeline of the peripherial device from the timeline of the main program flow.

    Anyway - in the end it's impossible to help people except when they are stuck with explicit and well-defined problems.

Reply
  • Well - the only reason to have individual initialization functions - and to have just initialization in them - is basically a question of maintenance.

    Having many small initialization functions makes it easy to enable/disable individual peripherials when trying to debug specific issues.

    And separate initialization code from action code means that all the initialization can be run first, before the program enters the main loop. Then the action code can do its thing based on whatever stimuli the program sees - keypresses, timers interrupting, ...

    Interrupts aren't magical. There are some minor differences between processor architectures. But you normally have nested interrupts or not. With nested interrupts, a higher-prio interrupt source may activate while the processor is already servicing a lower-prio interrupt source. Interrupt nesting is like a stack. When the high-prio interrupt ends, the processor drops back to the less prioritized interrupt and continues with the next instruction. When that interrupt handler, the program returns to the main loop code.

    If the processor doesn't support interrupt nesting, or the code doesn't enable interrupt nesting, then the first interrupt service routine (whatever prio it may have) must end, before a new interrupt service routine can get activated. Often, the processor manages to do maybe one instruction from the main loop before activating next pending interrupt service handler.

    Enabling interrupts doesn't mean an interrupt will happen. It only means that interrupts are globally allowed, or that interrupts from a specific peripherial is specifically allowed. There still needs to be an event of some kind for that peripherial to actually rise the interrupt service flag asking for an interrupt to happen. Such as the UART receiving a character. Sometimes the interrupt comes directly - like enabling UART transmit interrupts and instantly get a "I'm hungry - feed me" transmit interrupt.

    Anyway - the route to learn a new processor is to test one peripherial at a time. And only combine multiple peripherials as the individual modules have been tested. Easy to do when there is a separate function to initialize. A separate interrupt service handler. Individual "action" functions for interacting - like checking if data have been received from the UART or adding outgoing data to a send queue.

    While learning a new peripherial, it's also possible to test much of the code in polling mode directly from the main loop before upgrading the code to use interrupt handlers, separating the timeline of the peripherial device from the timeline of the main program flow.

    Anyway - in the end it's impossible to help people except when they are stuck with explicit and well-defined problems.

Children
No data