{"id":10012,"date":"2015-12-05T22:23:03","date_gmt":"2015-12-06T03:23:03","guid":{"rendered":"http:\/\/embedded-lab.com\/blog\/?p=10012"},"modified":"2016-12-18T19:43:18","modified_gmt":"2016-12-19T00:43:18","slug":"xmega-external-interrupt","status":"publish","type":"post","link":"https:\/\/embedded-lab.com\/blog\/xmega-external-interrupt\/","title":{"rendered":"XMega External Interrupt"},"content":{"rendered":"<p>External interrupts are a must have feature in any microcontroller. Interrupts solve a lot of problem that would have otherwise been dependent on polling methods. For instance when we press the volume up key of a TV tuner\u2019s remote controller, the remote controller quickly responds by transmitting the volume up command to the TV set and in turn the TV\u2019s volume increases. This fast response is due to external interrupt issued by the remote\u2019s button to the microcontroller it is connected to. If, however, all the keys of the remote were regularly and frequently scanned and then responded up on a press, the process would have been both slow and energy consuming because its microcontroller would then have never went to sleep or low power states and continuously kept scanning. In other words, the micro would have always ran despite no mandatory necessity and during standby conditions. This would have quickly drained the batteries. Since interrupt is typically used in such cases the remote controller will respond to a button press fast, wake up from sleep\/idle\/low power mode, transmit command data and then go back to sleep\/idle\/low power state. Thus the overall energy consumption is reduced while achieving fastest possible reaction. This is how real world applications work applying external interrupts.<\/p>\n<p><a href=\"http:\/\/embedded-lab.com\/blog\/xmega-external-interrupt\/xmega-3d\/\" rel=\"attachment wp-att-10014\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10014\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/XMega-3D.png\" alt=\"XMega 3D\" width=\"590\" height=\"529\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/XMega-3D.png 590w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/XMega-3D-550x493.png 550w\" sizes=\"auto, (max-width: 590px) 100vw, 590px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p><!--more--><\/p>\n<p>XMega devices just like any micro are equipped with interrupts for both external and internal peripherals but it is more than you can even guess. Any I\/O pin or group of I\/O pins can be used for external interrupt. Now that\u2019s a cool feature and a great relief as well because most traditional 8-bit micros like the ATMega328P, which is by the way the most widely used by the Arduino community, has only two external interrupts and fixed to one I\/O port only. Other larger Mega AVRs have up to eight external interrupts. However XMega\u2019s interrupt system is much more complex than those traditional AVRs. XMega devices support both maskable and non-maskable interrupts (NMI). Currently, however, there is only one NMI and it occurs due to crystal oscillator failure event. NMI is independent of global interrupt enable status. Unlike most traditional micros, interrupt priority can be set apart from edge selection and other stuffs. Priority setting has the effect of determining which interrupt can or will further interrupt another interrupt and so forth.<\/p>\n<p><a href=\"http:\/\/embedded-lab.com\/blog\/xmega-external-interrupt\/interrupt-system-internal-circuitry\/\" rel=\"attachment wp-att-10017\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10017\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/Interrupt-System-Internal-Circuitry.png\" alt=\"Interrupt System Internal Circuitry\" width=\"590\" height=\"204\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/Interrupt-System-Internal-Circuitry.png 590w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/Interrupt-System-Internal-Circuitry-550x190.png 550w\" sizes=\"auto, (max-width: 590px) 100vw, 590px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<h4>The PMIC and Interrupt Priority<\/h4>\n<p>The <b><i>Programmable Multilevel Interrupt Controller (PMIC)<\/i><\/b> is responsible for handling and prioritizing interrupt requests. As with any microcontroller the global interrupt flag (<b><i>SREG_I_bit<\/i><\/b>) should be set before using the interrupt system. When a given interrupt condition is enabled and present, the PMIC receives interrupt request and it either acknowledges it or keeps it waiting based on interrupt priority and ongoing interrupts (if any). After executing an interrupt request, the PMIC returns to the proper interrupt level or to a state before the occurrence of the interrupt.<\/p>\n<p>&nbsp;<\/p>\n<p>XMega reference manual states that there are three possible interrupt priority levels:<\/p>\n<p><a href=\"http:\/\/embedded-lab.com\/blog\/xmega-external-interrupt\/interrupt-priority\/\" rel=\"attachment wp-att-10016\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10016\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/Interrupt-Priority.png\" alt=\"Interrupt Priority\" width=\"590\" height=\"111\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/Interrupt-Priority.png 590w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/Interrupt-Priority-550x103.png 550w\" sizes=\"auto, (max-width: 590px) 100vw, 590px\" \/><\/a><\/p>\n<p>The PMIC prioritizes interrupts according to the following order:<a href=\"http:\/\/embedded-lab.com\/blog\/xmega-external-interrupt\/interrupt-priority-levels\/\" rel=\"attachment wp-att-10026\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10026\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/Interrupt-Priority-Levels.png\" alt=\"Interrupt Priority Levels\" width=\"322\" height=\"256\" \/><\/a><\/p>\n<p>This shows that a higher order interrupt will interrupt a lower order interrupt if both are occurring at the same instance. After processing the higher order interrupt the lower order interrupt is processed. Within a given order, interrupts with lower interrupt vector addresses have higher priorities than those with higher addresses. Typically reset has the highest priority and the lowest interrupt vector address. The same is true for XMega micros too. NMI is the next highest priority interrupt request.<\/p>\n<p><a href=\"http:\/\/embedded-lab.com\/blog\/xmega-external-interrupt\/isr-address-vs-priority\/\" rel=\"attachment wp-att-10018\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10018\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/ISR-Address-vs-Priority.png\" alt=\"ISR Address vs Priority\" width=\"385\" height=\"407\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>In the XMega, there are two types of interrupt and these are static and dynamic. Static interrupts are those which have fixed vector addresses while low priority interrupts are dynamic and this dynamic behaviour is achieved by <b><i>Round-robin Scheduling (RRS)<\/i><\/b> technique. The RRS ensures that the low level interrupts are not skipped. If this technique is applied then the last invoked interrupt will have the lowest priority for one or more interrupts. Thus within the low level interrupt there is a mechanism that makes sure that all of them are served within a certain time frame.<\/p>\n<p><a href=\"http:\/\/embedded-lab.com\/blog\/xmega-external-interrupt\/round-robin-scheme\/\" rel=\"attachment wp-att-10019\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10019\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/Round-Robin-Scheme.png\" alt=\"Round Robin Scheme\" width=\"590\" height=\"437\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/Round-Robin-Scheme.png 590w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/Round-Robin-Scheme-550x407.png 550w\" sizes=\"auto, (max-width: 590px) 100vw, 590px\" \/><br \/>\n<\/a><\/p>\n<h4><\/h4>\n<h4>Interrupt Service Routine in XMega Devices<\/h4>\n<p>All maskable interrupt peripherals have interrupt flags and settings to set interrupt priority as well as enabling them. Irrespective of its settings an interrupt flag will be set when it occurs. The interrupt flags in most cases are automatically cleared up on executing them or by setting them in software.<\/p>\n<p><b><i>Some key points regarding interrupt handling:<br \/>\n<\/i><\/b><\/p>\n<ul>\n<li>When a higher priority interrupt is ongoing and lower priority interrupt invokes, the lower priority interrupt is remembered and kept pending until its priority comes.<\/li>\n<li>When a higher priority interrupt overtakes an ongoing lower priority interrupt, the lower priority interrupt is remembered and served after executing the higher priority interrupt.<\/li>\n<li>If an interrupt has lower vector address then it will overtake another interrupt of same priority having a higher address. The latter will be remembered and served after executing the former.<\/li>\n<li>If an interrupt is disabled and it occurs, it is remembered until it is enabled or cleared by software. Previously in my post regarding the XMega ADC block we encountered this stuff.<\/li>\n<li>If interrupts occur when the global interrupt enable bit is disabled, all of the interrupts are remembered and processed according to priority when the global interrupt is enabled.<\/li>\n<li>Active interrupts can be cleared by issuing clear interrupt instruction <b><i>asm cli; <\/i><\/b>in assembly. This is just the opposite of global interrupt enable using the <b><i>asm sei; <\/i><\/b>instruction.<\/li>\n<\/ul>\n<p>Remember these points when watching the code example video. You\u2019ll certainly see all these happen.<\/p>\n<p>&nbsp;<\/p>\n<h4>Interrupt Disarmament<\/h4>\n<p>All maskable interrupts are disabled for four clock cycles automatically when the <b><i>Configuration Change Protection (CPU_CCP)<\/i><\/b><i> <\/i>register is feed with two correct instruction signatures. These are:<\/p>\n<ul>\n<li><i>Protect I\/O instruction (CCP_IOREG, 0xD8)<\/i>.<br \/>\nPrevents unintentional writes into protected peripheral registers. We already encountered it in the XMega Clock System post.&nbsp;<\/li>\n<li><i>Store Program Memory (CPU_SPM, 0x9D).<br \/>\n<\/i>Used to write to the XMega\u2019s flash memory from application software. <i><\/i><\/li>\n<\/ul>\n<p>Correct signature values as above should be feed to the <b><i>CPU_CCP<\/i><\/b> register before executing SPM instruction or modifying protected peripheral registers.<\/p>\n<p>&nbsp;<\/p>\n<h4>XMega Port Interrupt<\/h4>\n<p>Before understanding I\/O port pin interrupt, I would like to request readers to brush up my earlier post on XMega I\/O Ports <a href=\"http:\/\/embedded-lab.com\/blog\/?p=8989\" target=\"_blank\">here<\/a> because in that post I discussed about edge selection as well as other I\/O port pin properties which are necessary for external interrupts. The I\/O pins of the XMega are such that an external interrupt can occur when the logic state of a single pin or a group of pins changes. Every port in an XMega device has two independent external interrupt vector addresses (<b><i>INT0<\/i><\/b> and <b><i>INT1<\/i><\/b>).<\/p>\n<p>To configure external interrupts, we need to configure I\/O pins first. After having I\/Os setup, interrupt priorities are set for respective vector address. Finally before setting global interrupt flag, interrupt pin masks are applied to set which pins will invoke a given interrupt. When an interrupt occurs its corresponding flag is set. Shown below are port pin interrupt registers. We\u2019ll have to set them.<br \/>\n<a style=\"font-size: 0.95em;line-height: 1.6em\" href=\"http:\/\/embedded-lab.com\/blog\/xmega-external-interrupt\/port-interrupt-registers\/\" rel=\"attachment wp-att-10027\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10027\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/Port-Interrupt-Registers.png\" alt=\"Port Interrupt Registers\" width=\"590\" height=\"84\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/Port-Interrupt-Registers.png 590w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/Port-Interrupt-Registers-550x78.png 550w\" sizes=\"auto, (max-width: 590px) 100vw, 590px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #222222;font-size: 1.25em;font-weight: bold;line-height: 1em\">Coding<\/span><\/p>\n<p><span style=\"color: #111111;font-size: 0.95em;line-height: 1.6em\">The example code for external interrupt not only demonstrates the typical external interrupt response but also shows how priorities are handled. The ATXMega32A4U I used in this post runs at 8MHz clock derived from prescaled internal 32MHz oscillator. There are three LEDs (Red, Yellow and Green), two push buttons and a 16&#215;1 LCD attached to the XMega micro as shown:<\/span><\/p>\n<p><a href=\"http:\/\/embedded-lab.com\/blog\/xmega-external-interrupt\/schematic-2\/\" rel=\"attachment wp-att-10013\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10013\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/Schematic.png\" alt=\"Schematic\" width=\"590\" height=\"375\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/Schematic.png 590w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/Schematic-550x349.png 550w\" sizes=\"auto, (max-width: 590px) 100vw, 590px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>I\/O pin <b><i>PA0<\/i><\/b> is programmed as <b><i>INT0<\/i><\/b> pin while <b><i>PA1<\/i><\/b> is programmed as <b><i>INT1<\/i><\/b> pin. Both pins are configured to sense rising edge. Without any interrupt the main loop executes and the LCD shows <b><i>\u201cMain Loop\u201d <\/i><\/b>and D3 (Red LED) blinks. When INT0 (low level) interrupt occurs due to button press, the LCD shows <b><i>\u201cLOW Lvl ISR.\u201d<\/i><\/b> and D2 (Yellow LED) blinks sixteen times, halting the actions of the red LED. Similarly when INT1 (high level) interrupt occurs the LCD shows <b><i>\u201cHIGH Lvl ISR.\u201d <\/i><\/b>and D1 (Green LED) blinks sixteen times, pausing the actions of other two LEDs. After executing an interrupt either the next priority interrupt is served or moved to the main loop. In the example you\u2019ll notice everything I mentioned about <b><i>Interrupt Service Routine (ISR)<\/i><\/b> execution here.<\/p>\n<pre><\/pre>\n<pre><em><span style=\"color: #0000ff\">#include \"io.h\"<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">#include \"clock.h\"<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">#include \"interrupt.h\"<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">sbit LCD_RS at PORTC_OUT.B2;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">sbit LCD_EN at PORTC_OUT.B3;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">sbit LCD_D4 at PORTC_OUT.B4;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">sbit LCD_D5 at PORTC_OUT.B5;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">sbit LCD_D6 at PORTC_OUT.B6;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">sbit LCD_D7 at PORTC_OUT.B7;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">sbit LCD_RS_Direction at PORTC_DIR.B2;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">sbit LCD_EN_Direction at PORTC_DIR.B3;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">sbit LCD_D4_Direction at PORTC_DIR.B4;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">sbit LCD_D5_Direction at PORTC_DIR.B5;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">sbit LCD_D6_Direction at PORTC_DIR.B6;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">sbit LCD_D7_Direction at PORTC_DIR.B7;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">void setup_clock();<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">void setup_io();<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">void setup_interrupts();<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">void setup_lcd();<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">void PORTA_INT0_ISR()<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">org IVT_ADDR_PORTA_INT0<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">{<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 unsigned char s = 16;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 <\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 while(s &gt; 0)<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 {<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Lcd_Cmd(_LCD_CLEAR);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Lcd_Out(1, 1, \"LOW Lvl\");<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Lcd_Out(2, 3, \"ISR.\");<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 PORTD_OUT.B1 ^= 1;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 delay_ms(200);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 s--;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 }<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">}<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">void PORTA_INT1_ISR()<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">org IVT_ADDR_PORTA_INT1<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">{<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 unsigned char s = 16;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 <\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 while(s &gt; 0)<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 {<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Lcd_Cmd(_LCD_CLEAR);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Lcd_Out(1, 1, \"HIGH Lvl\");<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Lcd_Out(2, 3, \"ISR.\");<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 PORTD_OUT.B2 ^= 1;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 delay_ms(200);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 s--;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 }<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">}<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">void main() <\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">{<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0 setup_interrupts();<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0 setup_clock();<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0 setup_io();<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0 setup_lcd();<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0 <\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0 while(1)<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0 {<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Lcd_Cmd(_LCD_CLEAR);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Lcd_Out(1, 3, \"Main\");<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Lcd_Out(2, 3, \"Loop\");<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 PORTD_OUT.B0 ^= 1;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 delay_ms(900);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0\u00a0 }<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">}<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">void setup_clock()<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">{<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 clear_global_interrupt();<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 OSC_CTRL |= OSC_RC32KEN_bm;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 while(!(OSC_STATUS &amp; OSC_RC32KRDY_bm));<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 DFLLRC32M_CTRL = 0;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 OSC_CTRL |= OSC_RC32MEN_bm;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 while(!(OSC_STATUS &amp; OSC_RC32MRDY_bm));<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 OSC_DFLLCTRL = OSC_RC32MCREF_RC32K_gc;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 DFLLRC32M_CTRL = DFLL_ENABLE_bm;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 CPU_CCP = CCP_IOREG_gc;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 CLK_PSCTRL = (CLK_PSADIV_4_gc | CLK_PSBCDIV_1_1_gc);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 CPU_CCP = CCP_IOREG_gc;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 CLK_CTRL = CLK_SCLKSEL_RC32M_gc;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 OSC_CTRL &amp;= ~(OSC_RC2MEN_bm | OSC_XOSCEN_bm | OSC_PLLEN_bm);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTCFG_CLKEVOUT = 0x00;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">}<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">void setup_io()<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">{<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTA_OUT = 0x00;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTA_DIR = 0x00;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTA_PIN0CTRL = (PORT_OPC_TOTEM_gc | PORT_ISC_RISING_gc);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTA_PIN1CTRL = (PORT_OPC_TOTEM_gc | PORT_ISC_RISING_gc);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTA_PIN2CTRL = (PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTA_PIN3CTRL = (PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTA_PIN4CTRL = (PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTA_PIN5CTRL = (PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTA_PIN6CTRL = (PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTA_PIN7CTRL = (PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTA_INTCTRL = (PORT_INT1LVL_HI_gc | PORT_INT0LVL_LO_gc);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTA_INT0MASK = 0x01;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTA_INT1MASK = 0x02;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 <\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTD_OUT = 0x00;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTD_DIR = 0x07;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTD_PIN0CTRL = (PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTD_PIN1CTRL = (PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTD_PIN2CTRL = (PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTD_PIN3CTRL = (PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTD_PIN4CTRL = (PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTD_PIN5CTRL = (PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTD_PIN6CTRL = (PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTD_PIN7CTRL = (PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTD_INTCTRL = (PORT_INT1LVL_OFF_gc | PORT_INT0LVL_OFF_gc);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTD_INT0MASK = 0x00;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PORTD_INT1MASK = 0x00;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 <\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 set_global_interrupt();<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">}<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">void setup_interrupts()<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">{<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 clear_global_interrupt();<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 CPU_CCP = CCP_IOREG_gc;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PMIC_CTRL = (PMIC_LOLVLEN_bm | PMIC_HILVLEN_bm);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 PMIC_INTPRI = 0x00;<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">}<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">void setup_lcd()<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">{<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 Lcd_Init();<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 Lcd_Cmd(_LCD_CLEAR);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">\u00a0\u00a0\u00a0 Lcd_Cmd(_LCD_CURSOR_OFF);<\/span><\/em><\/pre>\n<pre><em><span style=\"color: #0000ff\">}<\/span>\r\n<\/em><\/pre>\n<p>&nbsp;<\/p>\n<p><a href=\"http:\/\/embedded-lab.com\/blog\/xmega-external-interrupt\/20150205_192725\/\" rel=\"attachment wp-att-10024\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10024\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/20150205_192725.jpg\" alt=\"20150205_192725\" width=\"590\" height=\"519\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/20150205_192725.jpg 590w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/20150205_192725-550x483.jpg 550w\" sizes=\"auto, (max-width: 590px) 100vw, 590px\" \/><\/a> <a href=\"http:\/\/embedded-lab.com\/blog\/xmega-external-interrupt\/20150205_192746\/\" rel=\"attachment wp-att-10025\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10025\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/20150205_192746.jpg\" alt=\"20150205_192746\" width=\"590\" height=\"552\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/20150205_192746.jpg 590w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/20150205_192746-550x514.jpg 550w\" sizes=\"auto, (max-width: 590px) 100vw, 590px\" \/><\/a> <a href=\"http:\/\/embedded-lab.com\/blog\/xmega-external-interrupt\/20150205_192752\/\" rel=\"attachment wp-att-10023\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10023\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/20150205_192752.jpg\" alt=\"20150205_192752\" width=\"590\" height=\"527\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/20150205_192752.jpg 590w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2015\/02\/20150205_192752-550x491.jpg 550w\" sizes=\"auto, (max-width: 590px) 100vw, 590px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Demo video link: <a href=\"https:\/\/www.youtube.com\/watch?v=N5UjBS_hjlg\">https:\/\/www.youtube.com\/watch?v=N5UjBS_hjlg<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>So far we just dealt with external interrupts but there are also interrupts that result due to internal hardware peripherals like timers, communication modules, ADC, etc. I\u2019ll discuss about them in my upcoming posts when I deal with those hardware. Should you have understood how external interrupts work in the XMega, I believe you have clearly understood how other interrupts will behave. Lastly please do read the reference manual for more clear understanding.<\/p>\n<p>Files:\u00a0<a href=\"http:\/\/embedded-lab.com\/blog\/xmega-external-interrupt\/xmega-external-interrupt\/\" rel=\"attachment wp-att-10015\">XMega External Interrupt<\/a>.<\/p>\n<p>References:<\/p>\n<ul>\n<li>XMega AU Manual and Datasheet.<\/li>\n<li>Atmel\u2019s Official Website <a href=\"https:\/\/www.atmel.com\/\">https:\/\/www.atmel.com<br \/>\n<\/a><\/li>\n<\/ul>\n<p>Happy coding.<\/p>\n<address><i>Author: Shawon M. Shahryiar <\/i><\/address>\n<address><a title=\"https:\/\/www.facebook.com\/groups\/microarena\" href=\"https:\/\/www.facebook.com\/groups\/microarena\" target=\"_blank\"><i>https:\/\/www.facebook.com\/groups\/microarena<\/i><\/a><i><a title=\"https:\/\/www.facebook.com\/groups\/microarena\" href=\"https:\/\/www.facebook.com\/groups\/microarena\" target=\"_blank\">\u00a0 \u00a0<\/a><\/i><\/address>\n<address><a title=\"https:\/\/www.facebook.com\/MicroArena \" href=\"https:\/\/www.facebook.com\/MicroArena\" target=\"_blank\"><i>https:\/\/www.facebook.com\/MicroArena<\/i><i>\u00a0<\/i><\/a><\/address>\n<address><i>+8801970046495 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<\/i><\/address>\n<address><i>06.02.2015<\/i><\/address>\n","protected":false},"excerpt":{"rendered":"<p>External interrupts are a must have feature in any microcontroller. Interrupts solve a lot of problem that would have otherwise been dependent on polling methods. For instance when we press the volume up key of a TV tuner\u2019s remote controller, the remote controller quickly responds by transmitting the volume up command to the TV set and in turn the TV\u2019s volume increases. This fast response is due to external interrupt issued by the remote\u2019s button to the microcontroller it is connected to. If, however, all the keys of the remote were regularly and frequently scanned and then responded up on<\/p>\n","protected":false},"author":5,"featured_media":10013,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1466,792],"tags":[644,807,800,11,14,312],"class_list":["post-10012","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","category-xmega","tag-atmel","tag-atxmega","tag-atxmega32a4u","tag-avr","tag-interrupts","tag-mikroc-for-avr"],"_links":{"self":[{"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/posts\/10012","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/comments?post=10012"}],"version-history":[{"count":9,"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/posts\/10012\/revisions"}],"predecessor-version":[{"id":12861,"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/posts\/10012\/revisions\/12861"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/media\/10013"}],"wp:attachment":[{"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/media?parent=10012"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/categories?post=10012"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/tags?post=10012"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}