The problem with using the built in delay is that CPU clock cycles are essentially wasted. In such a simple program like we had in the previous post, we are not worried about conserving clock cycles but you can imagine that in a very complex program you would want every clock cycle to do something. Once interrupts are set up and enabled, they will "interrupt" the program when a certain condition is met. In the case of delay, a timer counts clock cycles and once a certain number is reached, the program is interrupted and carries out a "service routine" specified by the programmer. Once the service routine is finished, the program returns to the line of code it was executing when the interrupt occurred.
To illustrate the difference between the two types of delays, I wrote a program that does the exact same thing as the program in the previous post but it uses interrupts rather than the built in delay. This program simply makes the built in LEDs turn on and off at a rate that is perceptible to the human eye:
#include <avr/io.h>
#include <avr/interrupt.h>
int main(void)
{
DDRB = 0xFF; //PORT B (LEDs) output
TCNT0 = 0; //timer starts at zero
OCR0 = 200; //and counts up to 200
TCCR0 = 0b00001101; //CTC mode, internal clk, 1024 prescaler
sei(); //global interrupt enable
TIMSK = (1<<OCIE0); //timer0 overflow interrupt enable
while(1)
asm("nop"); //stay here....
}
ISR (TIMER0_COMP_vect)
{
PORTB ^= 0xFF; //toggle PORTB (LEDs)
}
So you can load this program using the same method as I showed before and see that the LEDs simply turn on and off. All the connections should be exactly the same.
Some notes on the program: we first set up timer0 by setting TCCR0 to the binary 0001101. Of course we could express this in hex or even decimal but for me, the binary makes it easier to understand whats going on. Using the 8 bits of the TCCR0 register, you can specify whether you want "normal mode" (based on overflow) or "CTC mode" (based on compare match). You can also specify a prescaler value which is multiplies the number of clock cycles needed for a count. In other words, a large prescalar makes a delay longer. For our purposes, we'll set TCCR0 for CTC mode and have a prescaler of 1024. TCNT0 is the register which counts upwards with the clock cycles so we want this to start at zero. OCR0 is the value that TCNT0 will count up to before the interrupt occurs, so we will set this to 200. Note that since this is an 8 bit register, the largest value possible is 255. The sei() command sets the global interrupt bit and TIMSK enables the various different conditions that can cause an interrupt. The one we want is OCIE0 (timer0 overflow) which is actually bit _. Finally, the asm("nop") is not necessary for the program to work but it makes it easier to simulate the program in the AVR Simulator.
Speaking of the AVR Simulator or debugger in AVR Studio, lets take a look at how to make sure the program works without even loading it on the AVR. After you have entered all the code and hit F7 for build, go to Debug on the top menu and select Start Debugging.
So thats about all I'm going to get into. Of course there is a lot more to this subject but this at least illustrates one example.
If the main lights are blinking and very low in voltages then how would people travel. Because a blinking light can be very dangerous.
ReplyDelete