Newsgroup: it.hobby.elettronica.digitale
Titolo: Gestire interrupt in C

Ciao a tutti.
Devo imparare a programmare il MSP430 della TI ma ho problemi a capire 
come fare per gestire gli interrupt.
So che un interrupt è un evento che interrompe il normale flusso di 
funzionamento del programma caricato sul microcontrollore, ma non riesco 
a capire come fare in C a far capire al micro che all'arrivo 
dell'interrupt per esempio dovuto ad un overflow del conteggio di un 
timer interno, lui deve far partire un ISR che faccia una certa cosa.
Vi faccio un esempio: voglio fare in modo che ogni 5 minuti un micro 
acquisisca la temperatura da una sonda e tramite questa imposti il duty 
cicle di un segnale PWM.
1) Blocco il watchdog timer, abilito l'interrupt di overflow sul timer 
ed entro in low power mode;
2) Appena il contatore del timer va in overflow, una certa flag di 
interrupt passa da 0 a 1 e a questo punto dovrebbe venire chiamata la 
routine di interrupt durante la quale il micro campiona la temperatura, 
la converte in digitale, con essa calcola il duty cicle opportuno, lo 
imposta e va in low power mode;
3) Aspetta in low power mode altri 5 minuti prima di ripetere il tutto.
Io ho scritto il codice per fargli calcolare il duty cycle tramite la 
temperatura acquisita e per farglielo settare ma non capisco come faccia 
il programma principale a passare dal punto 1) al 2), poi dal 2) al 3) e 
dal 3) di nuovo al 2) e così via.
Ho sempre sotto mano la user guide del MSP430 ma proprio non mi entra in 
testa!!!
Spero di non aver fatto troppa confusione, di non aver scritto troppe 
castronerie ma soprattutto che qualcuno mi aiuti, per favore!!!
Grazie mille!
-- 
---------------------
Ciao,
   Dave Evans
---------------------

 
io personalmente adotterei una struttura del genere:
// codice C
volatile char int_flag;
void isr(void) interrupt	// questa sintassi va controllata
{
	int_flag=1;
}
main() {
	int_flag=0;
	setup_timer();
	enableinterrupt();
	while(1) {
// qui si sospende in attesa di un interrupt
		sleep();	
// al risveglio controlla se interrupt del timer
// e fa quello che deve fare ( anche con calma )
		if (int_flag) {
			do_something();
			int_flag=0;
		}
	}
}
// fine codice C
da notare:
1) l'uso della keyword volatile nel flag globale
2) la routine d'interrupt e' brevissima concentrando l'elaborazione solo 
nel loop principale
3) lo sleep() e' in realta' opzionale serve solo se si vuole far 
funzionare il micro in modalita' low power
ovviamente ho usato pseudo-funzioni da adattare allo specifico hardware


mmm ha scritto:
[CUT]
Ciao, tu sei stato chiarissimo, il problema è che sono io che sono 
ignorante :-P
Ho trovato questo esempio (mi scuso per la lungaggine e per l'inglese):
-----------------------------------------------------------------------
The MSP430 C Compiler lets you write interrupt handlers
directly in C using the interrupt keyword. The interrupt we will
handle is the timer interrupt. This program sets up the timer to
interrupt once a second and outputs a succession of digits to the LCD.
The following is a listing of the interrupt code. The code is provided 
in the sample tutorials as tutor3.c.
/* This example demonstrates how to use the basic timer
Interrupt frequency 1 Hz */
/* enable use of extended keywords */
#pragma language=extended
/* include sfr definitions for I/O registers and
intrinsic functions (_EINT) */
#include "io310.h"
#include "in430.h"
volatile int clock; /* count number of basic timer
interrupts */
char digit[10] = {
0xB7, /* "0" LCD segments a+b+c+d+e+f */
0x12, /* "1" */
0x8F, /* "2" */
0x1F, /* "3" */
0x3A, /* "4" */
0x3D, /* "5" */
0xBD, /* "6" */
0x13, /* "7" */
0xBF, /* "8" */
0x3F /* "9" */
};
/* Basic Timer has vector address 0xFFE2, ie offset 2 in
INTVECT */
interrupt [0x02] void basic_timer(void)
{
if (++clock == 10)
clock = 0;
/* Display 1,2,3,...,9,0,1,2,... */
LCDMEM[0] = digit[clock];
}
void main(void)
{
/* Initialize LCD driver (4Mux mode) */
LCDCTL = 0xFF;
/* Initialize Basic Timer
Interrupt FQ is ACLK/256/128 = 1 Hz */
BTCTL = 0xF6;
ME2 |= 0x80; /* Set Basic Timer Module Enable */
BTCTL &=~0x40; /* Disable Basic Timer Reset */
IE2 |= 0x80; /* Set Basic Timer Interrupt Enable */
clock = 0;
/* Enable interrupts */
_EINT();
/* wait for interrupt */
while (1);
}
interrupt [0x02] void basic_timer(void)
{
if (++clock == 10)
clock = 0;
/* Display 1,2,3,...,9,0,1,2,... */
LCDMEM[0] = digit[clock];
}
The interrupt function itself is defined by the following lines:
interrupt [0x02] void basic_timer(void)
{
if (++clock == 10)
clock = 0;
/* Display 1,2,3,...,9,0,1,2,... */
LCDMEM[0] = digit[clock];
}
---------------------------------------------------------------------
Vediamo se ho capito:
_EINT() dice alla CPU che se mentre dorme gli arriva un qualunque 
interrupt lei deve svegliarsi, giusto?
IE2 |= 0x80; dice che l'interrupt che mi aspetto sarà legato al Basic 
Timer (ma in che modo si manifesta?), ok?
while(1) fa girare a vuoto la CPU finchè non arriva l'interrupt (però 
così spreco potenza inutilmente, giusto?)
Quando arriva la richiesta di interrupt dal Basic timer, il codice che 
viene eseguito è quello dentro la funzione interrupt[0x02], giusto?
Una volta eseguita questa (supponiamo che debba far scrivere Hello 
World), come faccio a tornare al programma principale? lo fa da sola? e 
se volessi fargli scrivere Hello World ogni 5 minuti?
