Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Ejercicios Con MSP430F2013
Ejercicios Con MSP430F2013
Primero nos pedir que seleccionemos una carpeta en la cual se guardarn todos los proyectos que realizamos.
3. Escribimos el nombre del proyecto que queramos darle y seleccionamos el botn next
4. Ahora dejamos las opciones como se ven en la siguiente figura y seleccionamos next
5. Para esta ventana, dejamos todo como esta y seleccionamos al botn next
Incluyendo archivos .c y .h en CCS Para poder incluir archivos en nuestro proyecto, es muy sencillo, solo tenemos que seleccionar nuestra carpeta, y presionar el botn secundario del ratn.
Seleccionamos Source file para crear nuestro archivo main.c, cabe mencionar que cuando queramos incluir archivos de cabecera solo tenemos que seleccionar header file.
A partir de aqu, solo tenemos que empezar a escribir nuestro programa. Cmo compilar mi proyecto? Para compilar nuestro proyecto, solo tenemos que seleccionar Project->Build Project
Cmo programar el microcontrolador una vez que ya haya terminado mi programa? Solamente tenemos que presionar el botn que aparece encerrado en el crculo rojo en la figura:
A continuacin nos aparece un cambio de opciones en la pantalla, que nos permitirn hacer un debug en tiempo real, checando valores de variables, memoria, registros y lnea del programa.
En la pantalla podemos ver varios iconos que nos demuestran cuales son las herramientas que nos ofrece este excelente compilador:
Run: Este botn es para arrancar el programa Pause: para pausar el programa en tiempo real Terminate: para terminar el debug Step Into: Una vez que hemos seleccionado Pause, podemos ir recorriendo nuestro programa lnea por lnea, entrar a funciones, etc. Step Into (ensamblador): estos botones sirven para cuando queremos hacer un step para a un nivel de instruccin en ensamblador. Step Return: Este comando sirve, para cuando queremos salir de alguna funcin en la cual est el compilador corriendo en steps.
void main(void) { WDTCTL = WDTPW + WDTHOLD; P1DIR |= 0x01; for (;;) { volatile unsigned int i; P1OUT ^= 0x01; i = 50000; do (i--); while (i != 0); } }
Explicacin Aqu podemos ver un sencillo ejemplo, en el cual el objetivo en encender y apagar un led, el puerto P1.0
WDTCTL
PXDIR
Este registro, sirve para determinar si queremos el puerto como entrada o salida:
P1DIR |= 0x01;
Con esta orden, lo que hacemos es poner el pin 0 del Puerto 1 como salida, al escribir en el registro el valor hexadecimal 0x01.
PXOUT1
Este registro sirve para poner el estado lgico en el puerto como salida:
P1OUT ^= 0x01;
Que se realiza con esta orden? _________________________________________________________________________ _________________________________________________________________________ _________________________________________________________________________ Existe alguna otra forma de realizar la misma orden? _________________________________________________________________________ _________________________________________________________________________ _________________________________________________________________________ _________________________________________________________________________
// Stop watchdog timer // Set P1.0 to output direction // Test P1.4 // if P1.4 set, set P1.0 // else reset
while (1) { if ((0x10 & P1IN)) P1OUT |= 0x01; else P1OUT &= ~0x01; } }
En la condicin:
if ((0x10 & P1IN)) P1OUT |= 0x01; // if P1.4 set, set P1.0 else P1OUT &= ~0x01; // else reset
Con la condicin: if(P1IN==0x10) P1OUT=0x01; else P1OUT=0x00; Se hace lo mismo que en la anterior condicin y por qu?
void main(void) { WDTCTL = WDTPW + WDTHOLD; P1DIR = 0x01; P1OUT = 0x10; P1REN |= 0x10; P1IE |= 0x10; P1IES |= 0x10; P1IFG &= ~0x10; _BIS_SR(LPM4_bits + GIE); } // Port 1 interrupt service routine #pragma vector=PORT1_VECTOR __interrupt void Port_1(void) { P1OUT ^= 0x01; P1IFG &= ~0x10; }
// Stop watchdog timer // P1.0 output, else input // P1.4 set, else reset // P1.4 pullup // P1.4 interrupt enabled // P1.4 Hi/lo edge // P1.4 IFG cleared // Enter LPM4 w/interrupt
El circuito, es el mismo que se uso en la practica anterior. En este ejemplo, utilizamos por primera vez la interrupcin para detectar la entrada de una seal positiva. Para esto utilizamos la directiva:
// Port 1 interrupt service routine #pragma vector=PORT1_VECTOR __interrupt void Port_1(void)
{ P1OUT ^= 0x01; P1IFG &= ~0x10; } // P1.0 = toggle // P1.4 IFG cleared
Al declarar #pragma vector= PORT1_VECTOR direccionamos la funcin _interrupt void Port_1(void) para que cada vez que detecte un pulso en la entrad 1.4 el led se encienda o apague segn sea el caso. En el registro P1IFG limpiamos la bandera para que se salga de la interrupcin, de lo contrario jams saldramos de la funcin, ocasionando un ciclo infinito en la funcin de interrupcin.
P1IFG &= ~0x10;
Cada puerto P1 y P2 tienen interrupciones, configuradas con los registros PxIFG. PxIE, y PxIES. Todos los pines P1 llaman a un solo vector de interrupcin, y todos los pines del puerto P2 tienen otro vector de interrupcin. El registro PxIFG puede ser verificado para saber el estado de la interrupcin.
#include
<msp430f2013.h>
void delay(void){ volatile unsigned int i; for(i=0;i<80000;i++); } void main(void) { WDTCTL = WDTPW + WDTHOLD; P1DIR |= 0x0F; direction for (;;) { P1OUT = 0x00; delay(); P1OUT = 0x01; delay(); P1OUT = 0x02; delay(); P1OUT = 0x04; delay();
} }
Realiza un programa que despliegue una secuencia en leds dependiendo del valor de dos botones:
#include
<msp430f2013.h>
unsigned char flag_secuencia1, flag_secuencia2; void delay(void){ volatile unsigned int i; for(i=0;i<80000;i++); } void secuence(unsigned char value){ if(!value){ P1OUT = 0x00; delay(); P1OUT = 0x01; delay(); P1OUT = 0x02; delay(); P1OUT = 0x04; delay(); }else{ P1OUT = 0x04; delay(); P1OUT = 0x02; delay(); P1OUT = 0x01; delay(); P1OUT = 0x00; delay(); } }
void main(void) { WDTCTL = WDTPW + WDTHOLD; P1DIR |= 0x0F; P1REN |= 0x30; P1IE |= 0x30; P1IES |= 0x30; P1IFG &= ~0x30; flag_secuencia1=0; flag_secuencia2=0; for (;;) { if(flag_secuencia1){ secuence(0); flag_secuencia1=0; } if(flag_secuencia2){ secuence(1); flag_secuencia2=0; } } }
// Stop watchdog timer // Set P1.0 to P1.3 to output direction // P1.4 P1.5 pullup // P1.4 P1.5 interrupt enabled // P1.4 P1.5 Hi/lo edge
// Port 1 interrupt service routine #pragma vector=PORT1_VECTOR __interrupt void Port_1(void) { if(!(0x10 & P1IN)){ flag_secuencia1=1; } if(!(0x20 & P1IN)){ flag_secuencia2=1; } P1IFG &= ~0x30; } // P1.4 IFG cleared
Realiza un programa que utilice un display de 7 segmentos e incremente cada determinado tiempo automticamente.
El display de 7 segmentos se conforma de 7 leds que conforman un nmero del 1 al 9, se usan frecuentemente en dispositivos de medicin.
La tabla de valores que debemos de tener para desplegar en nuestro puerto 1 es el siguiente: Nmero Codificacin 1 2 B,C A,B,G,E,D Valor Hexadecimal (ctodo Comn) 0x06 0x5b Valor Hexadecimal (nodo Comn) 0xf9 0xa4
3 4 5 6 7 8 9 0
Entonces, como ya sabemos los valores que tenemos que imprimir para que se despliegue el nmero deseado, pasamos a la programacin:
#include <msp430f2013.h>
int valor=0; const unsigned char display[10]={0x40,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; void delay(void){ volatile unsigned int i; for(i=0;i<40000;i++); } void main(void) { WDTCTL = WDTPW + WDTHOLD; P1DIR = 0xFF; for(;;){ P1OUT=display[valor]; valor++; if(valor>9)valor=0; delay(); } }
Realice un programa que incremente el contador en el display de 7 segmentos cuando no se est presionando el botn, cuando se mantenga presionado, se decrementar el contador.
Respuesta:
Como nos explica este articulo, existen tres fuentes de reloj que necesitamos alimentar, ACLK, MCLK y SMCLK. La primera es para obtener la frecuencia de un cristal de 32.768 KHz, la segunda es la frecuencia que alimentar las ejecuciones de reloj del CPU y por ltimo, la frecuencia que suministrar de pulsos a los perifricos del microcontrolador como son ADC, IO, SPI, etc.
El microcontrolador MSP430 est diseado para aplicaciones de ultrabajo consumo, y se puede utilizar en diferentes tipos de operacin de bajo consumo.
BCSCTL3
BCSCTL2
IFG1
REGISTER SR
EJERCICIO #2 (VLO)
#include
<msp430x20x3.h>
void main(void) { volatile unsigned int i; WDTCTL = WDTPW + WDTHOLD; BCSCTL3 |= LFXT1S_2; IFG1 &= ~OFIFG; __bis_SR_register(SCG1 + SCG0); BCSCTL2 |= SELM_3 + DIVM_3; P1DIR = 0xFF; P1OUT = 0; P2DIR = 0xFF; P2OUT = 0; for (;;) { P1OUT |= for (i = P1OUT &= for (i = } }
// // // // // // // // // //
Volatile to prevent removal Stop watchdog timer LFXT1 = VLO Clear OSCFault flag Stop DCO MCLK = LFXT1/8 All P1.x outputs All P1.x reset All P2.x outputs All P2.x reset
// // // //
Para poder configurar el reloj en bajo consumo, en el programa se escriben los siguientes registros:
BCSCTL3 |= LFXT1S_2; IFG1 &= ~OFIFG; __bis_SR_register(SCG1 + SCG0); BCSCTL2 |= SELM_3 + DIVM_3; // LFXT1 = VLO // Clear OSCFault flag // Stop DCO // MCLK = LFXT1/8
Recordemos que el registro BCSCTL3 sirve para configurar la velocidad de reloj, as que al poner una operacin OR de lo que contiene, ms lo que se define como LFXT1S_2, seleccionamos:
La opcin VLO en el microcontrolador MSP430 es el oscilador interno, con una frecuencia normal de 12KHz, aqu podemos ver algunas de sus especificaciones:
En la siguiente lnea, se configura el registro IFG1, lo cual la nica tarea que hace, es limpiar la bandera de la interrupcin del oscilador interno. En la lnea: __bis_SR_register(SCG1 + SCG0); Configuramos el registro SR para que pongamos a 1 los bits SCG1 y SCG2 para poder apagar el DCO (digitally controlled oscillator) que permite despertar al microcontrolador de un estado de sueo en tan solo 1us.
Es as, como se elige en SELM_3 trabajar con el oscilador interno y con DIVM_3 tenemos una frecuencia de 12KHz dividida entre 8, que es igual a 1.5KHz de frecuencia de trabajo. En qu modo de operacin se encuentra el microcontrolador con los registros SELM_3 y DIVM_2? ___________________________________________________________________
EJERCICIO #3 (DCO)
#include <msp430f2013.h>
void main(void) { WDTCTL = WDTPW +WDTHOLD; // Stop Watchdog Timer if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF) { while(1); // If calibration constants erased // do not load, trap CPU!! } //1Mhz BCSCTL1 = CALBC1_1MHZ; // Set range DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation */ /* //8Mhz BCSCTL1 = CALBC1_8MHZ; DCOCTL = CALDCO_8MHZ; modulation */ /* //12Mhz BCSCTL1 = CALBC1_12MHZ; DCOCTL = CALDCO_12MHZ; modulation*/ /* //16Mhz BCSCTL1 = CALBC1_16MHZ; DCOCTL = CALDCO_16MHZ; modulation*/ P1DIR |= 0x13; P1SEL |= 0x11; while(1) { P1OUT |= 0x01; P1OUT &= ~0x01; } }
// P1.1 = 1 // P1.1 = 0
EJERCICIO #3 (LFxTAL)
#include <msp430x20x3.h> volatile unsigned int i; void main(void) { WDTCTL = WDT_ADLY_1000; IE1 |= WDTIE; P1DIR = 0xFF; P1OUT = 0; P2DIR = 0xFF; P2OUT = 0; // An immedate Osc Fault will occur next IE1 |= OFIE; while(1) { P1OUT ^= 0x01; _BIS_SR(LPM3_bits + GIE); } } #pragma vector=WDT_VECTOR __interrupt void watchdog_timer (void) { _BIC_SR_IRQ(LPM3_bits); // Clear LPM3 bits from 0(SR) } #pragma vector=NMI_VECTOR __interrupt void nmi_ (void) { do { IFG1 &= ~OFIFG; // Clear OSCFault flag for (i = 0xFFF; i > 0; i--); // Time for flag to set P1OUT ^= 0x01; // Toggle P1.0 using exclusive-OR } while (IFG1 & OFIFG); // OSCFault flag still set? IE1 |= OFIE; // Enable Osc Fault }
// // // // // //
WDT 1s interval timer Enable WDT interrupt All P1.x outputs All P1.x reset All P2.x outputs All P2.x reset
En este ejercicio podemos notar que por primera vez utilizamos el watchdog, y habilitamos una interrupcin en el registro IE1.
IE1
En la informacin aparece que debemos de utilizar una forma especial para cargar informacin en el registro, mencionan como hacerlo para ensamblador, en c se hace con una operacin OR.
IE1 |= WDTIE;
Esto quiere decir que estamos cargando el registro IE1 con el estado del bit de la interrupcin de watchdog para poder habilitar la interrupcin.
En la parte de:
WDTCTL = WDT_ADLY_1000;
Con la sentencia _BIS_SR(LPM3_bits + GIE); Entramos al modo de bajo consumo LPM3, con esta accin, el microcontrolador entrar en un modo de suspensin y bajo consumo, y solo se despertar cuando suceda alguna interrupcin. Como puede ser la interrupcin de cada 1 segundo del watchdog. En las siguientes sentencias, vemos varias interrupciones, estas se declaran de esta forma: #pragma vector=WDT_VECTOR __interrupt void watchdog_timer (void) { _BIC_SR_IRQ(LPM3_bits); // Clear LPM3 bits from 0(SR) } Cada vez que se cumple el segundo, se repite esta funcin, la cual limpia la bandera del modo LPM3 y as el CPU vuelva a despertar, lo cual har que parpadee el led que est conectado al pin de salida. Esto lo hacemos con una operacin en ensamblador: _BIC_SR_IRQ(LPM3_bits); // Clear LPM3 bits from 0(SR)
// ACLK/4 // WDT 1s/4 interval timer // Enable WDT interrupt // All P1.x outputs // All P1.x reset // All P2.x outputs // All P2.x reset
// // // //
Set P1.0 LED on Delay Reset P1.0 LED off Enter LPM3
El periferico SD16 es un convertidor analogico digital de 16 bits. Este modulo de conversin tipo sigma delta con alta impedancia a la entrada.
#include
<msp430f2013.h>
void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer P1DIR |= 0x01; // Set P1.0 to output direction SD16CTL = SD16REFON + SD16SSEL_1; // 1.2V ref, SMCLK SD16INCTL0 = SD16INCH_1; // A1+/SD16CCTL0 = SD16UNI + SD16IE; // 256OSR, unipolar, interrupt enable SD16AE = SD16AE2; // P1.1 A1+, A1- = VSS SD16CCTL0 |= SD16SC; // Set bit to start conversion _BIS_SR(LPM0_bits + GIE); } #pragma vector = SD16_VECTOR __interrupt void SD16ISR(void) { if (SD16MEM0 < 0x7FFF) P1OUT &= ~0x01; else P1OUT |= 0x01; }