You are on page 1of 44

1 LaunchPad

Gua definitiva de Microcontroladores TI:

LaunchPad

@Autor : Jorge Rodriguez

February 6, 2014
2 LaunchPad

Introduccin:

Este pequeo manual pero til, est enfocado en cmo empezar a programar en Code Composer
Studio y el uso del Kit de desarrollo de Texas intruments que es el LaunchPad.

En este manual desarrollaremos practicas sencillas para entender el funcionamiento de los


microcontroladores MSP430, a partir de ah el usuario podra realizar tareas ms complejas.

February 6, 2014
3 LaunchPad

Qu es Launch Pad?

La familia de Microcontroladores de Texas Intruments son dispositivos de 16-bits de bajo


consumo, estos estn en el mercado para aplicaciones que requieran bajo consumo tanto como
dispositivos para bateras aunque estos contienen un procesador sofisticado independientemente
del modelo, y un arreglo de perifricos integrado.

La compaa de Texas intruments ha desarrollado una tarjeta para los desarrolladores que deseen
entrar al mundo de los microcontroladores de TI.

LaunchPad es la tarjeta que nos permitir programar y debugear nuestros programas en los
microcontroladores de MSP430.

February 6, 2014
4 LaunchPad

Crear un Proyecto:
La herramienta fundamental para empezar a programar los microcontroladores es el IDE que
ofrece gratuitamente TI, estoy hablando de Code Composer Studio 5.5, esta herramienta nos
proporcionar todo lo necesario para programar los microcontroladores MSP430 y debugearlos.

Para poder obtener esta herramienta se debe de acceder a la pgina de Texas Intruments. Cuando
lo tengamos instalado vayamos a seguir el siguiente procedimiento para inicializar correctamente
el nuevo proyecto.

Cuando estemos en la ventana principal del CCS 5.5 (Code Composer Studio 5.5), vayamos a la
pestaa de <Proyect> y seleccionamos la opcin <New CCS proyect> y se abrir una ventana para
la configuracin del proyecto.

February 6, 2014
5 LaunchPad

En esta ventana, nos pedir el nombre del proyecto, del cual puede ser cualquier nombre que
deseemos, si queremos cambiar la ruta de guardar nuestro proyecto podemos deshabilitar la
seleccin Use Default location y guardar el proyecto en el lugar que queramos.

En el cuadro de Device, solo hay que checar que este seleccionado en Family los dispositivos
MSP430, y todo lo siguiente lo podemos dejar como esta.

Solo falta de seleccionar la opcin de Empty Proyect(With Main.c) para cuando aceptemos, nos
genere el archivo principal con la extensin C.

Realizando todo lo anterior estamos listos para empezar a programar en C para


microcontroladores MSP430 de TI.

February 6, 2014
6 LaunchPad

Proyecto # 1:

BLINK
En estos proyectos no voy a explicar detenidamente como programar en C, el usuario debe de
estar familiarizado con este lenguaje, lo que vamos a tratar en los temas siguientes es configurar
los perifricos de los microcontroladores MSP430.

Para empezar con el primer proyecto que no es ms que un simple parpadeo de una salida, se
debe tener la hoja de datos del dispositivo en este caso el MSP430G2553.

Con la hoja de datos tenemos todo lo necesario para entrar al


mundo de los MSP430, para iniciar el proyecto vamos a
configurar nuestro controlador.

February 6, 2014
7 LaunchPad

Los pasos bsicos para tener configurado nuestro programa al iniciar cualquier proyecto, son los
siguientes, aunque esto se puede aplicar para otras familias de microcontroladores.

Pasos:

1. Inicializar Frecuencia de trabajo.


2. Inicializa la direccin (Entrada o salida) de cada puerto del Micro.
3. Inicializar los perifricos que vamos a usar.
4. *Inicializar Interrupciones (Si existen)
5. Realizar Algoritmo Final.

El primer paso es establecer la frecuencia de trabajo, esto nos permite ya tener estable lo que es la
velocidad del controlador, y as tener la referencia de velocidad.

Para establecer la frecuencia para los MS430 es:

/*
* Se calibra la velocidad del cristal interno
* a 1 Mhz
*/
if(CALBC1_1MHZ == 0xFF || CALDCO_1MHZ == 0xFF){
while(1);
}

BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;

Si queremos saber lo que significa, podemos pasarnos a la hoja de datos.

El modulo bsico de reloj incluye dos, tres o cuatro recursos de reloj:

LFXT1CLK : El oscilador de baja y alta frecuencia que puede ser usado con cristales de reloj
de baja frecuencia o relojes externos de 32768 Hz o con cristales estndar, resonadores o
relojes externos.
XT2CLK: Una Opcin de oscilador de alta frecuencia que puede ser usado con cristales
estndar, resonadores o relojes externos en 400 Khz a 16 Mhz.
DCOCLK: Oscilador controlado digitalmente interno (DCO)
VLOCLK: Fuente interna muy baja, oscilador de baja frecuencia con 12 Khz de frecuencia
tpica.
ACLK: Reloj auxiliar. ACLK es seleccionado por software como LFXT1CKL o VLOCLK. ACLK es
divido por 1,2,4 o 8. ACLK es seleccionable por software para mdulos de perifricos
individuales.
MCLK: Reloj Maestro. MCLK es seleccionable por software como LFXT1CLK,
VLOCLK,XT2CLK (Si est disponible en el micro) o DCOCLK. MCLK is divido por 1,2,4,o 8.
MCLK es usado por el CPU y el sistema.

February 6, 2014
8 LaunchPad

SMCLK: Reloj Sub-principal. SMCLK es seleccionable por software como LFXT1CLK, VLOCLK,
XT2CLK (si dispone en el micro) o DC0CLK. SMCLK es divido por 1,2,4 o 8. SMCLK es
seleccionable por software para mdulos de perifricos individuales.

Entonces lo que estamos haciendo en el ejemplo anterior es poner una sentencia de decisin para
saber si los parmetros que por default tiene el microcontrolador para operar a 1Mhz este bien
calibrado, si por alguna causa se perdi lo que es la calibracin entonces caemos en un ciclo
infinito, sino calibramos lo que es la calibracin a 1Mhz.

Ahora bien ya hemos calibrado la velocidad con el que va a trabajar el micro, ahora debemos de
configurar la direccin de los puertos (Entra o salida). Para ello tenemos el registro PxDir, este
registro nos permitir definir el pin que vamos a usar como entrada o salida.

P1DIR |= BIT0; // P1DIR is a register that


configures the direction (DIR) of a port pin as an output or an input.

Cuando ponemos a 1 un bit del registro pasado es porque es en modo de salida y cuando es 0 es
de modo entrada.

Entonces ya hemos configurado la direccin del pin que vamos a usar para encender y apagar el
Led en el pin 0, en este caso TI define sus pines en los puertos como P1.0. P1 = Puerto 1 , 0=Bit 0.

Ahora bien como no vamos a usar lo que son los perifricos como es ADC, UART,SPI, etc. No
realizaremos mas, sino nada as entramos al algoritmo que vamos a implementar para el parpadeo
de un Led.

Para que siempre este corriendo nuestro programa en el micro, usaremo un ciclo For, sin
parmetros, para que este siempre este corriendo.

for (;;){

P1OUT ^= BIT0;

for(i=0; i< 20000; i++);


}

Con esta sentencia podemos crear un loop.

February 6, 2014
9 LaunchPad

Programa completo:

#include <msp430g2553.h>

unsigned int i = 0; // Initialize variables. This will


keep count of how many cycles between LED toggles

void main(void)
{
WDTCTL = WDTPW + WDTHOLD;

/*
* Se calibra la velocidad del cristal interno
* a 1 Mhz
*/
if(CALBC1_1MHZ == 0xFF || CALDCO_1MHZ == 0xFF){
while(1);
}

BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;

P1DIR |=BIT0;

for (;;){

P1OUT ^= BIT0;

for(i=0; i< 20000; i++);


}
}

February 6, 2014
10 LaunchPad

Cargar Codigo en MSP430:

Debemos de tener conectado a la computadora el launchpad, y en CCS en el Icono de debug

para cargar el programa en el micro, esperamos hasta empezar a debugear o arrancar el

programa en los iconos .

Al presionar en el icono de play, podemos notar que arrancara el programa sin pausa alguna, ya si
queremos debugear podemos poner breakpoints.

February 6, 2014
11 LaunchPad

Proyecto # 2:

Shift Leds
Para aun aprendiendo como usar las salidas digitales y entradas, vamos a realizar un pequeo
ejemplo donde haremos un corrimiento de leds y un switch para cambiar el sentido de corrimiento.

Lo que primero hay que hacer es los pasos que hemos visto en el ejemplo anterior:

1. Inicializar Frecuencia de trabajo.


2. Inicializa la direccin (Entrada o salida) de cada puerto del Micro.
3. Inicializar los perifricos que vamos a usar.
4. *Inicializar Interrupciones (Si existen)
5. Realizar Algoritmo Final.

Como desarrollamos en el ejemplo anterior para la inicializacin de la frecuencia del trabajo, se


utiliza las siguientes lneas.
/*
* Se calibra la velocidad del cristal interno
* a 1 Mhz
*/
if(CALBC1_1MHZ == 0xFF || CALDCO_1MHZ == 0xFF){
while(1);
}

BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;

Esto no permita que el microcontrolador opere a 1Mhz, como este dispositivo utiliza la arquitectura
RISC, ejecuta cada instruccin a la velocidad que tenga el MCLCK, en este caso cada 1 e-6 segundos.

Ahora debemos configurar los puertos de trabajo, no es mas que configurar cual es entrada y cual
es salida.

February 6, 2014
12 LaunchPad

/*
* Inicializa los P1.0 al P1.7 como salida
* Inicializa Apagado
*/
P1DIR|=0xFF;
P1OUT=0x00;
P1REN=0x00;
/*
* Inicializa el pin P2.0 como entrada
* P2.0 - Pullup
*/
P2DIR&=~(BIT0);
P2OUT|=(BIT0);
P2REN|=(BIT0);

/*
* Inicializa Puerto 2
*/
P1OUT=0x01;

Podemos saber que significa cada registro en el manual para saber exactamente para que sirve cada
uno.

PXDIR

Cada bit del registro PxDIR selecciona la direccin correspondiente Entrada o Salida. Los bits de
PxDIR para los pines de Entrada y Salida que estn seleccionados para otras funciones deben estar
establecidas como se requiere para la otra funcin.

BIT = 0 : El pin del puerto es cambiado a direccin de entrada.

BIT = 1 : El pin del puerto es cambiado a direccin de salida.

PXOUT

Cada bit en cada registro del PxOUT es el valor para actuar como salida en pin Entrada/Salida
correspondiente cuando es configurado como funcin de Entrada o Salida, y la resistencia
PullUp/down es deshabilitado.

BIT = 0: La salida est apagado

BIT = 1: La salida est en Alto.

February 6, 2014
13 LaunchPad

Cada bit en cada registro PxREN habilita o deshabilita la resistencia PullUp/Down del
correspondiente entrada o salida. El bit correspondiente en el registro PxOUT selecciona si el pin
es PullUp o PullDown.

BIT = 0: Resistencia PullUP/Down es deshabilitado.

BIT = 1: Resistencia PullUP/Down es habilitado.

Como ya hemos configurado lo que es el oscilador y los pines de trabajo, lo que sigue es nuestro
algoritmo, ya que no hemos habilitado interrupciones.
while(1){

if(!(P2IN&0x01)){

inc=1;

}else{

inc=0;
}

shift_leds(inc);

delay(10000);
}

La logia es simple cuando el PIN P2.0 es presionado cambiamos la variable inc a 1, para cambiar el
sentido de corrimiento, al soltar el switch la variable cambiara a cero y corriendo los leds al sentido
opuesto.

Como vemos una funcin shift_leds este nos permitir cambiar el sentido con el parmetro inc.
/*
* @PARAM = shift -> Variable que maneja el corrimiento de led
* = 0 ->Corrimiento hacia la derecha
* = 1 ->Corrimiento hacia la Izquierda
*/

void shift_leds(unsigned char shift){

if(shift==1){

if((P1OUT&0x10)==0X10){
P1OUT=0x01;
}else{
P1OUT<<=1;
}

February 6, 2014
14 LaunchPad

}else{

if((P1OUT&0x01)==0x01){
P1OUT=0x10;
}else{
P1OUT>>=1;
}

}
}

Programa Completo:
/*
* Codigo para hacer un corrimiento de led
* Compaia: ucursos.blogspot.com
*/

#include <msp430g2553.h>
#include"Libraries/delay.h"

/*
* Definimos Varibales globales
*/

volatile unsigned char inc=0;

/*
* @PARAM = shift -> Variable que maneja el corrimiento de led
* = 0 ->Corrimiento hacia la derecha
* = 1 ->Corrimiento hacia la Izquierda
*/

void shift_leds(unsigned char shift){

if(shift==1){

if((P1OUT&0x10)==0X10){
P1OUT=0x01;
}else{
P1OUT<<=1;
}

}else{

if((P1OUT&0x01)==0x01){
P1OUT=0x10;
}else{
P1OUT>>=1;
}

February 6, 2014
15 LaunchPad

/*
* main.c
*/
void main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

/*
* Se calibra la velocidad del cristal interno
* a 1 Mhz
*/
if(CALBC1_1MHZ == 0xFF || CALDCO_1MHZ == 0xFF){
while(1);
}

BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;

/*
* Inicializa los P1.0 al P1.7 como salida
* Inicializa Apagado
*/
P1DIR|=0xFF;
P1OUT=0x00;
P1REN=0x00;
/*
* Inicializa el pin P2.0 como entrada
* P2.0 - Pullup
*/
P2DIR&=~(BIT0);
P2OUT|=(BIT0);
P2REN|=(BIT0);

/*
* Inicializa Puerto 2
*/
P1OUT=0x01;

while(1){

if(!(P2IN&0x01)){

inc=1;

}else{

inc=0;
}

shift_leds(inc);

delay(10000);
}

February 6, 2014
16 LaunchPad

El diagrama es el siguiente:

February 6, 2014
17 LaunchPad

Proyecto # 3:

USCI: UART
En este proyecto nos enfocaremos al uso del USCI en modo UART, el USCI es Universal Serial
Comunication Interface por sus siglas en ingls, este interfaz puede operar tanto como UART, SPI,
I2C. Como mencionaba, en este proyecto vamos a configurar el USCI en modo UART, para ya tener
listo lo que es la librera y poder usarlo en otros proyectos que ms adelante veremos.

El launchPad que tenemos en las manos, tiene por default una configuracin en unos de sus
puentes para poderlo usar como Serial.

En la imagen superior podemos notar que tenemos dos puentes, RXD,TXD, y estn en forma
vertical, lo que vamos hacer es cambiar los puentes en forma horizontal tal como se ve en la
siguiente imagen.

February 6, 2014
18 LaunchPad

Y as de fcil hemos configurado el UART con el launchpad, ahora sigue la programacin para
usarlo.
P1SEL = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
P1SEL2 = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD

/*
* Configuracin del Mdulo Serial
* 9600,8,N,1
*/

UCA0CTL1 |= UCSSEL_2; // SMCLK - Set Master Clock


UCA0BR0 = 104; // 1Mhz/9600 = 104
UCA0BR1 = 0; // = 0
UCA0MCTL = UCBRS0; // Modulation UCBRSx = 1
UCA0CTL1 &= ~UCSWRST; // **Inicializa USCI **
IE2 |= UCA0RXIE; // Habilitamos Interrupcin de
Recepcin USCI

Las siguientes configuracin que se presenta arriba es una configuracin de 9600,8,N,1, para
saber lo que estamos haciendo podemos pasarnos a la hoja de datos del microcontrolador, para
checar los registros que estamos usando, y entender mejor la configuracin.

Como vamos a usar los pines que se relacionan con el perifrico del USCI, vamos a configurarlos
usando los dos registros:

P1SEL = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD


P1SEL2 = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD

Y as ya estn configurados los dos pines que en este caso son P1.1 Y y P1.2. Ahora bien, es tiempo
de decirle al micro que el USCI estar usando el Oscilador Maestro, para ello vamos a establecer el
bit UCSSEL_2 del registro UCA0CTL1 . Como ya sabe el micro que vamos a usar el oscilador
Maestro es tiempo de indicarle a qu velocidad va a trabajar el UART, hay que establecer el valor
en el registro UCA0BR0 usando la siguiente formula.

=
0

Despejamos:

0 0=

February 6, 2014
19 LaunchPad

En mi caso voy a establecer los baudios a 9600, entonces el valor que tengo que cargar al registro
es de 104, como el registro UCA0BR0 es de 16 bits, entonces solo cargar en el registro de 8 bits
de menor peso, y el de mayor peso lo dejar en cero.

/*
* Configuracion del Modulo Serial
* 9600,8,N,1
*/

UCA0CTL1 |= UCSSEL_2; // SMCLK - Set Master Clock


UCA0BR0 = 104; // 1Mhz/9600 = 104
UCA0BR1 = 0; // = 0

Despus por defecto hay que establecer la modulacin usando la siguiente sentencia.
UCA0MCTL = UCBRS0; // Modulation UCBRSx = 1

El modulo estar en estado de espera hasta liberar el bit,


UCSWRST

0 = Deshabilitado. Reinicia el USCI para la operacin

1 = Habilita. Mantiene el USCI en estado de espera.

La configuracin que hicimos con anterioridad est en modo de espera solo hay que establecer a
cero el bit UCSWRST .
UCA0CTL1 &= ~UCSWRST; // **Inicializa USCI **

Para ya terminar la configuracin del UART, vallamos a usar la interrupcin por recepcin ya que
ms adelante la usaremos.
IE2 |= UCA0RXIE; // Habilitamos Interrupcion de
Recepcion USCI

Si ya has llegado hasta aqu, ahora sigue nuestra lgica para crear las funciones pertinentes para la
recepcin y transmisin de datos. Aunque ya existe la funciones para hacer estas tareas usando la
librera STDIO.H , por defecto no podemos usar lo que es la sentencia printf ya que requiere
minimo 1 Kbyte de memoria RAM, entonces estamos limitados a usar esta funcin, buscando una
solucin, estuve pensando en algo para solucionar este gran dilema, entonces encontr las
funciones bsicas necesarias para transmitir datos.

February 6, 2014
20 LaunchPad

/*********************************************************************
* @brief Funcion para enviar un caracter
* @param[in] _c - Caracter a enviar
* @return None
**********************************************************************/

void putch(unsigned char _c){

while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready?


IFG2&=~(UCA0TXIFG);
UCA0TXBUF = _c; // TX -> RXed character

/*********************************************************************
* @brief Funcion para enviar una cadena de caracteres usando la RAM
* @param[in] _str - Puntero que localiza el primer byte de un arreglo
* @return None
**********************************************************************/

void puts_ram(char* _str){

do{

putch(*_str);

}while((*_str++)!='\r');
}

/*********************************************************************
* @brief Funcion para enviar una cadena de caracteres usando la ROM
* @param[in] _str - Puntero que localiza el primer byte de un arreglo
* @return None
**********************************************************************/

void puts_rom(const char* _str){

do{

putch(*_str);

}while((*_str++)!='\r');

/*********************************************************************
* @brief Funcion que regresa el paquete que recibio por el serial
* @param[in] _buf - Puntero que localiza el primer byte de un arreglo
* @return None
**********************************************************************/

void getchs(char* _buf){

unsigned char _i=0;

February 6, 2014
21 LaunchPad

do{
if(_i>sizeof(buffer_rx)) break;

while(!(IFG2&UCA0RXIFG)) continue;
IFG2&=~UCA0RXIFG;

buffer_rx[_i]=UCA0RXBUF;

}while(buffer_rx[_i++]!='\r');

IFG2&=~UCA0RXIFG;

/*********************************************************************
* @brief Limpia el buffer de Tx & Rx
* @param[in] None
* @return None
**********************************************************************/

void clear_buffers(void){
unsigned char index;

for(index=0;index<len_buffer;index++){
buffer_rx[index]=0;
buffer_tx[index]=0;
}
}

Si os un buen programador entendis estas simple funciones, sino entonces puedes leer los
encabezados de cada funcin para su entendimiento.

Esta prctica solo vamos a recibir datos por el serial usando la interrupcin por recepcin, y volver
a enviar la misma cadena de caracteres.
__bis_SR_register(GIE); // Habilitamos Interrupcione globales

puts_rom("Hola Mundo\r\n");

while(1){

puts_rom("Escribe cualquier caracter para reenviar\r\n");

while(!Flags.Rx);
Flags.Rx=0;

sprintf(buffer_tx,"%s\r",&buffer_rx);
puts_ram(buffer_tx);

clear_buffers();

February 6, 2014
22 LaunchPad

Como hemos habilitado lo que es la interrupcin, podemos usar el vector de recepcin, usando la
siguiente funcin:
/*
* Servicio de Interrupcion en Vector USCI_RX
*/
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
if(IFG2&UCA0RXIFG){

getchs(buffer_rx);

Flags.Rx=1;
}
}

Los vectores ya estn definidos en el compilador, pero para entender mejor esto de vectores
veamos la siguiente tabla:

February 6, 2014
23 LaunchPad

Entonces el cdigo nos quedara de la siguiente forma:


/*
* Codigo para la comunicacion UART
* Compaia: ucursos.blogspot.com
*/

#include <msp430g2553.h>
#include <stdio.h>

/*
* Definimos constantes
*/

#define len_buffer 20

/*
* Definimos Variables Globales
*/

struct{
unsigned Rx:1;
unsigned dumy:7;
}Flags={0};

char buffer_rx[len_buffer];
char buffer_tx[len_buffer];

/*********************************************************************
* @brief Funcion para enviar un caracter
* @param[in] _c - Caracter a enviar
* @return None
**********************************************************************/

void putch(unsigned char _c){

while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready?


IFG2&=~(UCA0TXIFG);
UCA0TXBUF = _c; // TX -> RXed character

/*********************************************************************
* @brief Funcion para enviar una cadena de caracteres usando la RAM
* @param[in] _str - Puntero que localiza el primer byte de un arreglo
* @return None
**********************************************************************/

void puts_ram(char* _str){

do{

putch(*_str);

February 6, 2014
24 LaunchPad

}while((*_str++)!='\r');
}

/*********************************************************************
* @brief Funcion para enviar una cadena de caracteres usando la ROM
* @param[in] _str - Puntero que localiza el primer byte de un arreglo
* @return None
**********************************************************************/

void puts_rom(const char* _str){

do{

putch(*_str);

}while((*_str++)!='\r');

/*********************************************************************
* @brief Funcion que regresa el paquete que recibio por el serial
* @param[in] _buf - Puntero que localiza el primer byte de un arreglo
* @return None
**********************************************************************/

void getchs(char* _buf){

unsigned char _i=0;

do{
if(_i>sizeof(buffer_rx)) break;

while(!(IFG2&UCA0RXIFG)) continue;
IFG2&=~UCA0RXIFG;

buffer_rx[_i]=UCA0RXBUF;

}while(buffer_rx[_i++]!='\r');

IFG2&=~UCA0RXIFG;

/*********************************************************************
* @brief Limpia el buffer de Tx & Rx
* @param[in] None
* @return None
**********************************************************************/

void clear_buffers(void){
unsigned char index;

for(index=0;index<len_buffer;index++){
buffer_rx[index]=0;

February 6, 2014
25 LaunchPad

buffer_tx[index]=0;
}
}

/*
* Servicio de Interrupcion en Vector USCI_RX
*/
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
if(IFG2&UCA0RXIFG){

getchs(buffer_rx);

Flags.Rx=1;
}
}

/*
* main.c
*/
void main(void) {

WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

/*
* Se calibra la velocidad del cristal interno
* a 1 Mhz
*/
if(CALBC1_1MHZ == 0xFF || CALDCO_1MHZ == 0xFF){
while(1);
}

BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;

P1SEL = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD


P1SEL2 = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD

/*
* Configuracion del Modulo Serial
* 9600,8,N,1
*/

UCA0CTL1 |= UCSSEL_2; // SMCLK - Set Master Clock


UCA0BR0 = 104; // 1Mhz/9600 = 104
UCA0BR1 = 0; // = 0
UCA0MCTL = UCBRS0; // Modulation UCBRSx = 1
UCA0CTL1 &= ~UCSWRST; // **Inicializa USCI **
IE2 |= UCA0RXIE; // Habilitamos Interrupcion de
Recepcion USCI

__bis_SR_register(GIE); // Habilitamos Interrupcione globales

February 6, 2014
26 LaunchPad

puts_rom("Hola Mundo\r\n");

while(1){

puts_rom("Escribe cualquier caracter para reenviar\r\n");

while(!Flags.Rx);
Flags.Rx=0;

sprintf(buffer_tx,"%s\r",&buffer_rx);
puts_ram(buffer_tx);

clear_buffers();

}
}

February 6, 2014
27 LaunchPad

Simulacin:

Las herramientas necesarias para llevar acabo la simulacin es:

HERCULES_3-2-6

Software para usarlo como receptor y transmisor de datos va UART, para usarlo solo conectemos
el launchpad al puerto USB y busquemos que puerto ha generado, puede ser cualquiera, al saber
cul es el puerto hay que abrir el software HERCULES y en la pestaa serial buscar el COM de
nuestro launchpad, y poner la velocidad a 9600.

Al abrir el puerto, solo basta de escribir lo que nosotros guste para despus con un solo ENTER, el
LAUNCHPAD lo reenve.

Si has notado en el programa una sentencia IF donde pongo un lmite de caracteres por recibir:
if(_i>sizeof(buffer_rx)) break;

Cuando supere el buffer de recepcin los datos que hemos enviado este solo se saldr del ciclo
para enviar los datos.

February 6, 2014
28 LaunchPad

Proyecto # 4:

ADC
En cualquier proyecto no falta usar el ADC (Convertidor Anlogo-Digital) en los
microcontroladores, ya que a veces es requerido convertir una seal fsica a una seal digital, y no
hay nada mejor que un convertidor ADC. En este proyecto nos enfocaremos en la configuracin
mnima para realizar una conversin de una seal de un Potencimetro y proyectarlo en nuestra
computadora usando lo que hemos visto en el proyecto anterior que es el USCI modo UART.
Tambin para agregar un ejemplo de cmo hacer una librera tal como el UART, para tener un
cdigo ms limpio.

Nuevamente para empezar a entender mejor como configurar este perifrico, vamos a usar los
pasos que hemos estado realizando en los proyectos anteriores.

1. Inicializar Frecuencia de trabajo.


2. Inicializa la direccin (Entrada o salida) de cada puerto del Micro.
3. Inicializar los perifricos que vamos a usar.
4. *Inicializar Interrupciones (Si existen)
5. Realizar Algoritmo Final.

Como no era de esperarse, el primer paso es elemental en todo proyecto para establecer la
frecuencia de trabajo, las instrucciones a la conocemos y no es ms que:
/*
* Se calibra la velocidad del cristal interno
* a 1 Mhz
*/
if(CALBC1_1MHZ == 0xFF || CALDCO_1MHZ == 0xFF){
while(1);
}

BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ

February 6, 2014
29 LaunchPad

Voy a dar un parntesis para mencionarles que yo empec a programar con los
microcontroladores PIC de microchip, y en verdad aprend rpido no mucho por ser rpido para
aprender sino ms que nada porque haba mucha informacin en internet, pero cuando uno quiere
migrar a otro Microcontrolador no muy conocido en el ambiente hobbysta, es muy difcil
aprenderlo. Es la razn por cual realice algunos proyectos con PIC, despus de saber que lo tena
dominado, entonces busque otros microcontroladores como metas para usarlos.

Hoy en da los que se estn usando ms a nivel industrial son los ARM CORTEX M3-4, ARM CORTEX
A10, etc. Estos son de arquitectura de 32 bits y de bajo costo.

Los de Texas instruments son muy buenos llegando tener ms rendimiento que los PIC o inclusive a
los AVR. Esta es la razn por la cual empec a realizar este tutorial muy completo para que usted
no tenga miedo a cambiar de tecnologa, sino al contrario que usted pueda dominar cualquier
dispositivo.

Regresando al uso del ADC, tenemos el siguiente punto que es Inicializar las entradas y salidas que
vamos a usar, en mi caso brinque este paso para configurar los perifricos como es el UART y ADC,
para el UART podemos crear una librera para poder utilizarlo las veces que deseamos en cada
proyecto.

/*
* Configuracion por defecto del Modulo Serial
* 9600,8,N,1
* Interrupcion Activada
*/
Init_USCI();

Para llegar a esta funcin basta de crear dos archivos en el proyecto con la extensin C para
incluir las funciones que realizamos en el proyecto pasado, despus creamos otro documento con
la extensin H donde esta referenciado todas las funciones de la archivo C.

February 6, 2014
30 LaunchPad

/*
* Configuramos el ADC
* Pin1.0 -> Entrada Analoga
*/
ADC10CTL0 |= REFON + ADC10SHT_2 + ADC10ON; // ADC10ON
ADC10CTL1 |= INCH_0 + ADC10DIV_3; // input A0
delay(10);
ADC10AE0 |= 0x01; // PA.0 ADC option select
P1DIR |= BIT6; // Set P1.0 to output direction

Esa configuracin que se menciona arriba es para usar el P1.0 como entada anloga, como lo
hemos estado hacienda en los proyectos pasados, voy a explicar los registros concernientes a esta
configuracin.

ADC10CTL0

REFON = Prende el generado de referencia

ADC10SHT_2 = Tiempo de muestra y de mantenido para ADC

ADC10ON = Activamos el Convertidor Anlogo Digital

ADC10CTL1

INCH_0 = Seleccin de canal de entrada. En este caso A0

ADC10DIV_3= Divisor entre 3.

ADC10AE0 = Opcin de seleccin de ADC. En este caso el P1.0 como entrada analoga.

Configuracin de 10-bit

El Core ADC convierte una entrada anloga a su representacin de 10-bits y los deposita en el
registro ADC10MEM. El core usa dos niveles de voltaje programable/seleccionable (VR+ y VR-)
para definir el lmite mximo y mnimo de la conversin. La salida digital (NADC) es escala
completa 3FF (1024) cuando la seal de entrada es igual o mayor que VR+ y cero cuando la seal
es igual o menor que VR-. El canal de entrada y la referencia de nivel de voltaje (VREF+ y VR-) son
definidos en el control de conversn de memoria.

La frmula de conversin es:


= 1023
+

February 6, 2014
31 LaunchPad

El core de ADC10 es configurado por dos registros de control, ADC10CTL0 y ADC10CTL1. El core es
habilitado con el bit ADC10ON. Con algunas excepciones el control de bit del ADC10 puede solo
ser modificado cuando el ENC =0. ENC debe ponerse a 1 antes de cualquier conversion.

__bis_SR_register(GIE); // Habilitamos Interrupciones globales

puts_rom("Entrada Analoga P1.0\r\n");

while(1){

ADC10CTL0 |= ENC + ADC10SC; // Empieza la conversn


while(ADC10CTL1&ADC10BUSY)continue;
ADC10CTL0 &= ~ENC; // Detiene la conversin

sprintf(buffer_tx,"%u\r",ADC10MEM);
puts_ram(buffer_tx);

clear_buffers();
delay(100000);
}

El bit de GIE es establecido para habilitar todas las interrupciones globales, la interrupcin que
habilitamos es recepcin de datos por UART.
ADC10CTL0 |= ENC + ADC10SC; // Empieza la conversn

La lnea que se presenta es el registro para iniciar la configuracin de conversin del ADC

El bit ENC es el que habilita el ADC10, mientras el bit ADC10SC realiza a accin iniciar el muestreo y
conversin.
while(ADC10CTL1&ADC10BUSY)continue;

La siguiente lnea es la que espera si la conversin ha terminado, el bit es ADC10BUSY, y


simplemente deshabilitamos el bit ENC para que no empiece la conversin.

sprintf(buffer_tx,"%u\r",ADC10MEM);
puts_ram(buffer_tx);

Estas dos ltimas lneas nos permitir visualizar lo que es el valor ADC.

February 6, 2014
32 LaunchPad

El programa completo se presenta a continuacin:


/*
* Codigo para la comunicacion UART con Entrada Analoga
* Compaia: ucursos.blogspot.com
*/

#include <msp430g2553.h>
#include "Libraries/USCI_lib.h"
#include <stdio.h>

/*
* Definimos Variables Globales
*/

struct{
unsigned Rx:1;
unsigned dumy:7;
}Flags={0};

void delay(long d){


long t=d;
while(--t>0){_delay_cycles(1);}
}

/*
* Servicio de Interrupcion en Vector USCI_RX
*/
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
if(IFG2&UCA0RXIFG){

getchs(buffer_rx);

Flags.Rx=1;
}
}

/*
* main.c
*/
void main(void) {

WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

/*
* Se calibra la velocidad del cristal interno
* a 1 Mhz
*/
if(CALBC1_1MHZ == 0xFF || CALDCO_1MHZ == 0xFF){

February 6, 2014
33 LaunchPad

while(1);
}

BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;

/*
* Configuracion por defecto del Modulo Serial
* 9600,8,N,1
* Interrupcion Activada
*/
Init_USCI();

/*
* Configuramos el ADC
* Pin1.0 -> Entrada Analoga
*/
ADC10CTL0 |= REFON + ADC10SHT_2 + ADC10ON; // ADC10ON
ADC10CTL1 |= INCH_0 + ADC10DIV_3; // input A0
delay(10);
ADC10AE0 |= 0x01; // PA.0 ADC option select
P1DIR |= BIT6; // Set P1.0 to output direction

__bis_SR_register(GIE); // Habilitamos Interrupcione globales

puts_rom("Entrada Analoga P1.0\r\n");

while(1){

ADC10CTL0 |= ENC + ADC10SC; // Empieza la converson


while(ADC10CTL1&ADC10BUSY)continue;
ADC10CTL0 &= ~ENC; // Detiene la
conversion

sprintf(buffer_tx,"%u\r",ADC10MEM);
puts_ram(buffer_tx);

clear_buffers();
delay(100000);
}
}

February 6, 2014
34 LaunchPad

El diagrama es el siguiente:

Nota: No olvide cambiar los puentes para poder usar el serial.

February 6, 2014
35 LaunchPad

Proyecto # 5:

USCI: SPI
El microcontrolador MSP430G2553 contiene dos perifricos USCI del cual podemos configurarlos
en las tres maneras SPI, UART y I2C.

Lo que vamos a hacer en este proyecto es usar los dos USCI para configurar uno de ellos (AZUL) en
UART y el otro (ROJO) en modo SPI, para leer una memoria RAM expansible de la seria AT45DBXX.

AT45DBXX

February 6, 2014
36 LaunchPad

Este dispositivo es controlado va SPI, del cual debemos de configurar nuestro micro para trabajar
con este protocolo, y crear lo que es la librera para este mdulo.

Para dar una pequea introduccin al este dispositivo vamos a checar la hoja de datos:

El AT24DBXX es un interfaz de memoria flash serial idealmente para usarse en una gran variedad
de imagen, voz digital etc. El AT45DBXX soporta interfaz serial para aplicaciones para frecuencias
hasta 66Mhz. Su memoria est organizada en 2 048 pginas de 256 bytes o cada 256 bytes.

Configuracin de SPI.
/*
*Inicializamos SPI
*
*/
P1SEL |= BIT6 + BIT7 + BIT5;
P1SEL2 |= BIT6 + BIT7 + BIT5;
UCB0CTL1 |= UCSWRST;
UCB0CTL0 |= UCCKPL+UCMSB + UCMST + UCSYNC; // 3-pin, 8-bit SPI master
UCB0CTL1 |= UCSSEL_2 + UCSWRST; // SMCLK
UCB0BR0 = 2; // /2 = 500Khz
UCB0BR1 = 0; //
UCB0CTL1 &= ~UCSWRST; // **Initialize USCI state
machine**

PORTX|=CS;
delay(200);

Como hemos visto en el proyecto anterior del UART, lo primero que se configura es:
P1SEL |= BIT6 + BIT7 + BIT5;
P1SEL2 |= BIT6 + BIT7 + BIT5;

Se deshabilita la funciona del perifrico para configurar el USCI en modo SPI:


UCB0CTL1 |= UCSWRST;

Configuramos modo de 3 pines, 8 bits y Modo Maestro, trabajando con el Oscilador Maestro:
UCB0CTL0 |= UCCKPL+UCMSB + UCMST + UCSYNC;
UCB0CTL1 |= UCSSEL_2 + UCSWRST;

Despus debemos de establecer la frecuencia con respecto al oscilador que seleccionamos en el


paso anterior, MCLK = SMCLK = 1Mhz/2 = 500 Khz.
UCB0BR0 = 2; ///2 = 500Khz
UCB0BR1 = 0; ///

Habilitamos el perifrico SPI.


UCB0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**

February 6, 2014
37 LaunchPad

La funcin requerida para transmitir datos es la que se muestra a continuacin, en cada


transmisin alguna veces el dispositivo a controlar enviara una respuesta, esto depende de
controlador.

void SPI_Transmit(unsigned char _data){

UCB0TXBUF=_data;
while (!(IFG2 & UCB0RXIFG));
IFG2 &=~ UCB0RXIFG;

Y simplemente creamos las funciones de escritura y lectura para el dispositivo AT45DBXX, para la
escritura el dispositivo debe de enviarse lo siguiente:

void AT45DBXX_write(unsigned int _bufaddr,unsigned char _info){

PORTX&=~CS;
SPI_Transmit(0x84);
SPI_Transmit(0xff);
SPI_Transmit((unsigned char)(_bufaddr>>8));
SPI_Transmit((unsigned char)_bufaddr);
SPI_Transmit(_info);
PORTX|=CS;

Y para a lectura.

unsigned char AT24DBXX_read(unsigned int _bufaddr){

unsigned char temp;


PORTX&=~CS;
SPI_Transmit(0xD4);
SPI_Transmit(0xff);
SPI_Transmit((unsigned char)(_bufaddr>>8));
SPI_Transmit((unsigned char)_bufaddr);
SPI_Transmit(0xff);
SPI_Transmit(0xff);
temp=UCB0RXBUF;
PORTX|=CS;
IFG2 &=~ UCB0RXIFG;
return temp;
}

February 6, 2014
38 LaunchPad

Con las dos funciones de arriba nos permitir tener el acceso a la memoria RAM del chip, del cual
podemos hacer una prctica sencilla que solo que guarde los datos y despus leer la misma
cantidad y visualizarlos en el protocolo UART.

El programa completo se puede ver a continuacin:


#include <msp430G2553.h>
#include <stdio.h>
#include "Libraries/USCI_lib.h"
#include "Libraries/delay.h"

unsigned char index;


unsigned char value;

#ifndef PORTX
#define PORTX P2OUT
#endif

#define CS BIT0

void SPI_Transmit(unsigned char _data){

UCB0TXBUF=_data;
while (!(IFG2 & UCB0RXIFG));
IFG2 &=~ UCB0RXIFG;

void AT45DBXX_write(unsigned int _bufaddr,unsigned char _info){

PORTX&=~CS;
SPI_Transmit(0x84);
SPI_Transmit(0xff);
SPI_Transmit((unsigned char)(_bufaddr>>8));
SPI_Transmit((unsigned char)_bufaddr);
SPI_Transmit(_info);
PORTX|=CS;

unsigned char AT24DBXX_read(unsigned int _bufaddr){

unsigned char temp;


PORTX&=~CS;
SPI_Transmit(0xD4);
SPI_Transmit(0xff);
SPI_Transmit((unsigned char)(_bufaddr>>8));
SPI_Transmit((unsigned char)_bufaddr);
SPI_Transmit(0xff);
SPI_Transmit(0xff);
temp=UCB0RXBUF;
PORTX|=CS;

February 6, 2014
39 LaunchPad

IFG2 &=~ UCB0RXIFG;


return temp;
}

/*
* main.c
*/
void main(void) {

WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

/*
* Se calibra la velocidad del cristal interno
* a 1 Mhz
*/
if(CALBC1_1MHZ == 0xFF || CALDCO_1MHZ == 0xFF){
while(1);
}

BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;

/*
* Inicializamos I2C
*/

Init_USCI();

/*
* Inicializamos Pin p2.0 como salida
*/
P2DIR|=BIT0;

/*
*Inicializamos SPI
*
*/
P1SEL |= BIT6 + BIT7 + BIT5;
P1SEL2 |= BIT6 + BIT7 + BIT5;
UCB0CTL1 |= UCSWRST;
UCB0CTL0 |= UCCKPL+UCMSB + UCMST + UCSYNC; // 3-pin, 8-bit SPI master
UCB0CTL1 |= UCSSEL_2 + UCSWRST; // SMCLK
UCB0BR0 = 2; // /2 = 500Khz
UCB0BR1 = 0; //
UCB0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**

PORTX|=CS;
delay(200);

puts_rom("AT45DBXX Writing & Reading...\r");

February 6, 2014
40 LaunchPad

while(1){

puts_rom("Writing\r");
for(index=0;index<50;index++){
AT45DBXX_write((unsigned int)index,index);
puts_rom(".\n\r");
delay(1000);
}
puts_rom("Reading\r");
for(index=0;index<50;index++){
value=AT24DBXX_read((unsigned int)index);
sprintf(buffer_tx,"%u\r",value);
puts_ram(buffer_tx);
delay(1000);
}
clear_buffers();
while(1);
}
}

El diagrama a continuacin se da:

En este proyecto recuerde usar el UART usando los puentes requeridos en el launchpad.

February 6, 2014
41 LaunchPad

Proyecto # 6:

Interrupciones: Timer
En este proyecto vamos a usar las interrupciones por timer, el micro msp430 contiene varios
timers y pueden actuar diferente dependiendo de la configuracin que se halla configuracin:

El timer es un contador/temporizador de 16-bits con tres registros de comparador/captura. El


timer A puede soportar mltiples capturas/comparadores, salidas PWM e intervalos de tiempo.
Las interrupciones podran ser generadas desde el contador en condiciones de desbordamientos y
de cada registro de comparador/captura.

Las caractersticas del timer A incluyen:

El contador/temporizador asincrnico de 16 bits con cuatro modos de operacin.


Seleccionable y configurable fuente de reloj.
Dos o tres configurables registros de comparador/captura.
Salidas configurable con capacidad PWM.
Entrada y salida asncronas.
Registro de vector de interrupcin para rpida decodificacin de las interrupciones de
Timer A.

En este proyecto solo que vamos a implementar es realizar una interrupcin por desbordamiento
usando el timer A.

Para ello solo se requiere la siguiente lnea.


/*
* Configuramos el Timer A
* Master Clock como fuente principal de conteo
* Time= (1/TASSEL_2)*(2^16-TAR)
* Time= (1/1Mhz)*(65536-0)
* Time=65,536 mS
*/
TACTL = TASSEL_2 + MC_2 + TAIE;

Lo que hacemos en el registro del timer A es configurar que la fuente del reloj a usar, en este caso
usaremos el SMCLK poniendo a 1 el bit TASSEL_2, ahora bien hay que indicarle que se usara en
modo continuo (contador hasta 0FFFFh) y por ultimo solo se establece la interrupcin.

February 6, 2014
42 LaunchPad

La funcin de vector de interrupcin es la siguiente:


#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer_A(void)
{
switch( TA0IV )
{
case 2: break; // CCR1 not used
case 4: break; // CCR2 not used
case 10:
P1OUT ^= 0x01; // overflow
break;
}
}

Para entender mejor el registro de TA0IV , las banderas TACCR1 CCIFG,TACCR2 CCIFG estn
priorizadas y combinadas para correr un simple vector de interrupcin. El registro de vector de
interrupcin TAIV es usado para determinar cul interrupcin es activada. La prioridad habilitada
ms alta de interrupcin genera un nmero en el registro TAIV. Este nmero puede ser evaluado o
adherido al programa de conteo para automticamente entrar a la rutina apropiada.

Deshabilitando la interrupcin de TIMER 1 no afecta al valor TAIV. Cualquier acceso, lectura o


escritura, del registro TAIV automticamente resetea la bandera de interrupcin mas alta y la pone
en pendiente.

February 6, 2014
43 LaunchPad

El programa completo es el siguiente:


#include <msp430g2553.h>

#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer_A(void)
{
switch( TA0IV )
{
case 2: break; // CCR1 not used
case 4: break; // CCR2 not used
case 10:
P1OUT ^= 0x01; // overflow
break;
}
}

/*
* main.c
*/
void main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

/*
* Se calibra la velocidad del cristal interno
* a 1 Mhz
*/
if(CALBC1_1MHZ == 0xFF || CALDCO_1MHZ == 0xFF){
while(1);
}

BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;

/*
* Configuramos P1.0 como salida
*/
P1DIR=0x01;
P1OUT|=BIT0;

/*
* Configuramos el Timer A
* Master Clock como fuente principal de conteo
* Time= (1/TASSEL_2)*(2^16-TAR)
* Time= (1/1Mhz)*(65536-0)
* Time=65,536 mS
*/
TACTL = TASSEL_2 + MC_2 + TAIE;

_bis_SR_register(LPM0_bits + GIE);

while(1);

February 6, 2014
44 LaunchPad

El diagrama es solo usar el launchpad en si para poder simular el ejemplo.

Muy pronto ver mas funcionalidades con los MSP430 y creare ms manuales al respecto, por
ahora usted con estos ejemplos podr tener el inicio para empezar a programar estos
microcontroladores de Texas Intruments

Atte. Jorge Rdz

Pgina: ucursos.blogspot.com

February 6, 2014

You might also like