Quote: "Would you be able to list a few small projects (links are fine) which demonstrates some of these?"
Most of those features listed can be applied in projects in the first post I made. I cannot stress the importance of interrupts enough, so here's a small post to get you started on that.
What is an interrupt? (or to use the proper term: ISR -> "Interrupt Service Routine")
An interrupt is - as the name suggests - an interruption which is triggered at any point in the program. It literally stops your program from being executed, immediately jumps to the interrupt service routine and begins executing the code there. Once that's done, it jumps back to where the program was stopped and resumes it again.
This is a technique introduced into micro controllers and computers today in general for multiple reasons.
1) By using interrupts you can create the illusion of processing multiple things at once.
2) It enables the micro controller to react to things immediately.
3) Interrupts can be used for time controlled things (we'll look at an example soon)
4) It allows the micro controller to do literally nothing when there's nothing to do. No really, the CPU is actually turned off when it finishes processing whatever, and the micro controller goes into sleep mode. This saves a lot of power and is very useful for low power applications (With "lower power" we're talking micro amps). Interesting fact: The "Game Boy" from nintendo had the CPU in idle mode for over 80% of the time.
Important things to know
ISRs have to contain as little code as possible. Actual processing of the data should be avoided if possible (and in almost all cases they are avoidable). The reason for this is to keep the execution time of the ISR below the time intervals between calling it. If your ISR takes longer to execute than the time it takes to call it, it will be "swallowed". The main program won't have any time to execute at all, and you'll be opening new interrupts again and again.
This leads me to explaining the technique of how to handle interrupts. Here is a very common example:
void main( void )
{
// main loop
while(1)
{
ProcessEvents(); // This processes events logged by interrupts
if( EventCount == 0 ) Sleep(); // Puts CPU to sleep
}
}
// Interrupt service routine
void ISR( vect )
{
// Add some kind of event to the event list here
}
So lets go through that by making up an example. An old man is sleeping in his chair next to a telephone. Suddenly, the telephone rings. The old man wakes up and answers the phone. He gets loads of information which he writes down onto a piece of paper. Angry, he hangs up the phone and begins doing all of the things listed on the piece of paper. Half way through the phone rings again! Damn it, the old man drops what he's doing and answers the phone. More things to do! The old man notes these things down onto the paper as well, hangs up the phone, and continues working his way down the list of things to do. Finally, he finishes the last instruction. Satisfied, he sits back onto his chair and goes to sleep.
There's no difference between that story and what's happening with your micro controller. Note how the old man
wrote onto a piece of paper what he had to do. Imagine if the old man had sat on the phone and did all of the things directly, what do you think would have happened? That's right, he would have
missed the second call completely. That's why it's important to do as little as possible in ISRs.
How does the micro controller handle them?
First of all, there's a global flag for interrupts stored in the CPU status register (SREG). You can think of this as a main switch. If this switch is turned off, interrupts won't work at all. If it's turned on, then they will work.
There is also a local flag for every individual interrupt stored in another register. With these you are able to enable/disable specific ISRs at any time you wish.
There might be a time where you don't want to be interrupted during your processing. That's when you can temporarily disable specific or all interrupts in the system. After you've finished processing whatever you are doing, you can re-enable them.
So what happens when an interrupt occurs during the time when you have them disabled? Quite simple really, the interrupt is queued. So when you re-anble the interrupt flags, all of the queued interrupts will execute. The only time when you'll lose a queued interrupt is if the exact same interrupt service routine is called again. Then it will just replace the last one.
Getting familiar
In order to get familiar with interrupts, I first suggest to do one of the simples things possible:
A flashing LED at exactly 1 Hz. Here's pretty much the procedure:
There are different types of timer modules, so I'll explain the one I use to you.
Mine has a 16 bit counter (it's able to count from 0-65535). You are able to specify the starting value (from where it begins to count) and the end value (where it should stop counting). From there I can also tell it to reload the starting value and begin counting again (so it does this continuously).
It also has a divider of either 2,8 or 12 (strange numbers, I know). This means that it divides the clock frequency by said number, and passes that to the counter.
So for example, my clock frequency is 40 MHz. I tell the timer module to divide it by 12, which gives me 3.333 MHz. Still way to high for creating any interrupts, but that's what the counter is for. The end frequency I want is 100 Hz, so now all I have to do is solve for the maximum counter value : Counter = 3.333 MHz / 100 Hz = 33'333. Excellent, I set my counter to count from 0-33333, and that means that the counter reaches 33333 every 10ms.
The last thing I do is I tell the timer module to trigger an interrupt when it resets.
This means that the interrupt is triggered once every 10ms. So logically, in order to get the LED to flash at 1 Hz, you'll have to count how many times the interrupt occurs, and invert the LED when it reaches a value of 50.
My boss is staring at me and I think he knows that I'm not doing what I'm supposed to.
Hope this helped!
TheComet
"if you don't understand recursion than you probably don't understand recursion." ~Jerico2day