You are on page 1of 50

Tutorial MSP430 Prender un Led

Bienvenido a mi casa. Venga libremente, vyase a salvo, y deje algo de la alegra que trae
consigo
Dracula, de Bram Stoker
Vamos a trabajar con el microcontrolador MSP430F2011, debido a que tiene slo 14 pines, de los
cuales podemos utilizar 10 pines como I/O, 2KB de memoria de programa (Flash Memory) y 12MB
de memoria de datos (RAM). Naturalmente si en algn momento nos queda chico este micro
migraremos a otro con mayor recursos.

En esta direccion de la empresa Texas Instruments se encuentran dos archivos que necesitamos
tener a nuestro lado como material de consulta absoluto:
1. Datasheet del MSP430F2011
2. Guia de Usuario de la Familia MSP430X2XX
Como podemos ver en la imagen, vamos a realizar un cdigo que active un nivel high en el pin 2
del MSP430F2011.

El cdigo que realizar esta tarea se muestra a continuacin:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

#include "io430.h"//libreria del propio IDE


//#define LED1 P1OUT_bit.P1OUT_0//definicion del pin LED
#define LED1 P1OUT_bit.P0//definicion del pin LED
int main( void ) //funcion principal
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
//CAPD = 0x00;//Habilitamos el output driver de todos los pines del
puerto 1.
P1SEL = 0x00;//Seteamos la funcion de I/O en todos los pines del
puerto 1.
P1DIR = 0xFF;//Seteamos todos los pines del puerto 1 como salida.
LED1 = 1;//nivel high en el pin LED
while(1);//bucle infinito
}

Como pueden notar se trata de un lenguaje C que respeta el formato del ANSI C, practicamente no
hemos tocado an varios aspectos como el oscilador, modo de arranques, etc. Estos temas los
iremos vislumbrando conforme avance el curso.
Pero por ahora toca entender que significan estos 3 registros: CAPD, P1SEL, P1DIR, y que
significa el label LED1.

CAPD, P1SEL, P1DIR se necesitan configurar de la siguiente manera para poder utilizar el pin 2
que corresponde con el P1.0, como output:

Observen que para que el pin P1.0 se comporte como un pin de salida (o de entrada) necesita que
el bit 0 del registro P1DIR sea cero, debido a que ese registro define el comportamiento de entrada
o salida del pin, donde un 1 significa salida y un 0 es entrada (contrario a como trabajan los
PICs por ejemplo).

As mismo el bit 0 de P1SEL tiene que ser cero, pues esto le indica al pin que se comporte como
un pin I/O, otro valor configurara al pin para que trabaje con algun perifrico que tiene
multiplexado. En otro proyecto usaremos esta configuracin.

Y el bit 0 del registro CAPD tambin tiene que ser seteado a cero, para que habilite los buffers de
entrada/salida del pin. Este registro tiene mayor relevancia cuando se usa el pin P1.0 en el modo
comparador.

Despus de todo esto ya tenemos el pin P1.0 configurado como salida (en el cdigo lo hemos
aplicado a todos los pines del puerto 1), entonces creamos el label LED1 que referencia al bit 0 del
registro P1OUT (quien controla los pines de salida del puerto 1).
#define LED1 P1OUT_bit.P1OUT_0, donde:
P1OUT_bit = registro P1OUT
P1OUT_0 = bit 0 del registro P1OUT

Finalmente un video para que la visita sea ms didctica:

Tutorial MSP430 Prender y Apagar un Led


Bienvenido a mi casa. Venga libremente, vyase a salvo, y deje algo de la alegra que trae
consigo
Dracula, de Bram Stoker
En esta nueva entrada vamos a estudiar un programa en el cual haremos prender y apagar
(parpadear) un led con un determinado retardo. El programa aparenta ser simple y sencillo, sin
embargo la pondremos dificil porque hasta ahora no sabemos a que frecuencia estamos trabajando
con el MSP430F2011, es ms, ni siquiera sabemos si estamos usando un oscilador externo o
interno, no hemos mencionado nada del sistema oscilador del microcontrolador en cuestin.
No es cuestin de poner un delay y ver como parpadea, se trata de entender como trabaja todo el
sistema, al inicio puede parecer complejo explorar como funciona la oscilacion del MSP430F2011,
pero veremos que ordenando la informacin y con algunos grficos, todo se vuelve fcil de
comprender.
El Basic Clock System

La frecuencia de oscilacin del MSP430F2011 (y de todos los MSP430xxx) depende de lo que se


conoce como el Basic Clock System, el cual si miran en el grfico siguiente, se puede observar que
est constituido por 5 elementos globales:

1. Clock Sources
2. Clock Signals
3. Modos de Operacion
4. Registros para configurar Clock Sources y Clock Signals
5. Registros para configurar el Modo de Operacion
Parece mucha informacin, lo s!, pero ya dice el sabio refrn: divide y vencers, por eso anticipo
que en esta entrada no exploraremos los puntos 3 y 5, simplemente lo dejaremos con su
configuracin por defecto que es Active Mode (AM), es decir no tocaremos sus registros de
configuracin. La aplicacin o utilidad de los puntos 3 y 5 se ve reflejado en el tema de ahorro de
consumo de energa, las diferentes configuraciones de low power mode permiten tener varios
consumos en el orden de micro amperios, segn sea la necesidad de la aplicacin.
Clock Sources y Clock Signals

Y Odin creo primero los clock sources y despus aparecieron los clock signals. Igual tenemos que
hacer nosotros, primero debemos configurar los clock sources y despus aparecieron los clock
signals. Porque? Por el siguiente grfico, una imagen habla ms que 1000 palabras:

El grfico fue extraido del family users guide que les suger descargar en el primer post del tutorial,
el esquema representa los bloques de trabajo del Basic Clock System para el MSP430F2xxx,
observen adems que he colocado unos apuntes de no est implementado para que sepan que
etapas no estn implementadas en el MSP430F2011. Adems podrn apreciar de izquierda a
derecha que los Clock Sources (VLOCLK, LFXT1CLK, DCOCLK) se concentran en un punto para

dar lugar a los Clock Signals (ACLK, MCLK, SMCLK). Tenemos que seleccionar de que fuente
(VLOCLK, LFXT1CLK, DCOCLK) provienen las seales de oscilacin del sistema (ACLK, MCLK,
SMCLK).
Clock Sources
Entonces, los entendemos como la fuente de oscilacin para las seales de reloj (Clock Signals)
del sistema, y tenemos que seleccionar slo una de ellas, pero podemos cambiar entre una y otra
en el tiempo de ejecucin del programa del microcontrolador:
LFXT1CLK: Low-frequency/high-frequency oscillator that can be used with low-frequency watch
crystals or external clock sources of 32768 Hz or with standard crystals, resonators, or external
clock sources in the 400-kHz to 16-MHz range. En el caso del MSP430F2011 el LFXT1CLK solo
soporta bajas frecuencias en el rango de 10KHz hasta 50KHz.
DCOCLK: Internal digitally controlled oscillator (DCO). Es un oscilador interno con un gran rango
de configuracin de trabajo de hasta 16MHz.
VLOCLK: Internal very low power, low frequency oscillator with 12kHz typical frequency. Es un
oscilador interno de solo 12KHz, utilizado para bajo consumo del sistema.
En esta entrada vamos a trabajar con el oscilador interno DCOCLK, por ello los dems clock
sources no sern analizados por el momento, ya tendrn su respectivo post.
DCOCLK: Internal digitally controlled oscillator (DCO)
Este oscilador interno es muy verstil, tiene un gran rango de trabajo que va desde 0.06MHz hasta
16MHz, en distintos niveles o pasos. El siguiente grfico lo explicar todo:

El grfico de arriba nos muestra en el eje horizontal los 8 (del 0 al 7) valores para el grupo de bits
DCO (son 3 bits) que se encuentran en el registro DCOCTL, y en el eje vertical los valores (en
realidad son 16 valores, del 0 al 15) del grupo de bits RSEL que se encuentran en el registro
BCSCTL1. Fijense el escalon que tiene por ejemplo RSEL = 0 para cada valor de DCO, a la
izquierda en el eje vertical podemos apreciar la frecuencia aproximada que conseguimos en
alguna de las configuraciones.

A esto me refera cuando les deca que tenemos un oscilador muy verstil para trabajar, ahora la
pregunta es y cmo saber la frecuencia aproximada que estaremos configurando al utlizalos los
bits DOC y RESL? Existen 2 caminos, utilizar los valores por defecto que ofrece el datasheet del
MSP430F2011 o averiguar por tu cuenta un valor de frecuencia experimental con que desees
trabajar.
En la siguiente tabla extrada del datasheet del MSP430F2011 estn los valores que debemos
cargar alos registros BCSCTL1 (CALBC1_xMHZ) y DCOCTL (CALDCO_xMHZ) para obtener las
correspondientes frecuencias:

Como mencion antes, existen otros valores de frecuencia para el DCO que no estn en esta tabla,
sin embargo no son tema de esta entrada, tendrn su propio post y aplicacin didctica. Para este
proyecto utilizaremos la configuracion de 1MHz.

Clock Signals
Son 3 salidas para el source que seleccionemos, donde cada clock signal tiene su propia
configuracin y aplicacin:
ACLK: Auxiliary clock (ACLK), sourced either from a 32768-Hz watch crystal or the internal LF
oscillator. Puede ser utilizado con los clock source: LFXT1CLK, VLOCLK. El source para esta seal
dependera de la configuracion de los bits LFXT1S (2 bits) del registro BCSCTL3 y del bit XTS (1
bit) del registro BCSCTL1.
MCLK: Main clock (MCLK), the system clock used by the CPU. Puede utilizar todos los source
disponibles. Por defecto despues de un reset del chip siempre selecciona iniciar con el source
DCOCLK. Por cdigo podemos cambiarlo a otro source si lo requerimos y se realiza esto con los
bits SELM (2 bits) que estn en el registro BCSCTL2. As mismo tiene un divisor de frecuencias en
los bits del DIVM (2 bits) tambin en el registro BCSCTL2.
SMCLK:Sub-Main clock (SMCLK), the sub-system clock used by the peripheral modules. Puede
utilizar todos los source disponibles. Para seleccionar el source se utiliza los bits SELS (2 bits) que
estn en el registro BCSCTL2 y un divisor de frecuencias en los bits del DIVS (2 bits) en el mismo
registro.

En este programa utlizaremos el DCO a 1MHz junto con el MCLK con divisor valor 1, as que hay
muy poco que manipular.
Programa de aplicacion

1
2
3
4
5
6
7
8
9
10

#include "io430.h"//libreria del propio IDE


#include "intrinsics.h"
//#define LED1 P1OUT_bit.P1OUT_0//definicion del pin LED
#define LED1 P1OUT_bit.P0//definicion del pin LED
int main( void ) //funcion principal
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
BCSCTL1 = CALBC1_8MHZ;// Use 1Mhz cal data for DCO

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

DCOCTL = CALDCO_8MHZ;// Use 1Mhz cal data for DCO


CAPD = 0x00;//Habilitamos el output driver de todos los pines del
puerto 1.
P1SEL = 0x00;//Seteamos la funcion de I/O en todos los pines del
puerto 1.
P1DIR = 0xFF;//Seteamos todos los pines del puerto 1 como salida.
LED1 = 0;//nivel low en el pin LED
while(1)//bucle infinito
{
LED1 = 1;
__delay_cycles(160000);//500 milisegundos
LED1 = 0;
__delay_cycles(160000);//500 milisegundos
}
}

Video
Todos los archivos los pueden encontrar en: 4shared, boxnet.
Estos nuevos enlaces estan compilador con la versin del software IAR 5.40 :

Tutorial MSP430 Barra de Leds Maskable Interrupts for


Input Port
Bienvenido a mi casa. Venga libremente, vyase a salvo, y deje algo de la alegra que trae
consigo
Dracula, de Bram Stoker
Vamos a realizar un proyecto en el cual con un boton (normalmente en bajo nivel) iremos
desplazando la activacin de un led en la salida de un 74xx138 segn un contador interno en el
MSP430. En este sencillo ejemplo aprenderemos a utilizar los pines del MSP430 como entradas
lgicas y tambin a configurar sus respectivas interrupciones de cambio de estado por flanco de
entrada.

Interrupciones en el MSP430
As como en otros microcontroladores, el MSP430 tambin viene provisto de interrupciones por
hardware que permiten realizar diversas aplicaciones segn la caraterstica de la interrupcin que
utilizemos. Podemos usar las interrupciones por ejemplo para los siguientes casos:
Tareas urgentes que deben ser atendidas inmediatamente y con mayor prioridad que el cdigo
principal.
Tareas de poca frecuencia, como el manejo de pulsadores en un humano. Esto nos libera de
realizar un cdigo con polling (bucle para evaluar constantemente en el orden de microsegundos
una entrada lgica).
Despertar el CPU del modo Sleep. Esto es muy importante en el MSP430, ya que por lo general
se lo utiliza la mayor parte del tiempo en modo de bajo consumo (low-power mode) y puede volver
al modo activo (AM mode) con una interrupcin.
Tipos de Interrupciones
En el MSP430 tenemos 3 tipos de interrupciones, stas son:

Si revisamos el datasheet del MSP430F2011, en la pagina 13, est plasmada una tabla con todas
las interrupciones que soporta el microcontrolador (en realidad ese datasheet es para las series
MSP430F20x3/2/1):

Debemos observar en esta tabla que existen 32 posiciones de memoria (0-lowest 31-highest) o
tambin llamados vectores reservados para almacenar la direccin de los ISR correspondientes a
la interrupcin que los define (tambin conocidos como los interrupt handler). Como pueden
apreciar en dicha tabla estn plasmados los 3 tipos de interrupciones del MSP430F2011,
separados por tipo y en orden descendente, donde dicho orden indica as mismo el rango de
prioridad de las interrupciones, es decir la interrupcion con prioridad 31 en la posicion de memoria
0xFFFEh correspondiente con el System Reset tiene la prioridad ms alta de toda la tabla.
Y cmo sabemos cuales son las interrupciones que maneja exactamente el MSP430F2011? Pues
basta darle un vistazo al archivo io430x20x1.h que est en los programas que hacemos con el
IAR cuando seleccionamos el MSP430F2011, y buscan lo siguiente:

Para escribir el interrupt handler de la interrupcin que queremos gestionar, necesitamos saber el
nombre del vector de la interrupcin que tiene en el microcontrolador que estamos programando
(siempre y cuando sea desde el IAR), para eso sirven esos #defines.
En esta entrada slo abarcaremos el estudio de las interrupciones enmascarables (MASKABLE
INTERRUPTS) , para los dems tipos prepararemos otras entradas ya que tienen su propio campo
de aplicacin.
Maskable Interrupts for Input Port
Las interrupciones enmascarables (MASKABLE INTERRUPTS) tienen la propiedad de activarse
individualmente y tambin como en una capa superior se pueden activar colectivamente. Esto es,
despues de configurar el pin de entrada P2.7 para que genere una interrupcion en cada flanco de
subida, debemos utilizar la funcin intrinseca: __enable_interrupt, la cual setea a nivel global la
activacin de todas las interrupciones enmascarables del MSP430. Sino la utlizamos ninguna de
las interrupciones enmascarables previamente y correctamente configuradas funcionarn. Siempre
se pone la linea __enable_interrupt al final de la configuracin de todas las interrupciones
enmascarables. Para tener la funcin __enable_interrupt disponible necesitamos colocar en la
cabecera la inclusin: #include intrinsics.h.
Luego requerimos escribir el interupt handler o ISR, que es el lugar donde haremos el tratamiento
de la interrupcin. En C para el IAR, existe un formato para escribir el interrupt handler o ISR de
la interrupcin que queremos utilizar. El formato es el siguiente:

A continuacin explicaremos los campos resaltados:


#pragma vector: esta directiva es usada para especificar la direccin del vector de interrupcin
que se escriba en el campo <VECTOR_NAME>.
<VECTOR_NAME>: aqu escribimos el nombre del vector de la interrupcin que deseamos utilizar,
el nombre lo obtenemos del archivo cabecera del micro que usemos, por ejemplo en esta entrada
usaremos una interrupcin en el pin P2.7, por lo tanto el vector name ser PORT2_VECTOR.

__interrupt: es usado para indicar al compilador que haga la llamada convencional que necesita
una funcin de tipo interrupcin.
<ISR_NAME>: es simplemente el nombre del interrupt handler, es decir puede ser cualquier
nombre que prefiera el programador. En nuestro caso le he puesto de ISR_NAME el literal
InterrupcionPuerto2.
Dentro del interrupt handler escribimos el cdigo que gestionar las acciones conjunto que
realizar la interrupcin del hardware especificado. Finalmente NUNCA olvidar de borrar el flag de
la interrupcin invocada.
Interrupcion de Cambio de Estado en el Pin de Entrada P2.7
Para configurar la interrupcion en el pin P2.7 necesitamos manipular los siguientes registros:

De la imagen entendemos que debemos configurar el bit 7 del registro P2DIR con valor 0 para
indicar entrada, luego el bit 7 del registro P2SEL con valor 0 para indicar funcion de I/O
(entrada/salida).

Tambin debemos utlizar el bit 7 del registro P2REN, para especificar si el pin P2.7 tendr una
resistencia de pullup (3.3V con el pin al aire) o pulldown (0V con el pin al aire) conectada a su
entrada. Esto por lo general se utiliza con pulsadores normalmente abiertos o cerrados.

As mismo hacemos con el bit 7 del registro P2IES, que permite especificar el flanco de disparo de
la interrupcin en el pin P2.7. Podemos seleccionar entre una transicin de bajada a subida o
viceversa. En nuestro caso tenemos una seal normalmente en bajo nivel, por ello elegimos la
transicin de bajada a subida.

A continuacin habilitamos la interrupcin del pin P2.7 escribiendo un 1 en el bit 7 del registro P2IE.

Luego borramos el flag de interrupcion en el bit 7 del registro P2IFG para evitar sorpresas
inesperadas. Recordar borrar este flag antes de salir del interrupt hanlder o ISR.

Finalmente agregaremos la linea de comando __enable_interrupt(); para activar de forma global


todas las interrupciones enmascarables previamente configuradas, como s el caso del pin P2.7.
Programa de Aplicacin:
#include "io430.h"//libreria del propio IDE
1
#include "intrinsics.h"

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

#define OUT_A P1OUT_bit.P1OUT_1//definicion del pin LED


#define OUT_B P1OUT_bit.P1OUT_2//definicion del pin LED
#define OUT_C P1OUT_bit.P1OUT_3//definicion del pin LED
unsigned char aux;
int main( void ) //funcion principal
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
BCSCTL1 = CALBC1_1MHZ;// Use 1Mhz cal data for DCO
DCOCTL = CALDCO_1MHZ;// Use 1Mhz cal data for DCO
CAPD = 0x00;//Habilitamos el output driver de todos los pines del
puerto 1.
P1SEL = 0x00;//Seteamos la funcion de I/O en todos los pines del
puerto 1.
P1DIR = 0xFF;//Seteamos todos los pines del puerto 1 como salida.
P1OUT = 0x00;
P1DIR_bit.P1DIR_7 = 0;//pin de entrada
//Configuramos pin P2.6 y P2.7 como entradas logicas.
P2DIR_bit.P2DIR_6 = 0;//logic input
P2SEL_bit.P2SEL_6 = 0;//input/output function
P2DIR_bit.P2DIR_7 = 0;//logic input

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

P2SEL_bit.P2SEL_7 = 0;//input/output function


//Primera capa de
//Configuramos la
P2REN_bit.P2REN_7
P2IES_bit.P2IES_7
P2IE_bit.P2IE_7 =
P2IFG_bit.P2IFG_7
P2.7

activacion de interrupcion
interrupcin en el pin P2.7
= 0;//deshabilitamos la resistencia pullup/pulldown.
= 0;//interrupcion en pulso de subida (low to high).
1;//habilitamos la interrupcion del pin P2.7
= 0;//limpiamos la bandera de interrupcion del pin

//Segunda capa de activacion de interrupcion


__enable_interrupt();
aux = 7;
while(1)//bucle infinito
{

#pragma vector = PORT2_VECTOR


__interrupt void InterrupcionPuerto2(void){
OUT_A = 0;
OUT_B = 0;
OUT_C = 0;
if((aux
OUT_A
}
if((aux
OUT_B
}
if((aux
OUT_C
}

& 0x01) == 0x01){


= 1;
& 0x02) == 0x02){
= 1;
& 0x04) == 0x04){
= 1;

if(aux >= 7){


aux = 0;
}else{
aux++;
}
P2IFG_bit.P2IFG_7 = 0;//Borro el flag de interrupcion.
}

Timer
En esta nueva entrada estudiaremos el comportamiento, configuraciones, y registros que
constituyen el Timer Block del Timer_A que posee el microcontrolador MSP430F2132. En efecto
hemos dejado atrs el MSP430F2011 y hemos cambiado al MSP430F2132 debido a su mayor
cantidad de memoria y pines. Vern que no ser nada complicado navegar por este nuevo micro.
Adems implementaremos en el proteus una aplicacin para probar todas las configuraciones del
Timer Block.

Timer_A
Es en esencia un timer/counter de 16 bits, con registros de control y captura/comparacin que en
conjunto proporcionan muchas configuraciones que servirn para alcanzar los objetivos de nuestra
aplicacin. Est constituido por dos partes principales:
Timer Block (gobernado por un solo registro).
Canales de Captura/Comparacin (conformado por varios registros).

Debemos mencionar que en los MSP430 pueden haber ms de un modulo Timer_A, por ello para
diferenciarlos se suelen enunciar colocando el ndice del mdulo despus de la palabra Timer y al
final la cantidad de canales que tiene implementado en dicho micro. Por ejemplo en el
MSP430F2132 tenemos dos modulo de Timer_A:
Timer0_A3: mdulo Timer_A con ndice 0 y con 3 canales Capture/Compare
(TA0CCR0,TA0CCR1,TA0CCR2).
Timer1_A2: mdulo Timer_A con ndice 1 y con 2 canales Capture/Compare
(TA1CCR0,TA1CCR1).
Ambos mdulos al ser Timer_A funcionan de la misma manera, por ello en los ejemplos
trabajaremos solamente con el Timer0_A3, migrar los ejemplos al otro timer ser cosa de modificar
tan slo el ndice en el nombre de los registros.

Veamos a continuacin todos los registros del Timer0_A3 (sombreados en amarillo los registros
asociados del Timer Block del Timer0_A3):

En esta entrada nos enfocaremos en el estudio del Timer Block del Timer0_A3, la otra parte
principal la dejaremos para la segunda parte del estudio del Timer_A.
Timer Block del Timer0_A3
El Timer Block del Timer0_A3 est gobernado por un registro de control llamado TA0CTL el cual se
apoya en un registro timer/counter de 16 bits llamado TA0R cuyo comportamiento se puede
configurar. Se puede seleccionar la fuente del reloj y un prescaler. El Timer Block no tiene salida
directa por algun pin sin embargo genera interrupcin con la bandera TAIFG cuando su contador
TA0R regresa a cero siempre que se habilite su interrupcin con el bit TAIE. As mismo existe un
modo de operacin donde se genera interrupcion cuando el valor del registro contador TA0R sea
igual al valor escrito en el registro TA0CCR0.

Si analizamos el diagrama de bloques del Timer Block empezando por la izquierda, tenemos los
clock source de donde se selecciona uno mediante los bits TASSEL (bits 9-8 del registro TA0CTL):
TACLK (0) : seal de reloj proveniente de un pin externo, en el MSP430F2132 se ubica en el pin
P1.0.
ACLK (1) : seal de reloj previamente configurada del Basic Clock System en el MSP430F2132.
SMCLK (2) : seal de reloj previamente configurada del Basic Clock System en el MSP430F2132.
INCLK (3) : seal de reloj proveniente del pin P2.1 (TAINCLK) que permite incrementar con flanco
de bajada al registro TA0R, para los dems clock source siempre se incrementar con flanco de
subida.
A continuacin nos encontramos con el bloque Input Divider o Divisor de Entrada, cuyos
valores /1,/2,/4,/8se seleccionan mediante los bits ID (bits 7-6 del registro TA0CTL), el cual dividir
la frecuencia que nos proporcione el bloque clock source entre el valor seleccionado.
Luego aparece el registro timer de 16 bits llamado TAR. En el MSP430F2132 este registro se
llamaTA0R.
Despus nos encontramos con el bloque que configura el comportamiento del registro TA0R, nos
referimos a los bits MC (bits 5-4 del registro TA0CTL) y sus opciones son las siguientes:
Stop Mode (0) : se detiene el movimiento del timer TA0R.
Up Mode (1) : el timer TA0R se incrementa hasta alcanzar el valor en el registro TA0CCR0 y luego
se reinicia desde cero.
Continuous Mode (2) : el timer TA0R se incrementa hasta ser igual a 0xFFFF y luego se reinicia
desde cero.
Up/Down Mode (3) : el timer TA0R se incrementa hasta alcanzar el valor en el registro TA0CCR0 y
luego se decrementa hasta el valor 00000.
Finalmente tenemos el bit TACLR (bit 2 del registro TA0CTL) el cual resetea el valor del divisor de
reloj (ID bits) y el valor del contador TA0R.

Las seales de interrupcin del Timer Block (TAIE, TAIFG) del MSP430F2132 las describiremos a
continuacin.
Interrupcion del Timer Block en el Timer0_A3
Las interrupciones del Timer0_A3 son otro tema, pues en la tabla de vectores de todas las
interrupciones enmascarables tiene reservado dos vectores, el #24 y el #25. El vector #24
responde a 3 banderas de interrupcion: TA0CCR1 CCIFG, TA0CCR2 CCIFG y TA0CTL TAIFG. El
vector #25 solamente refiere a la bandera TA0CCR0 CCIFG.

Para esta primera parte, vamos a enfocarnos solamente en el flag TAIFG de la interrupcion
Timer0_A3 (vector 24).
Ahora nos surge una pregunta, cmo identificamos en el vector #24 a la bandera TAIFG? Sucede
que existe un registro llamado TA0IV cuyo valor permite conocer cual de las 3 interrupciones se ha
producido.
TA0IV significa: Timer0_A3 Interrupt Vector Value, y tiene la propiedad de que por ejemplo cuando
se produce la interrupcin del TAIFG (que s cuando existe un desborde del timer TA0R) se carga
en dicho registro el valor 0x0A, es decir despues de que el compilador invoque a la funcin de
interrupcion del vector #24 del Timer0_A3, debemos de consultar una vez dentro de la ISR al
registro TA0IV por su valor para determinar el tipo de interrupcin, luego de esta lectura el registro
se resetea automticamente.

Las interrupciones TAIFG por desborde del registro timer TA0R se configuran con los bits MC (bits
5-4 del registro TA0CTL) y tienen el siguiente comportamiento:
Up Mode: En este modo la interrupcion se produce cuando el valor del registro TA0R se reinicia en
cero justo despus de que su valor haya sido igual al valor del registro TA0CCR0.

Continuous Mode: En este modo la interrupcion se produce cuando el valor del registro TA0R se
reinicia en cero justo despus de que su valor haya sido igual a 0xFFFF (65535 en decimal).

Up/Down Mode: En este modo la interrupcion se produce cuando el valor del registro TA0R llega a
cero justo despus de que su valor se haya decrementado desde que el valor de TA0R es igual el
valor del registro TA0CCR0.

Finalmente dicha interrupcin con flag TAIFG (bit 0 del registro TA0CTL) se activa con el
bit TAIE (bit 1 del registro TA0CTL).
Para entender y consolidar el funcionamiento del Timer Block hemos realizado un cdigo donde
mediante 3 pulsadores se podr seleccionar las configuraciones del source clock, del input divider,
y del mode control.
Programa de Aplicacion:
#include "io430.h"
1
#include "intrinsics.h"
2
#include "bsp\bsp.h"
3
#include "lcd2x16\lcd2x16.h"

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

char
char
char
char

estadoCLK;
estadoDIV;
estadoMODO;
cambia;

int main( void )


{
unsigned char titulo[16] = " microembebidos ";
unsigned char linea1[16] = "CLK:
DIV: ";
unsigned char linea2[16] = "MODO:
";
unsigned char source0[5] = "TACLK";
unsigned char div0[2] = "/1";
unsigned char modo0[10] = "STOP MODE ";
unsigned char source1[5] = "ACLK ";
unsigned char div1[2] = "/2";
unsigned char modo1[10] = "UP MODE
unsigned char source2[5] = "SMCLK";
unsigned char div2[2] = "/4";

";

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

unsigned char modo2[10] = "CONT.MODE ";


unsigned char source3[5] = "INCLK";
unsigned char div3[2] = "/8";
unsigned char modo3[10] = "UP/DN MODE";
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
BCSCTL1 = CALBC1_1MHZ;// Use 1Mhz cal data for DCO
DCOCTL = CALDCO_1MHZ;// Use 1Mhz cal data for DCO
ACLKInit();
SMCLKInit();
TACLKInit();
TACCR0 = 100;
BotonesInit();
P1DIR_bit.P1DIR_4 = 1;//salida
LcdInit();
LcdStringXY(titulo,16,1,1);
__delay_cycles(500000);//500mseg
LcdStringXY(linea1,16,1,1);
LcdStringXY(linea2,16,1,2);
estadoMODO = 2;
estadoDIV = 3;
estadoCLK = 2;
cambia = 1;
__enable_interrupt();//activa todas las interrupciones
enmascarables.
while(1){
do{
}while(cambia == 0);
cambia = 0;
switch(estadoCLK){
case 0:
LcdStringXY(source0,5,5,1);
break;
case 1:
LcdStringXY(source1,5,5,1);
break;
case 2:

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

LcdStringXY(source2,5,5,1);
break;
case 3:
LcdStringXY(source3,5,5,1);
break;
}
switch(estadoDIV){
case 0:
LcdStringXY(div0,2,15,1);
break;
case 1:
LcdStringXY(div1,2,15,1);
break;
case 2:
LcdStringXY(div2,2,15,1);
break;
case 3:
LcdStringXY(div3,2,15,1);
break;
}
switch(estadoMODO){
case 0:
LcdStringXY(modo0,10,6,2);
break;
case 1:
LcdStringXY(modo1,10,6,2);
break;
case 2:
LcdStringXY(modo2,10,6,2);
break;
case 3:
LcdStringXY(modo3,10,6,2);
break;
}
Setup_Timer0_A3(estadoCLK, estadoDIV, estadoMODO);
}

#pragma vector = TIMER0_A1_VECTOR


__interrupt void InterrupcionLowPrioTimer0_A3(void)
{
unsigned char aux;
aux = TAIV;
if(aux == 0x0A){
P1OUT_bit.P1OUT_4 = ~P1OUT_bit.P1OUT_4;
TACTL_bit.TAIFG = 0;
}
}
#pragma vector = PORT1_VECTOR
__interrupt void InterrupcionPuerto1(void)
{
if(BOTON1_IFG){

117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156

estadoCLK++;
if(estadoCLK > 3){
estadoCLK = 0;
}
cambia = 1;
BOTON1_IFG = 0;
} else if(BOTON2_IFG){
estadoDIV++;
if(estadoDIV > 3){
estadoDIV = 0;
}
cambia = 1;
BOTON2_IFG = 0;
} else if(BOTON3_IFG){
estadoMODO++;
if(estadoMODO > 3){
estadoMODO = 0;
}
cambia = 1;
BOTON3_IFG = 0;
}

Video 1_2:
Video 2_2:
Archivos:
Boxnet.
4Shared.
Estos nuevos enlaces estan compilador con la versin del software IAR 5.40 :

4Shared
esta segunda parte del Timer_A, trataremos con los registros Capture/Compare en su
configuracion de Captura (Capture Mode). Veremos lo prcico que resulta utilizar estos registros y
sus configuraciones para detectar la duracin de un pulso o para decodificar comunicaciones
donde el ancho de los pulsos sea importante para obtener los datos. Para ello hemos realizado dos
programas a manera de ejemplos para practicar.

Capture Mode del Timer0_A3


En la primera parte del post del Timer_A, mencionamos los registros que constituyen el Timer0_A3
dentro del MSP430F2132, de los cuales los que estn en amarillo ya han sido estudiados
anteriormente. Lo nuevo son los tres Canales de Captura/Comparacin (recordar que en el otro
Timer1_A2 slo tiene dos de estos canales) donde cada canal tiene dos registros propios mediante
los cuales podremos configurar y generar la respectiva interrupcin para el modo de captura.

Observemos que para el Canal 0 existen dos registros, lo mismo para los otros canales, todos ellos
tienen la misma estructura y funcin. En nuestro proyecto hemos trabajado solamente con el Canal
0, el estudio de los dems canales se deja como tarea al lector, pues ver que son idnticos al
Canal 0.
Tener en cuenta que antes de tener funcionando el Canal 0 del Timer0_A3 en Modo Captura
tenemos que configurar siempre su respectivo Timer Block, pues como veremos despus, las
capturas dependen directamente del valor que tenga el registro TA0R en el preciso momento de la
captura.

TA0CCR0
En el Modo Captura este registro almacena el valor del registro TA0R cuando se cumple con la
condicin de captura de flanco del Timer0_A3. Dicha condicin se configura en el otro registro del
Canal 0 (TA0CCTL0).

Citamos un ejemplo, digamos que queremos medir el ancho de un pulso (Low-High-Low) entonces
en el primer flanco de subida genera interrupcion (despus veremos donde est su vector de
interrupcin y cmo seleccionar el flanco de captura) y leemos el valor del TA0CCR0 (que acaba
de capturar el valor del TAoR) para almacenarlo en un registro que llamaremos FS, luego se
genera otra interrupcion en el flanco de bajada y guardamos el valor del TA0CCR0 en otro registro
FB. Entonces para determinar el ancho del pulso simplemente restamos FB FS, cuyo resultado
estar en funcin del source clock que tenga configurado el Timer Block del Timer0_A3.
Frecuencia TimerBlock = 125KHz (1MHz SMCLK, divisor /8)
FS = 1206; (primera captura del flanco de subida en Terminos del TA0CCR0)
FB = 1469; (segunda captura del flanco de bajada en Terminos del TA0CCR0)
Ancho de Pulso en Terminos del TA0CCR0 = FB FS = 263
Ancho de Pulso en Segundos = 263/(125KHz) =263/125000 seg. = 2.104 mseg.
TA0CCTL0
El segundo registro del Canal 0 permite configurar el comportamiento del canal, as como la
habilitacin de su interrupcion. Describiremos a continuacin sus campos.

CMx (bits 15-14) : Slo para el Modo Captura. Permite definir el flanco de captura del Canal 0.
0: Sin captura.

1: Captura en flanco de subida.


2: Captura en flanco de bajada.
3: Captura en ambos flancos.
CCISx (bits 13-12) : Slo para el Modo Captura. Permiten definir la seal de entrada cuyos flancos
vamos a capturar.
0: CCI0A. Entrada A para el Canal 0.
1: CCI0B. Entrada B para el Canal 0.
2: GND. Pone a nivel bajo la Entrada del Canal 0.
3: VCC. Pone a nivel alto la Entrada del Canal 0.
Las entradas CCI0A y CCIoB del MSP430F2132 se ubican en los pines P1.1 (CCI0A) y en P2.2
(CCI0B):

SCS (bit 11) : Slo para el Modo Captura. Sirve para sincronizar la captura de la seal con el timer
clock. De preferencia siempre habilitarlo.
SCCI (bit 10) : Bit de slo lectura que sirve para monitorear el estado actual de la entrada de la
seal CCI (seal que proporciona el bloque de los bits CCISx) pero sincronizada.
CAP (bit 8) : Bit que permite definir el modo de trabajo de los Canales de Captura/Comparacin.
0: Modo de Comparacin.
1: Modo de Captura.
OUTMODx (bits 7-5) : Slo para el Modo Comparacin. Explicaremos estos bits en el tercer post
del Timer_A.

CCIE (bit 4) : Bit para habilitar la interrupcion del Canal de Captura/Comparacin.


CCI (bit 3) : Bit de slo lectura que sirve para monitorear el estado actual de la entrada de la seal
CCI (seal que proporciona el bloque de los bits CCISx).
OUT (bit 2) : Slo para el Modo Comparacin. Explicaremos estos bits en el tercer post del
Timer_A.
COV (bit 1) : Slo para el Modo Captura. Indica de que se ha producido una segunda captura del
timer TA0R sin que se halla ledo la primera captura almacenada an en TA0CCR0. Se debe borrar
mediante cdigo.
CCIFG (bit 0) : Bandera de la interrupcin CCIE del Canal 0.

Interrupcin del Modo Captura del Timer0_A3


La interrupcion del Canal 0 es ms simple que la del Timer Block pues tiene su propio vector en la
tabla de direcciones, est ubicado en la prioridad 25.

En el cdigo nos servimos del nombre del vector definido por TIMER0_A0_VECTOR para
construir la funcin de gestionar su interrupcin de captura.

Bueno, ya expuesta la teora tenemos que echar mano a la prctica.

Programa de Aplicacin
En este primer ejemplo tenemos un programa que permite determinar el ancho de un pulso en la
entrada CCI0A del Canal 0 del Timer0_A3:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

#include
#include
#include
#include

"io430.h"
"intrinsics.h"
"bsp\bsp.h"
"lcd2x16\lcd2x16.h"

unsigned
unsigned
unsigned
unsigned

int sampleFS;
int sampleFB;
char samplestate = 0;
char sampleok = 0;

unsigned char datos[4];


int main( void )
{
unsigned char titulo[16] = " microembebidos ";
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
BCSCTL1 = CALBC1_1MHZ;// Use 1Mhz cal data for DCO
DCOCTL = CALDCO_1MHZ;// Use 1Mhz cal data for DCO
P1DIR_bit.P1DIR_4 = 1;//salida
LcdInit();
LcdStringXY(titulo,16,1,1);
ACLKInit();
SMCLKInit();
Timer0_A3_TimerBlockInit();
Timer0_A3_CaptureInputInit();
__enable_interrupt();
while(1){
while((sampleok==0));
if(sampleok){
unsigned int aux;
aux = sampleFB - sampleFS;
ConvertHexToString(aux, datos);
LcdStringXY(datos,4,1,2);
sampleok = 0;
}
}

#pragma vector = TIMER0_A0_VECTOR

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

__interrupt void InterrupcionHighPrioTimer0_A3(void)


{
if(samplestate == 0){
sampleFS = TACCR0;
samplestate++;
} else if(samplestate == 1){
sampleFB = TACCR0;
samplestate++;
sampleok = 1;
}
TACCTL0_bit.CCIFG = 0;
}
#pragma vector = TIMER0_A1_VECTOR
__interrupt void InterrupcionLowPrioTimer0_A3(void)
{
unsigned char aux;
aux = TAIV;
if(aux == 0x02){
TACCTL1_bit.CCIFG = 0;
} else if(aux == 0x0A){
P1OUT_bit.P1OUT_4 = ~P1OUT_bit.P1OUT_4;
TACTL_bit.TAIFG = 0;
}
}

En este segundo ejemplo hemos implementado la lectura de una trama de pulsos que pertenecen
a la codificacin CODE39 que utlizan las tarjetas de cdigo de barras, donde el ancho de los
pulsos determinan el digito codificado:

1
2
3
4
5
6
7
8
9
10

#include
#include
#include
#include

"io430.h"
"intrinsics.h"
"bsp\bsp.h"
"lcd2x16\lcd2x16.h"

unsigned char samplestate = 0;


unsigned char sampleok = 0;
unsigned char dato;
unsigned int barraFS;
unsigned int barraFB;

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

unsigned int espacioFB;


unsigned int espacioFS;
unsigned int digitocode39;
unsigned int lenghtcode39[9];
int main( void )
{
unsigned char titulo[16] = " microembebidos ";
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
BCSCTL1 = CALBC1_1MHZ;// Use 1Mhz cal data for DCO
DCOCTL = CALDCO_1MHZ;// Use 1Mhz cal data for DCO
P1DIR_bit.P1DIR_4 = 1;//salida
LcdInit();
LcdStringXY(titulo,16,1,1);
ACLKInit();
SMCLKInit();
Timer0_A3_TimerBlockInit();
Timer0_A3_CaptureInputInit();
__enable_interrupt();
while(1){
while((sampleok==0));
if(sampleok){
unsigned int aux;
unsigned int ancho;
unsigned int peque;
//determinamos las longitudes
if(lenghtcode39[0]>lenghtcode39[1]){
ancho = lenghtcode39[0];
peque = lenghtcode39[1];
} else {
peque = lenghtcode39[0];
ancho = lenghtcode39[1];
}
//hallamos el codigo
for(digitocode39 = 0,aux = 0; aux < 9; aux++){
if(lenghtcode39[aux] < (peque*2)){
//colocamos un cero
digitocode39 = digitocode39 & 0xFE;
} else {
//colocamos un uno

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

digitocode39 = digitocode39 | 0x01;


}
digitocode39 = digitocode39 << 1;
}
digitocode39 = digitocode39 >> 1;
//imprimir el dato
//ConvertHexToString(digitocode39, datos);
if(digitocode39 == 0x0094){
dato = '*';
} else if(digitocode39 == 0x0034){
dato = '0';
} else if(digitocode39 == 0x0121){
dato = '1';
} else if(digitocode39 == 0x0061){
dato = '2';
} else {
dato = 'E';
}
LcdStringXY(&dato,1,1,2);
sampleok = 0;
__disable_interrupt();
}

}
#pragma vector = TIMER0_A0_VECTOR
__interrupt void InterrupcionHighPrioTimer0_A3(void)
{
switch(samplestate){
case 0:
barraFS = TACCR0;
break;
case 1:
barraFB = TACCR0;
espacioFB = barraFB;
lenghtcode39[0]=barraFB-barraFS;
break;
case 2:
espacioFS = TACCR0;
barraFS = espacioFS;
lenghtcode39[1]=espacioFS-espacioFB;
break;
case 3:
barraFB = TACCR0;
espacioFB = barraFB;
lenghtcode39[2]=barraFB-barraFS;
break;
case 4:
espacioFS = TACCR0;
barraFS = espacioFS;
lenghtcode39[3]=espacioFS-espacioFB;
break;
case 5:
barraFB = TACCR0;
espacioFB = barraFB;
lenghtcode39[4]=barraFB-barraFS;
break;

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

//
//
//
//
//
//
//
//
}

case 6:
espacioFS = TACCR0;
barraFS = espacioFS;
lenghtcode39[5]=espacioFS-espacioFB;
break;
case 7:
barraFB = TACCR0;
espacioFB = barraFB;
lenghtcode39[6]=barraFB-barraFS;
break;
case 8:
espacioFS = TACCR0;
barraFS = espacioFS;
lenghtcode39[7]=espacioFS-espacioFB;
break;
case 9:
barraFB = TACCR0;
//espacioFB = barraFB;
lenghtcode39[8]=barraFB-barraFS;
sampleok = 1;
break;
}
if(samplestate == 0){
barraFS = TACCR0;
samplestate++;
} else if(samplestate == 1){
barraFB = TACCR0;
espacioFB = barraFB;
samplestate++;
}
samplestate++;
TACCTL0_bit.CCIFG = 0;

#pragma vector = TIMER0_A1_VECTOR


__interrupt void InterrupcionLowPrioTimer0_A3(void)
{
unsigned char aux;
aux = TAIV;
if(aux == 0x02){
TACCTL1_bit.CCIFG = 0;
} else if(aux == 0x0A){
P1OUT_bit.P1OUT_4 = ~P1OUT_bit.P1OUT_4;
TACTL_bit.TAIFG = 0;
}
}

152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
Videos:

Lab 4 - Interrumpe con ensamblador y C

En esta prctica, vamos a cubrir dos temas principales:


- Interrups y rutinas de servicio de interrupcin
- C programacin del MSP430

Tutorial y Antecedentes

1 - Las interrupciones en la Asamblea

Las interrupciones sern discutidos en la conferencia - pero en pocas palabras que son un mecanismo para tomar el control del procesador en funcin de la
peticin de hardware. El procesador completa con gracia la instruccin actual y
luego los "servicios" de la interrupcin, ejecute el cdigo definido en una rutina
de servicio de interrupcin. Hay muchas fuentes de las interrupciones en el
MSP430, pero en este laboratorio vamos a centrar en la entrada de propsito
general en P1.3 que est unido al pulsador.

Una interrupcin en P1.3 se puede activar mediante el control de varios


puertos 1 registros encontrados:

P1IE es un registro que permite a las interrupciones para el puerto 1 pins.

P1IES es el opositor que determina (si las interrupciones estn habilitadas


para el pin correspondiente) para que el borde (ascendente o descendente)
causa una interrupcin.

P1IFG es el registro en el que cada bit PxIFGx es la bandera de interrupcin


para su correspondiente pin de E / S y se establece cuando el borde de la seal
de entrada seleccionada aparece en el pin. Todos PxIFGx interrumpen banderas
solicitar una interrupcin cuando su correspondiente bit PXIe y el bit GIE se
establecen. Cada bandera PxIFG se debe restablecer con el software. El
software tambin puede configurar cada bandera PxIFG, proporcionando una
manera de generar un programa iniciado interrupcin.

Bit = 0: Sin interrupcin est pendiente


Bit = 1: Una interrupcin est pendiente

Slo las transiciones, los niveles estticos, no causan interrupciones. Si


cualquier bandera PxIFGx cuaja durante la rutina de servicio de interrupcin Px,
o si se establece despus de la instruccin RETI de una rutina de servicio de
interrupcin Px se ejecuta, la bandera conjunto PxIFGx genera otra
interrupcin. Esto asegura que se reconoce cada transicin.

Finalmente, las banderas de interrupcin debe ser limpiado y, finalmente, las


alarmas deben estar habilitadas en todo el mundo. Estas tres lneas realizan
esta funcin en este caso.

Cmo implementar rutinas de servicio de interrupcin

Para utilizar interrumpe necesita configurar su interrupcin especfica (puerto


1.3 en este caso), desactive las interrupciones pendientes y habilitar las
interrupciones globalmente. Este cdigo hace esto.

bis.b # 008H, y P1IE; P1.3 Interrupcin habilitada


bis.b # 008H, y P1IES; Hi P1.3 / borde inferior
bic.b # 008H, y P1IFG; IFG P1.3 Autorizado
bis.w # GIE, SR; LPM4, habilitar las interrupciones

Aadir este cdigo de ejemplo al final de su programa de la asamblea para


incluir una rutina de servicio de interrupcin para el puerto 1. Usted tendr que
aadir el cdigo del programa especfico por encima de la instruccin RETI. El
bic.b es necesario borrar el indicador de interrupcin. Esto se conoce como
"reconocer" la interrupcin y evita una solicitud de interrupcin siendo
administrados ms de una vez.

; ------------------------------------------------- -----------------------------P1_ISR; P1.0 Toggle salida


; ------------------------------------------------- -----------------------------; AADIR CDIGO AQU PARA SERVICIO DE INTERRUPCIN DE RUTINA
bic.b # 008H, y P1IFG; IFG P1.3 Autorizado
retina; Regreso de ISR
;
; ------------------------------------------------- ----------------------------; interrupcin Vectores
; ------------------------------------------------- -----------------------------

. secta ". reset"; REINICIAR MSP430 Vector


. REINICIAR corto;
. secta "int02."; P1.x Vector
. P1_ISR corto;
. fin

2 - Introduccin a C con el MSP430

TI tiene una amplia documentacin sobre el Code Composer Studio. Usted


puede encontrar todo aqu.
Para crear un proyecto de CCS, seleccione Proyecto CCS "en el nuevo men
Archivo->. Seleccione un "Proyecto vaco" con el fin de crear un proyecto de C.

You might also like