ti msp430 polling interrupts isrs
Download
Skip this Video
Download Presentation
TI MSP430 Polling, Interrupts, ISRs

Loading in 2 Seconds...

play fullscreen
1 / 42

TI MSP430 Polling, Interrupts, ISRs - PowerPoint PPT Presentation


  • 130 Views
  • Uploaded on

TI MSP430 Polling, Interrupts, ISRs. Polling, Interrupts. Polling Εισαγωγή στα Interrupts Παραδείγματα. Polling vs Interrupt. Interrupt Service Routines in Assembly. PORT1_ISR: ; respond to inputs on port1 reti ; return from interrupt ORG 0FFE8 DW PORT1_ISR -- or --

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about ' TI MSP430 Polling, Interrupts, ISRs' - penney


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
ti msp430 polling interrupts isrs
TI MSP430

Polling, Interrupts, ISRs

polling interrupts
Polling, Interrupts
  • Polling
  • Εισαγωγή στα Interrupts
  • Παραδείγματα
interrupt service routines in assembly
Interrupt Service Routines in Assembly

PORT1_ISR:

; respond to inputs on port1

reti ; return from interrupt

ORG 0FFE8

DW PORT1_ISR

-- or --

COMMON INTVEC

ORG PORT1_VECTOR

DW PORT1_ISR

  • Το υποπρόγραμμα εξυπηρέτησης διακοπής είναι αρκετά απλό. (Παρατηρήστε την εντολή “reti”.)
  • Αποθηκεύει την διεύθυνση της συγκεκριμένης ISR (PORT1_ISR) στην κατάλληλη θέση του πίνακα διανυσμάτων (vector table) με την οδηγία (directive) ORG.
  • Το PORT1_VECTOR ορίζεται στο αρχείο επικεφαλίδας (header file) αναφορικά με το INTVEC segment. Η οδηγία COMMON πρέπει να χρησιμοποιηθεί ώστε η καθορισμένη διεύθυνση (PORT1_ISR) να τοποθετηθεί στην σωστή θέση. Αυτό είναι χρήσιμο ώστε να ορίζουμε ISRs σε πολλαπλά αρχεία.
interrupt service routines in c
Interrupt Service Routines in C

// tell the compiler the vector for this ISR

#pragma vector = PORT1_VECTOR

__interrupt void port1_isr(void)

{

// respond to inputs on port1

}

  • Η οδηγία “#pragma vector” πληροφορεί τον compiler για την αποθήκευση της διεύθυνσης του υποπρογράμματος στην θέση PORT1_VECTOR.
  • Η οδηγία“__interrupt” πληροφορεί τον compiler ότι αυτή η συνάρτηση πρέπει να τελειώνει με την εντολή “reti”.
  • Το όνομα της συνάρτησης port1_isr δεν έχει σημασία…
interrupt vector jump table
Interrupt Vector Jump Table
  • Ο πίνακας των διανυσμάτων πληροφορεί το πρόγραμμα για το που θα συνεχίσει όταν συμβεί ένα interrupt.
  • Ένα διάνυσμα- vector δείχνει στην διεύθυνση όπου ξεκινά το πρόγραμμα εξυπηρέτησης της διακοπής (interrupt service routine).
  • Ο πίνακας διανυσμάτων διακοπών για τον MSP430 είναι αποθηκευμένος στην μνήμη RAM από 0xFFC0 έως 0xFFFF και μπορεί να τροποποιηθεί.
msp430 status register
MSP430 Status Register
  • GIE (bit 3): Global Interrupt Enable
    • 1: Ενεργοποιεί όλες τις διακοπές (Οι διακοπές πρέπει επιπλέον να ενεργοποιηθούν η καθεμία ξεχωριστά!!!)
    • 0: Απενεργοποιεί όλες τις διακοπές (Disable all interrupts )

Σημείωση:Ο καταχωρητής κατάστασης SR σώζεται στον σωρό (stack) και καθαρίζεται (απενεργοποιούνται οι διακοπές!!!) όταν εκτελείται μια ISR.

setting and clearing the general interrupt mask
Setting and Clearing the General Interrupt Mask
  • Assembly

EINT – Enable interrupts (set GIE)

DINT – Disable interrupts (clear GIE)

  • C

asm(“ EINT”);

asm(“ DINT”);

  • C (#include intrinsics.h)

__enable_interrupt();

__disable_interrupt();

ece447 msp430 interrupt execution flow
ECE447: MSP430 Interrupt execution flow

RAM JUMP TABLE

0xFFFF

SR

PC

00F8

EE

10EE

10

0000

0xFFC0

STACK

F8

00

SP

RAM SERVICE ROUTINE

0x10EE

interrupts example toggling leds
Interrupts Example: Toggling LEDs

// Listing 6.5: Toggles LEDs in ISR using interrupts from timer A CCR0

// in Up mode with a period of about 0.5s

#define LED1 BIT3

#define LED2 BIT4

void main (void)

{

WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

P2OUT = ~LED1; // Preload LED1 on, LED2 off

P2DIR = LED1 | LED2; // Set pins with LED1,2 to output

TACCR0 = 49999; // Upper limit of count for TAR

TACCTL0 = CCIE; // Enable interrupts on Compare 0

TACTL = MC_1 | ID_3 | TASSEL_2 | TACLR; // Set up and start Timer A

// “Up to CCR0” mode, divide clock 8, clock SMCLK, clear timer

__enable_interrupt ( ); // Enable interrupts (intrinsic)

for (;;) { // Loop forever doing nothing

} // Interrupts do the work

}

// Interrupt Service Routine for Timer A channel 0

#pragma vector = TIMERA0_VECTOR // Assoc. the funct. w/ an interrupt vector

__interrupt void TA0_ISR (void) // name of the interrupt function (can be anything)

{

P2OUT ^= LED1 | LED2; // Toggle LEDs

}

msp430 interrupt exercise
MSP430 Interrupt Exercise

Write a program that collects samples from input Port 2. A signal line that indicates a new data value is available is connected to pin P1.0. Use an interrupt to detect a rising edge on the P1.0. When an interrupt is triggered the value on Port2 should be stored into a byte array of 32 entries. When 32 samples have been collected, P1.7 should be driven as an output high to indicate the memory is “full”

slide30

BITFIELDS

Time Based Processing on an MSP430 Launchpad

I recently saw a video on MyBitBox on using bitfields in time based processes and thought it was and excellent example of a fairly advanced topic in embedded systems.  In that blog, an mBed is used, which is an ARM based dev kit.  I thought it would be useful to port this example to the MSP430 Launchpad.  In this example, I’m using the MSP430G2231, but any MSP430 with Timer_A can be used.

This example is used to show that microcontrollers can be setup to run several tasks at multiple intervals.  The desired result is a system that executes these commands deterministically, meaning that at the desired time interval a routine WILL execute.  this is useful when a microcontroller needs to multitask or divide a workload.

For this example, we’re going to setup a routine to run every second and another routine to run every 100ms. There are two LEDs on the Launchpad, so for this example we’ll toggle one LED at 100ms and the other at 1 second. The first thing to do is define a struct with a bitfield to set flags whenever a time interval is reached.

http://busted240sx.wordpress.com/2011/11/27/time-based-processing-on-an-msp430-launchpad/

slide31

typedef struct time_flags{ unsigned time_1ms :1; unsigned time_100ms :1; unsigned time_1s :1;}time_flags;extern volatile struct time_flags sys_time;

These flags will be set by an interrupt service routine that executes every millisecond. This ISR increments several counters. counter_base increments every millisecond until it reaches 100 and is reset. counter_100ms increments every 100ms until it reaches 10 (1 second), then it is reset. whenever we reach these desired increments we set the flags of the structs we created earlier. This method can be extended as much as desired so you could have an hour counter or day counter if you wanted.

slide32

#pragma vector=TIMERA0_VECTOR__interrupt void Timer_ISR(void){ sys_time.time_1ms = TRUE; counter_base++; if(counter_base>=100) { counter_base=0; sys_time.time_100ms = TRUE; counter_100ms++; //this is for 1sec if(counter_100ms>=10) { counter_100ms=0; //counter_1s++; sys_time.time_1s = TRUE; } } return;}

slide33

In a separate file we’ll setup our main functions and the routines we wish to call.

After turning off the Watchdog timer, we setup Timer A which we’ll use to trigger

the interrupt. We set Timer A to Up mode, which will generate an interrupt when

the timer reaches the value of CCR0 and then reset the timer. By default, the

SMCLK is setup for 1MHz, so I didn’t have to divide the clock down or change

the source. If you want to use a different clock, go right ahead but be aware

that the value of CCR0 will have to be changed.

the while(1) starts an infinite loop that the microcontroller will

never break from. This is known as the “idle loop”. The ISR

will handle all the counting and setting of the flags and most of the time,

the MSP will just loop through this and check the flags status. If the flag is set, a routine is called and the flag is cleared.

slide34

void main(void){ WDTCTL = WDTPW + WDTHOLD; //stop watchdog TACTL = TASSEL_2 + MC_1 + TAIE; //Timer A, SMCLK, up mode, enable interrupts P1DIR |= BIT0 + BIT6; CCTL0 = CCIE; //CCR0 Interrupt enable CCR0 = 1000-1; //SMCLK/CCR0 = 1MHz/1000 = 1kHz _BIS_SR(GIE); //enable global interrupts while(1) //idle loop { if(sys_time.time_1ms == TRUE) { //main_1ms_routine , if needed sys_time.time_1ms = FALSE; } if(sys_time.time_100ms == TRUE) { main_100ms_routine(); sys_time.time_100ms = FALSE; } if(sys_time.time_1s == TRUE) { main_1s_routine(); sys_time.time_1s = FALSE; } } }

slide35

Finally, we define the routines we want to run. Here, we’re just blinking LEDs, but it could be anything. On the Launchpad, the Green LED is on Port 1 Pin 6, so I set Bit 6 to toggle with an XOR every second. The same is done with the red LED on Port 1 Pin 0 every 100ms.

void main_1s_routine (void){ //toggle Green LED P1OUT ^= BIT6;}void main_100ms_routine (void){ //toggle Red LED P1OUT ^= BIT0;}

slide36

Thats it! We’ve setup a timer to trigger an interrupt every millisecond,

defined the flags and counters, incremented the counters and set the flags

in the ISR, and created routines to run based on the flags that are set. Now,

we Build the code and watch it run!

You can download the full source code here.

Thanks. Big thanks to myBitBox for enlightening me to this method.

slide38

MSP430 Launchpad - Low Power Thermometer Code

TI has a really low cost development platform called launchpad

that I have been playing with recently.  It is $4.30 with free shipping

until august and it has some crazy low power capabilities.  Below

is my first program beyond a blinky.  It sleeps in the second to

lowest power mode then wakes up, reads the temperature, counts

it out on 2 LEDs on the dev board then goes back to sleep.  Other

than driving the LEDs, this should use so little power that batteries

could conceivably die from age as fast as they are used if I cranked

the sleep all the way up.  It also has the advantage of working on

a launchpad in factory condition with no additional parts..

http://bill-landers.blogspot.com/2010/08/msp430-launchpad-low-power-thermometer.html

slide39

// the goal was to sleep as long as possible, read temp// then display it through flashing the launchpad leds//// when not flashing or measuring go to the lowest power reasonable//#include  "msp430x20x2.h"//unsigned short cc = 65470;    //longest CCR0//unsigned short cc = 1000;       //debugging CCR0 valueunsigned short cc = 10000;       //interval between tests - CCR0 valuelong IntDegF;//this is all setupvoid main(void){  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT  BCSCTL3 |= LFXT1S_2;                      // make clock work without crystal  P1DIR |= 65;                              // P1.0 & 6 output  P1OUT = 65;                               // lights on so we know we are started  CCTL0 = CCIE;                             // CCR0 interrupt enabled  CCR0 = cc;                                // set the long interval  TACTL = TASSEL_1 + MC_1 + ID_3 ;          // SMCLK, upmode, / 8  _BIS_SR(LPM3_bits + GIE);                 // Enter LPM3 w/ interrupt}

slide40

//this captures the temp valuevoid dotemp(void){  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT  ADC10CTL1 = INCH_10 + ADC10DIV_3;         // Temp Sensor ADC10CLK/4  ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON + ADC10IE;  ADC10CTL0 |= ENC + ADC10SC;             // Sampling and conversion start  __bis_SR_register(CPUOFF + GIE);        // LPM0 with interrupts enabled  // oF = ((A10/1024)*1500mV)-923mV)*1/1.97mV = A10*761/1024 - 468  long temp = ADC10MEM;                         // raw adc temp  IntDegF = ((temp - 630) * 761) / 1024;  CCR0 = 999;                             // set short interval for display}

slide41

// ADC10 interrupt service routine - #pragma vector=ADC10_VECTOR__interrupt void ADC10_ISR (void){  __bic_SR_register_on_exit(CPUOFF);        // Clear CPUOFF bit from 0(SR)}

slide42

/ Timer A0 interrupt service routine - this is the main flow control#pragma vector=TIMERA0_VECTOR__interrupt void Timer_A (void){  if (CCR0<1000)            //if we are on the short interval we are blinking    if (P1OUT > 0)          //if the leds are on turn them off    {      P1OUT = 0;      CCR0 = 600;    }    else                    //time to count down      if (IntDegF == 0)     //if we have counted to zero back to the long count        CCR0 = cc;      else      {        CCR0 = 100;        if (IntDegF > 9)    //if there are more than 10 left use the first led        {          P1OUT = 1;        //first led onIntDegF -= 10;    //decrement 10        }        else        {          P1OUT = 64;       //less than ten, second ledIntDegF -= 1;     //decrement one        }      }  elsedotemp();               //do the temp measure}

ad