This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| en:avr:interrupts [2010/02/08 14:55] – mikk.leini | en:avr:interrupts [2020/07/20 12:00] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Interrupts ====== | ||
| + | Interrupts in AVR can be caused by counters, communication interfaces, analog-to-digital converters, comparators, | ||
| + | |||
| + | Every interrupt in the AVR microcontroller is tied to a specific event. Each event has a flag bit in the status register, which marks the occurring of the event. Events are also tied to interrupt mask registers and the corresponding bits. If the event' | ||
| + | |||
| + | <box 100% round # | ||
| + | |||
| + | To use interrupts with the AVR LibC library, it is necessary to include // | ||
| + | |||
| + | <code c> | ||
| + | #include < | ||
| + | |||
| + | ISR(XXX_vect) | ||
| + | { | ||
| + | // Do something | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | </ | ||
| + | |||
| + | Global allowing of all interrupts is configured from the control and status register SREG. The option to allow or disallow all interrupts at once is there to help protect data. Since interrupts disrupt the execution of the main program, some data used by the main program may be disturbed or corrupted in the process. Situations like this can be avoided by simply disallowing all interrupts before processing such delicate data. Disallowing interrupts globally is easy, if it can be done by changing only one register (SREG). After the critical part of the program has been executed, the interrupts can easily be allowed again and all the interrupts that would have fired in the meantime are executed. | ||
| + | |||
| + | < | ||
| + | |||
| + | <box 100% round # | ||
| + | |||
| + | Let's suppose there is a 16-bit variable in use in the program, which is changed by both the main program and the interrupt program and the value of this variable is later given to another variable: | ||
| + | |||
| + | <code c> | ||
| + | #include < | ||
| + | |||
| + | // Global 16-bit variables x and y | ||
| + | unsigned short x, y; | ||
| + | |||
| + | // A random interrupt that changes the value of x | ||
| + | ISR(XXX_vect) | ||
| + | { | ||
| + | x = 0x3333; | ||
| + | } | ||
| + | |||
| + | int main() | ||
| + | { | ||
| + | // Give a value to x | ||
| + | x = 0x1111; | ||
| + | |||
| + | // Allow interrupts globally | ||
| + | sei(); | ||
| + | |||
| + | // Give the value of x to y | ||
| + | y = x; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | The program itself is very simple - first, variable x is given a value of 0x1111 and later, its value is given to variable y. If an interrupt occurs between those two operations, x gets a value of 0x3333. By logic, variable y can have two possible values by the end of the program, but on an 8-bit AVR there is also a third option. This is because 8-bit architecture needs 2 cycles to move 16-bit data and therefore a badly-timed interrupt can corrupt the integrity of the data. Consequently, | ||
| + | |||
| + | In the following example, the value of x is given to y using a safe method: | ||
| + | |||
| + | <code c> | ||
| + | // Disallow interrupts globally | ||
| + | cli(); | ||
| + | |||
| + | // Give the value of x to y | ||
| + | y = x; | ||
| + | |||
| + | // Re-allow all interrupts again | ||
| + | sei(); | ||
| + | </ | ||
| + | |||
| + | </ | ||