[ Log In ]

An interrupt is an event that stops regular program flow to run a separate set of code that relates to the interrupt. Interrupts have many uses and applications. Interrupts can be used with:
- Timers and counters (When a timer matches a specific value)
- Serial communications (USART, UART - tell you when data is received, or when the transmit is ready to take data to transmit)
- When a pin goes from high to low or vice verse
- ADC (Analog to Digital Converter) completes the conversion
- Software interrupt (custom)
- And many others.

The interrupt can be used to create an event when the timer/counter TCNT1 or TCNT0 achieves a specific value. The OCR1A is used to hold this value.

The TCCR1B is set to a prescaler of 64 using the Clock Select bits (CS10, CS11 and CS 12) and another control bit called WGM12 (Waveform Generation Mode) CTC Mode (Clear Timer on Compare). This will cause the TCNT1 to go back to 0 when the OCR1A value is hit.

sei() is used to enable global interrupts along with the timer interrupts enable control TIMSK.

The interrupt can be used to create an event when the timer/counter TCNT1 or TCNT0 achieves a specific value. The OCR1A is used to hold this value.

The TCCR1B is set to a prescaler of 64 using the Clock Select bits (CS10, CS11 and CS 12) and another control bit called WGM12 (Waveform Generation Mode) CTC Mode (Clear Timer on Compare). This will cause the TCNT1 to go back to 0 when the OCR1A value is hit.

sei() is used to enable global interrupts along with the timer interrupts enable control TIMSK.

The interrupt can be used to create an event when the timer/counter TCNT1 or TCNT0 achieves a specific value. The OCR1A is used to hold this value.

The TCCR1B is set to a prescaler of 64 using the Clock Select bits (CS10, CS11 and CS 12) and another control bit called WGM12 (Waveform Generation Mode) CTC Mode (Clear Timer on Compare). This will cause the TCNT1 to go back to 0 when the OCR1A value is hit.

sei() is used to enable global interrupts along with the timer interrupts enable control TIMSK.

To test the output, an LED is connected to PORTB pin 0 and toggled on the interrupt.

To enable interrupts, a library (header file) must be included:

To use the interrupt for the Timer/Counter, an ISR (Interrupt Service Routine) must be written.

Specifically relating to enabling the interrupt for the Timer/Counter, the WGM12 (Waveform Generation Mode) in the TCCR1B must be set so the TCNT1 CTCs (Clears on Timer Compare). The Timer Mask TIMSK must set the OCIE1A (Output Compare Interrupt Enable). This bit is related to the OCR1A. Alternatively, the OCIE1B and OCR1B could be used.

The OCR1A must be equal to the count that will invoke the interrupt.

The ADC (Analog to Digital Converter) converts an analog voltage between a range of voltages and provides an 8 to 10 bit number in proportion to the voltage sensed by the ADC.

In this video, the ADC automatically notifies of it's conversion complete using an interrupt. A potentiometer is used as a voltage divider to provide variable voltages to the ADC pin.

Enabling global interrupts must be done to allow the interrupt functions to work.

Setting the interrupt control bit is located in the ADCSRA Control and Status Register. The bit to set in this register is ADIE (Analog to Digital Interrupt Enable).

Optionally, we can check the ADIF flag to manually determine if the ADC has completed a conversion.

Remember that the global interrupt must be set sei(); and the interrupt service routine and vector is established and another conversion is started within this service routine.

To use the interrupt for the ADC, an ISR (Interrupt Service Routine) must be established. This is just a function that resides outside of the main function that will run whenever the ADC completes a conversion. Once completed and the function is started, make sure the have code in that function that starts a new conversion. The ISR requires a parameter of the ISR vector. The vector for the ADC is ADC_vect.

To be able to use the interrupts with the ADC, the ADC Interrupt Enable (ADIE) must be set which is located in the ADCSRA Control and Status Register.

To make sure that the interrupt will work, the global interrupt (I-bit in SREG) must be used:

sei();

This is a boilerplate code to initialize the ADC for interrupts and including the LCD library so the result can be displayed.

In this program, interrupts are used to provide an interrupt every time the PWM counter reaches the top value in ICR1 (Input Capture Register 1).

Within the ISR (Interrupt Service Routine), all of the pins that will output the PWM signal will go high. This is to start all of the pins off as a pulse. When the timer reaches the desired width, that single pin will go low. This is using the TCNT1 register to determine the counts.

To enable the interrupt for the Timer, the TIMSK1 (Timer Mask) OCIE1A (Output Compare Interrupt Enable 1A) bit is set.

In this program, interrupts are used to provide an interrupt every time the PWM counter reaches the top value in ICR1 (Input Capture Register 1).

Within the ISR (Interrupt Service Routine), all of the pins that will output the PWM signal will go high. This is to start all of the pins off as a pulse. When the timer reaches the desired width, that single pin will go low. This is using the TCNT1 register to determine the counts.

To enable the interrupt for the Timer, the TIMSK1 (Timer Mask) OCIE1A (Output Compare Interrupt Enable 1A) bit is set.

The oscilloscope is also used to show the PWM output on the pin of choice.

Important aspects of outputting to more than one pin are as follows:

- Make sure the pins that will output the PWM are set for output data direction (i.e. DDRB = 0xFF for all PORT B pins output)

- Make sure that the pins will be set high in the interrupt service routine (ISR)

- Add another line within code block of the if (TCNT1>=800 && TCNT1<=2400) and make sure the pin reflect the correct output pin and the number after the TCNT1 >= value is correctly set for the position for that servo on that pin.

Important aspects of outputting to more than one pin are as follows:

- Make sure the pins that will output the PWM are set for output data direction (i.e. DDRB = 0xFF for all PORT B pins output)

- Make sure that the pins will be set high in the interrupt service routine (ISR)

- Add another line within code block of the if (TCNT1>=800 && TCNT1<=2400) and make sure the pin reflect the correct output pin and the number after the TCNT1 >= value is correctly set for the position for that servo on that pin.

Important aspects of outputting to more than one pin are as follows:

- Make sure the pins that will output the PWM are set for output data direction (i.e. DDRB = 0xFF for all PORT B pins output)

- Make sure that the pins will be set high in the interrupt service routine (ISR)

- Add another line within code block of the if (TCNT1>=800 && TCNT1<=2400) and make sure the pin reflect the correct output pin and the number after the TCNT1 >= value is correctly set for the position for that servo on that pin.

Only three servos were available, so the true output will not be shown.

Important aspects of outputting to more than one pin are as follows:

- Make sure the pins that will output the PWM are set for output data direction (i.e. DDRB = 0xFF for all PORT B pins output)

- Make sure that the pins will be set high in the interrupt service routine (ISR)

- Add another line within code block of the if (TCNT1>=800 && TCNT1<=2400) and make sure the pin reflect the correct output pin and the number after the TCNT1 >= value is correctly set for the position for that servo on that pin.

The interrupts library must be included. The OCIE1A (Output Compare Interrupt Enable) is set in the TIMSK1 (Timer mask) register to enable the interrupts for the timer/counter when the ICR (Input Capture Register) is reached. The Global Interrupt is used sei();. When the ICR value is reached, the ISR (Interrupt Service Routine) for the TIMER1_COMPA_vect is called.

The LCD library and initialization is established. The interrupts for the ADC is started and a string is sent to the LCD. This is to get ready for the pressure sensor program. A string is sent to the LCD to create a label called Pressure.

Enabling the ADC (turning the ADC on) is setting the ADEN (ADC Enable) in the ADCSRA (ADC Control and Status Register).

Starting a new single conversion is also in the ADCSRA and is the ADSC (ADC Single Conversion) bit.

When creating a global variable, especially when the variable will be used in an ISR (Interrupt Service Routine), this global variable may be eliminated by the compiler (optimized out). To force this variable to be used and not optimized out, declare the variable with its type and 'static volatile' and then the variable.

An interrupt can be triggered by outputting a signal on a pin (output pin) and connecting that pin back to an input pin. This can be resolved within the program, but an interesting idea.

Interrups are difficult to debug. For instance, putting a print statement inside an interrupt service routine will cause a high time delay within the ISR.

There is only enough memory to handle a single interrupts. If there is a desire to handle two interrupts, only one of them will fire is the current interrupt is not completed.

*another explanation in the description*
Watch with sound!
in this video i'll explain the interrupt coding principle.
the interrupt example is written to PIC16F887 but the explanation is relavent to a large variety of microcontrollers, including arduino!

feel free to comment with questions and requests.


if the principle is still not clear, reffer to this analogy:
imagine a situation where your phone can't ring or vibrate, during every day routine, in order to know if you got a call you need to constantly look at the phone's screen, So if you are waiting on an important phone call you will check the phone every few seconds, this is like the polling principle:

if(Pone_Ring())
Answer;
Rest_of_Life();
if(Pone_Ring())
Answer;
Rest_of_Life();
if(Pone_Ring())
Answer;
Rest_of_Life();

and so on.
but if your phone is fine, then you can do everything (within the legal boundaries) you want, and at the second you get a phone call a Flag will raise(you will hear the phone Ring) and you would answer it. without the need of constantly checking wheter you have a call or not.



music: Paintball theme, by Bird Creek

*another explanation in the description*
Watch with sound!
in this video i'll explain the interrupt coding principle.
the interrupt example is written to PIC16F887 but the explanation is relavent to a large variety of microcontrollers, including arduino!

feel free to comment with questions and requests.


if the principle is still not clear, reffer to this analogy:
imagine a situation where your phone can't ring or vibrate, during every day routine, in order to know if you got a call you need to constantly look at the phone's screen, So if you are waiting on an important phone call you will check the phone every few seconds, this is like the polling principle:

if(Pone_Ring())
Answer;
Rest_of_Life();
if(Pone_Ring())
Answer;
Rest_of_Life();
if(Pone_Ring())
Answer;
Rest_of_Life();

and so on.
but if your phone is fine, then you can do everything (within the legal boundaries) you want, and at the second you get a phone call a Flag will raise(you will hear the phone Ring) and you would answer it. without the need of constantly checking wheter you have a call or not.



music: Paintball theme, by Bird Creek