Вы находитесь на странице: 1из 36

HOJA

 DE  EJERCICIOS  (curso  2014/15)  


1. Realizar  un  programa  en  ensamblador  para  que  parpadee  el  bit  P1.0,  utilizando  un  bucle  para  realizar  el  retardo.  

SOLUCIÓN:  

;*************************************************************
; Plantilla que se crea automáticamente
; Conviene especificar el microcontrolador usado, describir
; el programa y si fuera posible las patillas utilizadas
; Microcontrolador: MSP430G2553
; Descripción:
; MSP430G2553
; -----------------
; /|\| XIN|-
; | | |
; --|RST XOUT|-
; | |
; | P1.0|-->LED
;
; Autor:
; Empresa: UA
; Fecha: 07/07/14
; Herramienta: IAR Embedded Workbench Version: 5.51
;*************************************************************
#include "msp430g2553.h"
miSP EQU 0x400 ; define el puntero de la Pila
ORG 0FC00h ; inicio del programa en memoria
;-----------------------------------------------------------
RESET
MOV.W #miSP,SP ; Inicializa el SP
MOV.W #WDTPW+WDTHOLD,&WDTCTL ; para el watchdog

BIS.B #001h,&P1DIR ; el bit P1.0 como salida

INICIO
XOR.B #001h,&P1OUT ; Conmuta el bit P1.0
MOV.W #050000,R15 ; R15=50000 para realizar un retardo
L1 ; se realiza 50000 veces el bucle L1
DEC.W R15 ; Decrementando R15
JNZ L1 ; retardo=(1+2)*50000=150000T
JMP INICIO ; vuelve a empezar

;--------------------------------------------
; VECTORES
;--------------------------------------------
ORG 0FFFEh
DW RESET
END
 
 

 
 
 
1   Sistemas  Electrónicos  Digitales    
HOJA  DE  EJERCICIOS  (curso  2014/15)  
2. Realizar  un  programa  en  C  para  que  parpadee  el  bit  P1.0,  utilizando  un  bucle  para  realizar  el  retardo.  

SOLUCIÓN:  

//*************************************************************
#include <msp430.h>

int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Para el watchdog
P1DIR |= 0x01; // Configura P1.0 como salida direction

for (;;)
{
volatile unsigned int i;
P1OUT ^= 0x01; // Conmuta P1.0 usando la XOR

i = 50000; // Retardo
do (i--);
while (i != 0);
}
}  

3. Realizar  un  programa  en  C  que  haga  parpadear  el  bit  P1.6,  utilizando  la  función  __delay_cicles(nº  ciclos)  

SOLUCIÓN:  

/*
Enciende el led verde P1.6
Utilizando __delay_cicles()
*/

#include <msp430.h> //inclusiones.


#include <inttypes.h>

void main(){ //funcion principal

WDTCTL= WDTPW+WDTHOLD; //Apagamos el watchdog

P1SEL= 0x00;
P1DIR|= BIT6; //Salida el bit 6 del puerto 1

P1OUT|=BIT6; //LED parte apagado

while(1){ //Loop infinito


P1OUT|=BIT6; //prende el LED
__delay_cycles(100000); //espera
P1OUT&=~BIT6; //apaga el LED
__delay_cycles(100000); //espera
}
}

2   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
4. Escribe   un   programa   en   lenguaje   ensamblador   en   el   cual   inicialmente   el   bit   P1.6   esté   apagado,   cuando   se   pulse   el  
botón  colocado  en  P1.3  se  ponga  a  uno  el  bit  P1.6  y  si  se  vuelve  a  pulsar  que  se  apague.  Esto  se  debe  realizar  de  
forma  indefinida.  

SOLUCIÓN:  

;********************************************************************
#include "msp430g2553.h"
;------------------------------------------------------
ORG 0FC00h ; Definimos la direccion de inicio
;------------------------------------------------------
RESET MOV.W #0400h,SP ; Establecemos el SP
MOV.W #WDTPW+WDTHOLD,&WDTCTL ; Detenemos el watchdog timer
MOV.B #040h,&P1DIR ; Colocamos P1.6 salida resto entrada
MOV.B #00h,&P1OUT
BIS.B #BIT3, &P1REN ; Resistencia en la entrda P1.3
BIS.B #BIT3, &P1OUT ; Resistencia de pull-up
SIGUE
BIT.B #BIT3, &P1IN ;  si pulsado 0000 1000 AND XXXX 0XXX
JZ ENCIENDE ; si pulsado salta y enciende P1.6
JMP APAGA
JMP SIGUE
APAGA
BIC.B #BIT6,&P1OUT
JMP SIGUE

ENCIENDE
BIS.B #BIT6,&P1OUT
JMP SIGUE
;------------------------------------------------------
; Vectores Interrupción
;------------------------------------------------------
ORG 0FFFEh ; Vector RESET MSP 430
DW RESET ;
END  

3   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
5. Escribe   un   programa   en   lenguaje   C   en   el   cual   inicialmente   el   bit   P1.6   esté   apagado,   cuando   se   pulse   el   botón  
colocado  en  P1.3  se  ponga  a  uno  el  bit  P1.6  y  si  se  vuelve  a  pulsar  que  se  apague.  Esto  se  debe  realizar  de  forma  
indefinida.  

SOLUCIÓN:  

#include <msp430g2553.h>

int i;

void main(void) {

WDTCTL = WDTPW + WDTHOLD; // para el watchdog

P1OUT &= ~0x40; // P1.6 a cero


P1DIR |= 0x40; // P1.6 (LED) como salida
P1DIR &= ~0x08; // P1.3 (push button) como entrada
P1REN |= 0x08; // P1.3 (botón) resistencia habilitada
P1OUT |= 0x08; // P1.3 (botón) resistencia pull-up

while (1){

if( BIT3 & ~P1IN ) { // Si se pulsa botón


P1OUT ^= 0x40; // led encendidO
}
}
}  

6. Añade  un  antirrebotes  al  ejercicio  3  

7. Añade  un  antirrebotes  al  ejercicio  4  

8. Supongamos   que   la   ejecución   normal   del   programa   consiste   en   el   desplazamiento   de   un   bit,   empezando   en   el  
P2.0,  después  se  encenderá  el  P2.0  y  el  P2.1,  después  el  P2.0,  P2.1  y  P2.2,  así  sucesivamente  hasta  llega  al  P2.7,  
que   vuelve   a   empezar.   Si   en   el   bit   P1.3   hay   un   flanco   de   bajada   se   debe   atender   la   interrupción   ejecute   el  
correspondiente  servicio  (ISR)  que  deberá    sacar  por  P2  la  siguiente  secuencia:  

 secu            DC8            00000001b,00000010b,00000100b,00001000b  

  DC8            00010000b,00100000b,01000000b,10000000b  

                    DC8            00000000b,11111111b,00000000b,11111111b  

                  DC8            00000000b,11111111b,00000000b,11111111b  

Finsecu    DC8            01010101b  

Cuando   se   encuentre   el   valor   01010101b   se   debe   salir   de   la   interrupción   y   continuar   por   donde   iba.   Escribir   el  
programa  en  ensamblador  
4   Sistemas  Electrónicos  Digitales    
HOJA  DE  EJERCICIOS  (curso  2014/15)  

;-----------------------------------------------------
#include "msp430g2553.h"
#define miSP 0x400

main
;--------------------------------------------------------------------------------
ORG 0xFC00 ;Inicio del programa
;--------------------------------------------------------------------------------
RESET
MOV.W #miSP,SP ; Inicia SP
MOV.W #WDTPW+WDTHOLD,&WDTCTL ; Detiene WD
;----------------------esto es opcional para conseguir la frecuencia------------
MOV.B &CALDCO_1MHZ, &DCOCTL ; calibra la f a 1MHz
MOV.B &CALBC1_1MHZ, &BCSCTL1 ; calibra la f a 1MHz
;--------------------------------------------------------------------------------
BIC.B #BIT3, &P1DIR ; P1.3 IN #11110111b
BIS.B #BIT3, &P1OUT ; P1.3 Resist pullup, resto a cero 00001000b
BIS.B #BIT3, &P1REN ; P1.3 Resist pullup habilitada

BIS.B #BIT3, &P1IES ; flanco de bajada para P1.3


BIC.B #BIT3, &P1IFG ; borrar flags de interrup para P1.3
BIS.B #BIT3, &P1IE ; interrup locales habilita para P1.3
EINT ; GIE <--1
MOV.B #0xFF,&P2DIR ; P2 como salida 11111111b
;------------------------------------------------------------------
; PROGRAMA PRINCIPAL EN EJECUCIÓN
;------------------------------------------------------------------
MOV.B #00h,&P2SEL ; obligatorio para que P2.6 y P2.7 sean salida
sigue MOV.B #00h,&P2OUT ; apagamos los diodos
MOV.W #00010h,R14 ; R14 y R15 para pasar parámetros
MOV.W #020000,R15 ; R14 y R15 para pasar parámetros
CALL #retardo ; que se note que se apagan todos
SETC ; C <-- 1
MOV.B #00h, R7 ; R7 <-- 0000 0000
vuelta
RLC.B R7 ; rotar R7 a la izda incluido C
MOV.B R7,&P2OUT ; P2.0 a P2.7 pone ceros, apaga,
MOV.W #0005h,R14 ; R14 y R15 para pasar parámetros
MOV.W #025000,R15 ; R14 y R15 para pasar parámetros
CALL #retardo
MOV.B R7,R8 ; R7 --> R8 para saber si he terminado
XOR.B #0FFh,R8 ; averigua si se han apagado P2.0 a P2.7
JZ sigue ; si es así, volvemos a empezar
JMP vuelta ; si no, se continua rotando

5   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  

;---------------------------------------------------------------------
P1_3_ISR; Rutina de servicio a la interrupción
;---------------------------------------------------------------------
PUSH R7
PUSH R8
PUSH R11
PUSH R12
MOV #secu,R5 ; Asigna a la secu1 el puntero (R5)
ETQ1
MOV.B @R5+,&P2OUT
MOV.W #7,R14 ; R14 y R15 para pasar parámetros
MOV.W #25000,R15 ; a la subrutina retardo
CALL #retardo
CMP Finsecu,0(R5)
JNE ETQ1
BIC.B #BIT3,&P1IFG ; Borra la flag de la interrupción
POP R12
POP R11
POP R8
POP R7
RETI
;----------------------------------------------------------------------------
retardo
;----------------------------------------------------------------------------
MOV R14,R11 ; Valores del retardo
b2 MOV R15,R12 ; se pueden ajustar
b1 DEC.W R12 ; bucle fino R12
JNZ b1
DEC.W R11 ; bucle grueso
JNZ b2
RET
;-----------------------------------------------------
; Definicion de las secuencias
;-----------------------------------------------------
secu DC8 00000001b,00000010b,00000100b,00001000b
DC8 00010000b,00100000b,01000000b,10000000b
DC8 00000000b,11111111b,00000000b,11111111b
DC8 00000000b,11111111b,00000000b,11111111b
Finsecu DC8 01010101b
;---------------------------------------------------------------------
; Vectores de Interrupción y Reset
;---------------------------------------------------------------------
ORG 0FFFEh ; Vector para el reset
DW RESET
ORG 0FFE4h ; Vector para la interrupción del P1
DW P1_3_ISR
END main

6   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
 

9. Supongamos   que   la   ejecución   normal   del   programa   consiste   en   el   desplazamiento   de   un   bit,   empezando   en   el  
P2.0,  después  se  encenderá  el  P2.0  y  el  P2.1,  después  el  P2.0,  P2.1  y  P2.2,  así  sucesivamente  hasta  llega  al  P2.7,  
que   vuelve   a   empezar.   Si   en   el   bit   P1.3   hay   un   flanco   de   bajada   se   debe   atender   la   interrupción   ejecute   el  
correspondiente  servicio  (ISR)  que  deberá    sacar  por  P2  la  siguiente  secuencia:  

 secu            DC8            00000001b,00000010b,00000100b,00001000b  

  DC8            00010000b,00100000b,01000000b,10000000b  

                    DC8            01000000b,00100000b,00010000b,00001000b  

                  DC8            00000100b,00000010b,00000001b,00000000b  

  DC8            11111111b,00000000b,  11111111b,00000000b  

Finsecu    DC8            01010101b  

Cuando   se   encuentre   el   valor   01010101b   se   debe   salir   de   la   interrupción   y   continuar   por   donde   iba.   Esrcribir   el  
programa  en  C  

SOLUCIÓN:  

7   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  

#include <msp430.h>
char secu[21] = {0x01,0x02,0x04, 0x08,0x10,0x20,0x40,0x80,
0x40,0x20, 0x10, 0x08,0x04,0x02,0x01};

char secu_interrup[24] = {0x01,0x03,0x07, 0x0F,0x1F,0x3F,0x7F,0xFF,


0x7F,0x3F, 0x1F, 0x0F,0x07,0x03,0x01,0x00,0xFF,0x00,
0xFF,0x00,0xFF,0x00,0xFF,0x00};
int i,r,j;

// Rutina de Retardo
void RETARDO(void)
{r = 20000;
do (r--);
while (r != 0);
}

void main(void) {
WDTCTL = WDTPW + WDTHOLD; // para el watchdog
DCOCTL = CALDCO_1MHZ; //calibra la f a 1MHz
BCSCTL1 = CALBC1_1MHZ;
// configuración de los puertos
P2SEL &= ~0xFF; // P2 como I/O general (GPIO)
P2DIR |= 0xFF; // P2 como salida
P1DIR &= ~0x08; // P1.3 (push button) como entrada
P1REN |= 0x08; // P1.3 (botón) resistencia habilitada
P1OUT |= 0x08; // P1.3 (botón) resistencia pull-up
// configuración de la interrupción de P1.3
P1IES |= 0x08; // flanco de bajada para P1.3
P1IFG &= ~0x08; // borrar flags de interrup para P1.3
P1IE |= 0x08; // interrup locales habilita para P1.3
_BIS_SR(GIE); // GIE <--1
// __enable_interrupt(); // equivalente a la anterior, se debe cambiar
// msp430.h por <io430.h>

while(1)
for (i = 0; i <15 ; i++)
{

if( BIT3 & P1IN ){ // Si NO se pulsa botón


P2OUT = secu[i];
RETARDO();
}
}
}

//-----------------------------------------------------
// Rutina de atención de interrupción del puerto P1
//-----------------------------------------------------
#pragma vector=PORT1_VECTOR
__interrupt void P1_Interrupt(void)
{
for (j = 0; j <24 ; j++)
{
P2OUT = secu_interrup[j];
RETARDO();
}
P1IFG &= ~BIT3; // Reseta IFG para P1.3
}

 8   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
 

10. El   circuito   de   la   figura   tiene   el   μC   alimentado   a   3,3V,   y   los   displays   de   7   segmentos   son   de   cátodo   común.  
Encenderemos   los   segmentos   mediante   los   bits   del   P1   y   seleccionamos   el   que   debe   encenderse   mediante   el  
P2(P2.0  y  P2.1).    Calcula  el  valor  de  las  resistencias  R1  y  R2,  sabiendo  que:  

ILED=5mA;      VLED=1,8V  

 VCEsat=0,2V;  β=  200  

La   corriente   proporcionada   por   cada   patilla   de   un   puerto   de   salida   debe   estar   entre   4   y   5   mA   como   máximo   y     la  
corriente  máxima  que  debe  proporcionar  un  puerto  en  conjunto  no  debe  exceder  de  los  25  mA.  

Fig.1  circuito    
 

SOLUCIÓN:  

R1=300Ω  ≅330Ω    ;  R2=21600Ω  ≅22KΩ    

11. Escribir  un  programa  en  C  para  el  circuito  del  problema  anterior.  Al  pulsar  el  botón  se  iniciará  la  cuenta  de  0  a  99  
con  un  periodo  aproximado  de  1s.  El  pulsador  solicita  una  interrupción  en  P1.3  por  flanco  de  bajada  

9   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
 

#include <msp430g2553.h>
unsigned int r, i, j;
char display[10] = {0x77,0x06,0xB3, 0x97,0xC6,0xD5,0xF5,0x07,0xF7,0xC7};
//gfedcba -> p1.7,6,5,4,2,1,0
// Rutina de Retardo
void RETARDO(void)
{r = 200;
do (r--);
while (r != 0);
}
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Paramos el WDT
BCSCTL1 = CALBC1_1MHZ; // Y establecemos una frecuencia
DCOCTL = CALDCO_1MHZ; // de un 1MHz
P1DIR = 0xF7; // P1.3 como entrada, resto como salidas
P2DIR = BIT0+BIT1; // P2.0 y P2.1 como salidas
P1OUT = BIT3; // resitencia pull-up
P1REN = BIT3; // P1.3 con resistencia de pullup
P1IE = BIT3; // P1.3 con interrupción habilitada
P1IES = BIT3; // y activa por flanco de bajada
_BIS_SR(LPM0_bits + GIE); // Habilita interrupciones y deshabilita la CPU y MCLK
}
#pragma vector=PORT1_VECTOR // Rutina de servicio para la interrupción del P1
__interrupt void Port_1(void) // forma de llamar a la ISR del P1
{
i = 0;
j = 0;
for (j = 0; j < 10; j++)
{
for (i = 0; i < 10; i++)
{
int k;
for (k=0; k< 100; k++)
{
P1OUT = display[i]; // Pone el número en P1
P2OUT = 0x01; // Y activa el display de las unidades
RETARDO();
P1OUT = display[j]; // Pone el otro número en P1
P2OUT = 0x02; // Y activa el display de las decenas
RETARDO();
}
}
}
P2OUT = 0x03; // deja activos los dos displays
P1IFG &= ~0x08; // borra el flag de petición de interrupción
}  

10   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
12. Escribir   un   programa   en   ensamblador   para   el   circuito   del   problema   anterior.   Al   pulsar   el   botón   se   iniciará   la  
cuenta   de   0   a   99   con   un   periodo   aproximado   de   1s.   El   pulsador   solicita   una   interrupción   en   P1.3   por   flanco   de  
bajada.  

SOLUCIÓN:  

#include <msp430G2553.h>
Tmux DEFINE 300
main ;Esto viene bien por lo del "run tu main", aunque se puede quitar
;-------------------------------------------------------------------------------
ORG 0F800h
;-------------------------------------------------------------------------------
RESET
;--------------Configuración --------------------------------------
MOV #0280h,SP
MOV #WDTPW+WDTHOLD,&WDTCTL
MOV.B &CALBC1_1MHZ,&BCSCTL1 ; Funciones de Calibración a 1MHz
MOV.B &CALDCO_1MHZ,&DCOCTL
MOV.B #BIT6+BIT0,&P1DIR
MOV.B #0x0,&P1OUT ; para que estén apagados
MOV.B #0F7h,&P1DIR ; P1.3 como entrada y el resto como salidas
BIS.B #BIT3,&P1REN ; Resistencia en la entrada P1.3
BIS.B #BIT3,&P1OUT ; Decimos que sea de pull-up
BIS.B #BIT3,&P1IES ; Defino P1.3 como activo por flanco de bajada
BIS.B #BIT3,&P1IE ; Y lo habilito como entrada de interrupción
BIS.B #BIT0+BIT1,P2DIR ; Defino P2.0 y P2.1 como salidas
MOV.B #GIE,SR ; Habilitación global de las interrupciones
;-------------------------------------------------------------------------------

jmp $ ; Programa principal


;-------------------------------------------------------------------------------

11   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  

;-------------------------------------------------------------------------------
; Rutina de tratamiento de la interrupción
;-------------------------------------------------------------------------------
P1_ISR
MOV #TSeg,R4 ; Inicializamos los punteros de Unidades y
MOV #TSeg,R5 ; Decenas con la dirección de la tabla de segmentos
CLR R6 ; Unidades = 0
CLR R7 ; Decenas = 0
Tiempo
MOV.B #100,R10
ETIQ1
MOV.B @R4,&P1OUT ; PUni al Puerto de Salida
MOV.B #001h,&P2OUT ; Visualiza dato en posicion de las Unidades
CALL #RETARDO ; Tiempo que está encendido el dígito
MOV.B @R5,&P1OUT ; PDcn al Puerto de Salida
MOV.B #002,&P2OUT ; Visualiza dato en posicion de las decenas
CALL #RETARDO ; Tiempo que está encendido el dígito
DEC R10
JNZ ETIQ1
INC R6 ; Unidades = Unidades + 1
INC R4 ; Actualiza el puntero de unidades
CMP #10,R6 ; ¿Unidades es 9?
JNE Tiempo
CLR R6 ; Unidades = 0
MOV #TSeg,R4 ; Restaura la dirección de la Tabla de segmentos
INC R7 ; Decenas = Decenas + 1
INC R5 ; Actualiza el puntero de decenas
CMP #10,R7 ; ¿Decenas es 9?
JNE Tiempo
CLR R6 ; Unidades = 0
MOV #TSeg,R4 ; Restaura la dirección de la Tabla de segmentos
INC R7 ; Decenas = Decenas + 1
INC R5 ; Actualiza el puntero de decenas
CMP #10,R7 ; ¿Decenas es 9?
JNE Tiempo
MOV.B #BIT3,&P1OUT ; Para apagar el display al terminar
MOV.B #BIT0+BIT1,&P2OUT
BIC.B #BIT3,&P1IFG ; Borra el flag de interrupcion
RETI

12   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  

;-------------------------------------------------------------------------------
; Subrutina de retardo
;-------------------------------------------------------------------------------
RETARDO MOV #Tmux,R15
ETIQ2 DEC R15
JNZ ETIQ2
RET
;-------------------------------------------------------------------------------
; Tabla de 7 segmentos
; Están ordenados g-f-e-d-c-b-a
;-------------------------------------------------------------------------------
TSeg
; 0, 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9
DC8 77h,06h,0B3h,97h,0C6h,0D5h,0F5h,07h,0F7h,0C7h
;-------------------------------------------------------------------------------
; Vectores de interrupción y reset
;-------------------------------------------------------------------------------
ORG 0FFFEh ; Vector de reset
DW RESET
ORG 0FFE4h ; Vector de interrupción para P1
DW P1_ISR
END main

13.  Escribe   un   programa   en   C   para   que   cuando   cada   vez   que   se   pulse   el   P1.3,   interrupción   por   flanco   de   bajada,  
cambie  la  frecuencia  de  parpadeo    de  los  dos  diodos  colocados  en  P1.0  y  P1.6  

SOLUCIÓN:  

13   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  

#include <msp430.h>
#include <inttypes.h>

int j=0;
int Tini=30000;

void main(){
WDTCTL= WDTPW+WDTHOLD;

P1SEL= 0x00;
P1DIR|= (BIT0+BIT6);

P1DIR&=~BIT3;
P1REN|=BIT3; //resistencia en la entrada habilitada
P1OUT|=BIT3; // de pull-up

P1IE|=BIT3; //Habilitamos las interrupciones,


//mas información en la userguide.
P1IES|=BIT3;
P1IFG&=~BIT3;

P1OUT|=BIT0;
P1OUT&=~BIT6;

_BIS_SR(GIE); //Habilitamos las interrupciones generales. IMPORTANTE!!

while(1){ //El mismo código anterior


for(j=0;j<Tini;j++);

P1OUT^=BIT6;
P1OUT^=BIT0;

if(Tini<=1500){Tini=30000;}
}
}
Rutina de interrupción.
#pragma vector= PORT1_VECTOR
__interrupt void Led_ISR (void){
P1IFG&=~BIT3; //Al salir de una interrupción
//SIEMPRE es necesario limpiar la bandera.
Tini=Tini-5000;
}

14   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
 

14.  Escribir  un  programa  en  ensamblador  para  que  el  bit  P1.0  parpadee  utilizando  la  interrupción  del  Watchdog.  El  
periodo  de  parpadeo  será  aproximadamente  30ms,  si  la  fuente  del  reloj  es  por  defecto  DCO=SMCLK    

SOLUCIÓN:  

;***********************************************************************
#include <msp430.h>
;-------------------------------------------------------------------------
ORG 0FC00h ; Reset
;-------------------------------------------------------------------------
RESET mov.w #0400h,SP ; Inicializa stackpointer
SetupWDT mov.w #WDT_MDLY_32,&WDTCTL ; WDT~30ms intérvalo del timer
bis.b #WDTIE,&IE1 ; habilita interrupción del WD
SetupP1 bis.b #001h,&P1DIR ; P1.0 salida
;

Mainloop bis.w #CPUOFF+GIE,SR


; CPU off, habilita Interrup
Jmp $ ; se para aquí
;
;-----------------------------------------------------------------------
WDT_ISR; Cambia P1.0
;-----------------------------------------------------------------------
xor.b #001h,&P1OUT ; cambia P1.0
reti ;
;
;-----------------------------------------------------------------------
; Vectores de Interrupción
;-----------------------------------------------------------------------
ORG 0FFFEh ; MSP430 RESET Vector
DW RESET ;
ORG 0FFF4h ; WDT Vector
DW WDT_ISR ;
END

 
15   Sistemas  Electrónicos  Digitales    
HOJA  DE  EJERCICIOS  (curso  2014/15)  
 

15. Escribir   un   programa   en   ensamblador   para   que   el   bit   P1.0   parpadee   utilizando   la   interrupción   del   Watchdog.   El  
periodo   de   parpadeo   será   exactamente   250ms   basado   en   el   cristal   de   32KHz   colocado   en   las   patillas   del  
microcontrolador  .  Teniendo  en  cuenta  que  la  fuente  del  reloj  será  ACLK=LFXT1=32768Hz,  y  MCLK=SMCLK=DCO.  Si  
dividimos  los  215  /  213  obtendremos  una  frecuencia  de  4Hz,  es  decir  un  T=250ms.  

SOLUCIÓN:  

;*********************************************************************
#include <msp430.h>
;--------------------------------------------------------------------
ORG 0FC00h ; Reset
;--------------------------------------------------------------------
RESET mov.w #0400h,SP ; Inicializa stackpointer
Setup mov.w #WDT_ADLY_250,&WDTCTL ; WDT 250ms
bis.b #WDTIE,&IE1 ; habiita la INT del WDT
SetupP1 bis.b #001h,&P1DIR ; P1.0 salida
;
Mainloop bis.w #LPM3+GIE,SR ; Modo LPM3, INT habilitadas
Jmp $
;-------------------------------------------------------------------------
WDT_ISR; Cambia P1.0
;-------------------------------------------------------------------------
xor.b #001h,&P1OUT ; Cambia P1.0
reti ;
;
;-------------------------------------------------------------------------
; Interrupt Vectors
;-------------------------------------------------------------------------
ORG 0FFFEh ; MSP430 RESET Vector
DW RESET ;
ORG 0FFF4h ; WDT Vector
DW WDT_ISR ;
END

16   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
 

16. Escribe  un  programa  que  utilizando  la  interrupción  software    TA_0,  cambie  el  P1.6  cada  50.000  ciclos  de  SMCLK.    

SMCLK   proporciona   la   fuente   de   reloj   para   TACLK.   Durante   la   ISR   de   TA_0,   P1.6   se   enciende   y   apaga   cada   50.000  
ciclos  de  reloj.  La  CPU  está  normalmente  apagada  y  se  pone  en  marcha  sólo  durante  el  ISR  de  TA.  

SOLUCIÓN:  

;*************************************************************************
#include <msp430.h>
;-------------------------------------------------------------------------
ORG 0FC00h ; Reset
;-------------------------------------------------------------------------
RESET mov.w #0400h,SP ; Inicializa SP
StopWDT mov.w #WDTPW+WDTHOLD,&WDTCTL ; Stop WDT
SetupP1 bis.b #BIT0,&P1DIR ; P1.0 salida
SetupC0 mov.w #CCIE,&CCTL0 ; habilita INT de CCR0
mov.w #50000,&CCR0 ;
SetupTA mov.w #TASSEL_2+MC_2,&TACTL ; SMCLK, modo cont
;

Mainloop bis.w #CPUOFF+GIE,SR ; CPU off, INT habilitadas


jmp $
;-------------------------------------------------------------------------
TA0_ISR; Cambia P1.0
;-------------------------------------------------------------------------
xor.b #001h,&P1OUT ; Cambia P1.0
add.w #50000,&CCR0 ; AñAde el Offset a CCR0
reti ;
;
;-------------------------------------------------------------------------
; Interrupt Vectors
;-------------------------------------------------------------------------
ORG 0FFFEh ; MSP430 RESET Vector
DW RESET ;
ORG 0FFF2h ; Timer_A0 Vector
DW TA0_ISR ;
END

17   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
17. Escribir  un  programa  en  ensamblador  que  visualice  ACLK  en  P1.0  ,  SMCLK  en  P1.4  y  que  en  P1.1  se  obtenga  una  
frecuencia  de  aproximadamente  SMCLK/15.  

SOLUCIÓN:  

18. Utilizando  consulta  (polling),  de  los  bits  P1.4  y  P1.5.  Generar  el  programa  que  permita  realizar  lo  siguiente:  

a)  Cuando  P1.4  tengan  un  flanco  de  bajada  se  realizará  una  salida  por  el  puerto  P2  (irán  apagándose  los  leds  de  
mayor  a  menor  peso),  con  un  tiempo  de  aproximadamente  500ms  

b)  Cuando  P1.5  tengan  un  flanco  de  bajada  se  realizará  una  salida  por  el  puerto  P2  (irán  apagándose  los  leds  de  
menor  a  mayor  peso),  con  un  tiempo  de  aproximadamente  1s  

SOLUCIÓN  

18   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
 

19. ¿Qué   ventaja   tiene   utilizar     _BIS_SR(GIE)frente   a __enable_interrupt()para   habilitar   las   interrupciones  
globales.  

SOLUCIÓN:  

Con   _BIS_SR(GIE)se  puede,  además,  modificar  el  resto  de  bits  del  registro  SR,  por  ejemplo  establecer  el  modo  de  trabajo  
LPM0,   que   sería,   _BIS_SR(LPM0+GIE)mientras   que   con   __enable_interrupt()solamente   podemos   habilitar   las  
interrupciones  globales.  

 
 

19   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
 

20.  Escribir   un   programa   que   realice   lo   siguiente.   Cuando   se   pulsa   reset   se   está   ejecutando   una   secuencia   que  
consiste   en   desplazar   un   bit   a   uno   de   izquierda   a   derecha   y   de   derecha   a   izquierda   por   los   8   bits   del   puerto   2.  
Cuando  se  pulsa  por  primera  vez  el  pulsador  S2,  colocado  en  P1.3,  se  para  la  secuencia  y  cuando  se  vuelve  a  pulsar  
por  segunda  vez  se  continúa  por  donde  iba  la  secuencia.  

SOLUCIÓN:  

#include <msp430.h>

char secuencia[15] = {0x01,0x02,0x04, 0x08,0x10,0x20,0x40,0x80,


0x40,0x20, 0x10, 0x08,0x04,0x02,0x01};
int i,j;
int ii=0; // variable para saber por donde va las secuencia
int parar=0;

void main(void) {

WDTCTL = WDTPW + WDTHOLD; // para el watchdog


DCOCTL = CALDCO_1MHZ; //calibra la f a 1MHz
BCSCTL1 = CALBC1_1MHZ;
// configuración de los puertos
P2SEL &= ~0xFF; // P2 como I/O general (GPIO)
P2DIR |= 0xFF; // P2 como salida
P1DIR &= ~0x08; // P1.3 (push button) como entrada
P1REN |= 0x08; // P1.3 (botón) resistencia habilitada
P1OUT |= 0x08; // P1.3 (botón) resistencia pull-up
// configuración de la interrupción de P1.3

P1IES |= 0x08; // flanco de bajada para P1.3


P1IFG &= ~0x08; // borrar flags de interrup para P1.3
P1IE |= 0x08; // interrup locales habilita para P1.3
//_BIS_SR(GIE); // GIE <--1
__enable_interrupt() ; //es equivalente a la anterior

20   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
 

while(1) {
for (i = ii; i <15 ; i++)
{
P2OUT = secuencia[i];
if (parar==1) break;
//P2OUT = secu[i];
__delay_cycles(100000);
}
ii=i; //para saber por donde va la secuencia
if (ii==15) ii=0; // si se ha llegado al final de la secuencia
// ponerla a cero
while (parar==1){
P2OUT = secuencia[ii-1]; //se resta para que muestre el adecuado
}
}
}
//-----------------------------------------------------
// Rutina de atención de interrupción del puerto P1
//-----------------------------------------------------
#pragma vector=PORT1_VECTOR
__interrupt void P1_Interrupt(void)
{
__delay_cycles(250000); //antirrebotes software este valor es el más adecuado
parar ^= 1;
P1IFG &= ~BIT3; // Pone a cero IFG para P1.3
}

21   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
21. Utilizar  el  Timer    1  en  modo  continuo  con  el  módulo  captura/compara  0  para  que  el  led  P1.0  parpadee  cada  
0,1s  (utilizar  MCLK  =  1MHz).  

SOLUCIÓN:  

#include <msp430.h>

int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Paramos el WDT
DCOCTL = CALDCO_1MHZ; //calibra la f a 1MHz
BCSCTL1 = CALBC1_1MHZ;
P1DIR |= 0x01; // P1.0 como salida para el LED
TA1CCTL0 = CCIE; // Habilito la interrupciones del
// Registro Captura/Compara 0 del Timer A1
TA1CCR0 = 50000; // Y cargo este registro con el número de
// ciclos que quiero contar
TA1CTL = TASSEL_2 + ID_1 + MC_2; // Seleccionamos SMCLK como fuente de reloj,
//la divido por dos y modo continuo
// ***********************************************************************
// f=1000000; 1000000/2=500000 à T= 2us; cuento 50000 pulsos*2us=0,1ms
// ***********************************************************************
//En registro de control del timer, para cada uno de los campos está la opción
//elegir los bits de forma individual o directamente el modo (aparecen con
//subguión)
//Como voy a trabajar en modo comparación no hace falta que modifique el bit CAP

_BIS_SR(LPM0_bits + GIE); // habilitamos el modo 0 de bajo


//consumo y habilitamos las interrupciones
}

// Rutina de servicio de la interrupción del Timer 1


#pragma vector=TIMER1_A0_VECTOR
__interrupt void Timer_A0 (void)
{
P1OUT ^= 0x01; // Hacemos cambiar al LED
TA1CCR0 += 50000; // Se recarga el registro con 50000 valor que
//debe contar para conseguir 0,1s
}

22   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
22. Utilizar   el   Timer     1   en   modo   ascendente   con   el   módulo   captura/compara   0   para   que   el   led   P1.0   parpadee  
cada  0,1s  (utilizar  MCLK  =  1MHz)  

SOLUCIÓN:  

#include <msp430.h>

int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Paramos el WDT
DCOCTL = CALDCO_1MHZ; //calibra la f a 1MHz
BCSCTL1 = CALBC1_1MHZ;
P1DIR |= 0x01; // P1.0 como salida para el LED
TA1CCTL0 = CCIE; // Habilito la interrupciones del
// Registro Captura/Compara 0 del Timer A1
TA1CCR0 = 50000; // Y cargo este registro con el número de
// ciclos que quiero contar
TA1CTL = TASSEL_2 + ID_1 + MC_1; // Seleccionamos SMCLK como fuente de reloj,
//la divido por dos y modo ASCENDENTE
// ***********************************************************************
// f=1000000; 1000000/2=500000 à T= 2us; cuento 50000 pulsos*2us=0,1ms
// ***********************************************************************
//En registro de control del timer, para cada uno de los campos está la opción
//elegir los bits de forma individual o directamente el modo (aparecen con
//subguión)
//Como voy a trabajar en modo comparación no hace falta que modifique el bit CAP

_BIS_SR(LPM0_bits + GIE); // habilitamos el modo 0 de bajo


//consumo y habilitamos las interrupciones
}

// Rutina de servicio de la interrupción del Timer 1


#pragma vector=TIMER1_A0_VECTOR
__interrupt void Timer_A0 (void)
{
P1OUT ^= 0x01; // Hacemos cambiar al LED
}

23   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
23. Escribir   un   programa   para   que   el   led   P1.0   parpadee   unas   8   veces   por   segundo   (suponiendo   que   MCLK   =   1  
MHz)  por  desbordamiento  del  timer.    

SOLUCIÓN:  

Cuando   se   desborda   el   timer   el   flag   TAIFG   se   activa   y   se   produce   la   llamada   a   la   interrupción.   Para   saber   quien   ha  
producido  la  llamada  a  la  interrupción  bastaría  consultar  los  flags  (CCIFG1,  CCIFG2,  TAIFG),  pero  habría  que  hacerlo  
por  encuesta.  Para  evitarlo,  el  MSP430  tiene  el  registro  TAIV,  que  nos  ayudará  a  identificar  la  fuente  de  interrupción  
rápidamente.   Este   registro   contiene   un   valor   que   viene   determinado   por   la   fuente   de   interrupción,   0x000A   para   el  
overflow  del  Timer.  Este  ejemplo  es  interesante  verlo  en  ensamblador.  

#include <msp430.h>

int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Paramos el WDT
P1DIR |= 0x01; // P1.0 como salida para el LED
TA0CTL = TASSEL_2 + MC_2 + ID_1 + TAIE; // Seleccionamos SMCLK como fuente
// de reloj, modo continuo, % por 2 y
// habilita interrupciones

_BIS_SR(LPM0_bits + GIE); // habilitamos el modo 0 de bajo


// consumo y habilitamos
// las interrupciones globales
}
#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer_A0 (void)
{
/* switch(TA0IV)
{
case 2: break; // Este es el caso de que se haya activado CCIFG1
case 4: break; // Este es el caso de que se haya activado CCIFG2
case 10: P1OUT ^= 0x01; // Y este es el timer overflow
break;
}
*/
P1OUT ^= 0x01;
}

24   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
24. Repetir  el  ejercicio  anterior,  en  ensamblador.  

SOLUCIÓN:  

#include <msp430G2553.h>
;-------------------------------------------------------------------------------
ORG 0F800h
;-------------------------------------------------------------------------------
RESET mov.w #0400h,SP ;Incializamos el SP
mov.w #WDTPW+WDTHOLD,&WDTCTL ;Paramos el WDT
bis.b #001h,&P1DIR
SetupTA
mov.w #TASSEL_2+ID_1+MC_2+TAIE,&TACTL ;Seleccionamos SMCLK ;
;como fuente de reloj y se % 2
;modo ascendente
Mainloop bis.w #LPM0+GIE,SR ;CPU OFF e interrupciones
nop
;-------------------------------------------------------------------------------
; ISR genérica para CCR1 a 4 y overflow
; TA0IV contiene 2, 4, 6, 8 ó 10 (0A). Lo que se hace es añadir su contenido al
; PC.
; si los ponemos de forma consecutiva, siempre sabremos quién ha producido la
; interrupción y saltar a donde toque.
; Los reti también ocupan 2 bytes, por lo que también es correcto
;En este caso, como en caso de desbordamiento el contenido de TA0IV es 10 (0A)
; y es el último, no hace falta poner salto.
;Eso sí, hay que poner los todos los CCR1 a 4, aunque el nuestro solo tenga 3
; porque los valores son fijos.
;-------------------------------------------------------------------------------
TA0_ISR add.w &TA0IV,PC
reti ; No hay interrupción pendiente (TA0IV = 0)
reti ; CCR1
reti ; CCR2
reti ; CCR3 - Este no existe en nuestro MSP430
reti ; CCR4 - Este no existe en nuestro MSP430
TA_over xor.b #001h,&P1OUT ; Desbordamiento, también JMP tratar_over
reti ;
;-------------------------------------------------------------------------------
; Interrupt Vectors
;-------------------------------------------------------------------------------
ORG 0FFFEh ; MSP430 RESET Vector
DW RESET ;
ORG 0FFF0h ; Vector del Timer0_A1
DW TA0_ISR ;
END

25   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
 

25. Escribir  un  programa  para  que  por  la  patilla  P1.1  se  muestre  TA.0    (suponiendo  que  MCLK  =  1  MHz)  y  que  la  
frecuencia  obtenida  por  P1.1  sea  de  1KHz.  Utilizando  como  reloj  SMCLK  

SOLUCIÓN:  

Se   utiliza   la   patilla   P1.1     como   salida   de   TA.0.   No   hay   llamada   a   interrupciones,   se   desconecta   la   CPU   y   queda  
simplemente  funcionando  el  Timer  con  el  reloj.    

El  registro  TA0CCR0  deberemos  cargarlo  con  un  valor    que  obtenemos  de  fsal  =  fSMCLK/TA0CCRO  

cargamos  el  registro  de  comparación  con:  TA0CCR0  =  fSMCLK/  fsal  =1000,  es  decir,  como  tenemos  el  tiempo  a  cero  y  el  
tiempo  a  uno,  1000/2=500,  y  se  empieza  la  cuenta  en  0,  TA0CCRO=499    

#include <msp430.h>

int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Paramos el WDT
BCSCTL1 = CALBC1_1MHZ; // Ajustamos frecuencia a 1MHz
DCOCTL = CALDCO_1MHZ; //
P1SEL |= 0x02; // Configuramos P1.1 como salida del Timer
P1DIR |= 0x07; // Y la habilitamos como salida
TA0CCTL0 = OUTMOD_4; // Registro Captura/Compara del Timer A0 pongo
// modo Salida Toggle
TA0CCR0 = 499;
TA0CTL = TASSEL_2 + MC_1; // Y en registro del control de timer
// seleccionamos SMCLK como fuente de reloj
// modo ascendente.

_BIS_SR(LPM0_bits); // habilitamos el modo 0 de bajo consumo


}

 
26   Sistemas  Electrónicos  Digitales    
HOJA  DE  EJERCICIOS  (curso  2014/15)  
26. Escribir  un  programa  en  ensamblador  para  que  el  bit  P1.6  se  encienda  cuando  la  señal  introducida  por  A1  sea  
mayor  de  0,5*Vcc,  utilizar  el  convertidor  ADC  tomando  16  muestras  por  segundo  

;*******************************************************************************
#include <msp430.h>
;-------------------------------------------------------------------------------
ORG 0FC00h
;-------------------------------------------------------------------------------
#define miSP 0x400
;-------------------------------------------------------------------------------
RESET mov.w #miSP,SP ; inicializa stackpointer
mov.w #WDTPW+WDTHOLD,&WDTCTL ; Stop WDT
mov.w #ADC10SHT_2+ADC10ON+ADC10IE,&ADC10CTL0 ; 16x, enable int.
mov.w #INCH_1, &ADC10CTL1
bis.b #0x02,&ADC10AE0 ; P1.1 entrada de ADC10
bis.b #0x040,&P1DIR ; P1.6 salida
;
vuelta bis.w #ENC+ADC10SC,&ADC10CTL0 ; empezar muestreo y conversión
bis.w #CPUOFF+GIE,SR ; modo LPM0, int global hab
bic.b #0x40,&P1OUT ; P1.6 = 0
cmp.w #01FFh,&ADC10MEM ; ADC10MEM = A1 > 0.5*Vcc
jlo vuelta ; otra vez
bis.b #0x40,&P1OUT ; P1.6 = 1
jmp vuelta ; otra vez

;-------------------------------------------------------------------------------
ADC10_ISR; Salir de LPM0 y reti
;-------------------------------------------------------------------------------
bic.w #CPUOFF,0(SP) ; sale de LPM0 y reti
reti ;

;-------------------------------------------------------------------------------
COMMON INTVEC ; Interrupt Vectors
;-------------------------------------------------------------------------------
ORG ADC10_VECTOR ; ADC10 Vector
DW ADC10_ISR
ORG RESET_VECTOR ; POR, ext. Reset
DW RESET
END

27   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
27. Escribir  un  programa  en  C  para  que  el  bit  P1.6  se  encienda  cuando  la  señal  introducida  por  A1  sea  mayor  de  
0,5*Vcc,  utilizar  el  convertidor  ADC  tomando  16  muestras  por  segundo.  

#include <msp430.h>

int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
ADC10CTL0 = ADC10SHT_2 + ADC10ON + ADC10IE; // 16x, enable int.
ADC10CTL1 = INCH_1; // entrada A1
ADC10AE0 |= 0x02; // PA.1 entrada a convertir
P1DIR |= 0x40; // P1.6 salida

for (;;)
{
ADC10CTL0 |= ENC + ADC10SC; // inicio de muestro y conversión
__bis_SR_register(CPUOFF + GIE); // modo LPM0 e inter. globales hab.
if (ADC10MEM < 0x1FF)
P1OUT &= ~0x40; // apagar P1.6
else
P1OUT |= 0x40; // encender P1.6
}
}

// ADC10 interrupt service routine


#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
__bic_SR_register_on_exit(CPUOFF); // sacar de LMP0(CPUOFF)
}

28   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
28. Escribir  un  programa  para  que  por  la  patilla  P1.1  se  muestre  TA.0    (suponiendo  que  MCLK  =  1  MHz)  y  que  la  
frecuencia  obtenida  por  P1.1  sea  de  1KHz.  Utilizando  como  reloj  ACLK  

SOLUCIÓN:  El  registro  TA0CCR0  deberemos  cargarlo  con  un  valor    que  obtenemos  de  fsal  =  fACLK/TA0CCRO  

cargamos  el  registro  de  comparación  con:  TA0CCR0  =  fACLK/  fsal  =32768/1000=32,7,  es  decir,  como  tenemos  el  tiempo  
a  cero  y  el  tiempo  a  uno,  32,7/2=16,35  y  se  empieza  la  cuenta  en  0,  TA0CCRO=15    

#include <msp430.h>

int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Paramos el WDT
P1SEL |= 0x02; // Configuramos P1.1 como salida del Timer
P1DIR |= 0x07; // Y la habilitamos como salida
TA0CCTL0 = OUTMOD_4; // Registro Captura/Compara del Timer A0 pongo
// modo Salida Toggle
TA0CCR0 = 15;
TA0CTL = TASSEL_1 + MC_1; // Y en registro del control de timer
// seleccionamos ACLK como fuente de reloj
// modo ascendente.

_BIS_SR(LPM3_bits); // habilitamos el modo 3 de bajo consumo


}

29   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
29. Generar  una  salida  PWM  en  la  patilla  P1.2  con  una  frecuencia  de  2KHz  y  un  Duty  Cycle  del  75%  y  utilizando  el  
Timer  A0  en  modo  ascendente  y  salida  reset/set,  utilizando  SMCLK  como  fuente  del  reloj  

SOLUCIÓN:  

El   valor   de   TA0   define   el   periodo   del   PWM   y   el     valor   en   TACCR1   define   el   duty   cycle   que   viene   dado   por  
TA0CCR1/TA0CCR0.   Calculamos   el   valor   de   TA0CCR0=500,   para   obtener   un   duty   cycle   del   75%   tendremos   que  
poner  en  TA0CCR1=375,  es  decir,    (500*0.75)=375  

  fSAL  =  fSMCLK  /  TA0CCR0  =    2  KHz  à  TA0CCR0=  fSMCLK/fSAL=  106/2000  =  500  à  499  (0  a  499)à  75%  de  500  =375  

#include <msp430.h>

int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Paramos el WDT
BCSCTL1 = CALBC1_1MHZ; // f=1Mhz
DCOCTL = CALDCO_1MHZ;
P1SEL |= 0x04; // Configuramos P1.2 como salida del Timer
P1DIR |= 0x04; // Y la habilitamos como salida

TA0CCTL1 = OUTMOD_7; // Registro Captura/Compara 1 del Timer A0


// el modo Salida Reset/Set
// TA0CCR0 determina el periodo
// TA0CCR1 determina el flanco
TA0CCR0 = 499;
TA0CCR1 = 375;

TA0CTL = TASSEL_2 + MC_1; //modo ascendente y SMCLK fuente del reloj

_BIS_SR(LPM0_bits); // habilitamos el modo 0 de bajo consumo


}

30   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
 

30. Generar  una  salida  PWM  en  la  patilla  P1.2  con  una  frecuencia  de  2KHz  y  un  Duty  Cycle  del  75%  y  utilizando  el  
Timer  A0  en  modo  ascendente  y  salida  reset/set,  utilizando  ACLK  como  fuente  del  reloj  

SOLUCIÓN:  

El   valor   de   TA0   define   el   periodo   del   PWM   y   el     valor   en   TACCR1   define   el   duty   cycle,   que   viene   dado   por  
TA0CCR1/TA0CCR0.   Calculamos   el   valor   de   TA0CCR0=16,   para   obtener   un   duty   cycle   del   75%   tendremos   que  
poner  en  TA0CCR1=375,  es  decir,    (500*0.75)=12  

  fSAL  =  fACLK  /  TA0CCR0  =    2  KHz  à  TA0CCR0=  fACLK/fSAL=  16,3  à15(0  a  15)  à  75%  de  16  =12  

#include <msp430.h>

int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Paramos el WDT
BCSCTL1 = CALBC1_1MHZ; // f=1Mhz
DCOCTL = CALDCO_1MHZ;
P1SEL |= 0x04; // Configuramos P1.2 como salida del Timer
P1DIR |= 0x04; // Y la habilitamos como salida

TA0CCTL1 = OUTMOD_7; // Registro Captura/Compara 1 del Timer A0


// el modo Salida Reset/Set
// TA0CCR0 determina el periodo
// TA0CCR1 determina el flanco
TA0CCR0 = 15;
TA0CCR1 = 12;

TA0CTL = TASSEL_1 + MC_1; //modo ascendente y SMCLK fuente del reloj

_BIS_SR(LPM0_bits); // habilitamos el modo 0 de bajo consumo


}

31   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
31. Realizar  un  programa  para  que  la  UART  transmita  el  abecedario  con  la  siguiente  configuración:  9600,  8bits,  
1bit  de  stop,  y  sin  paridad    y  que  se  pueda  visualizara  través  del  USB  en  el  hyperteminal.  

SOLUCIÓN:  

#include <msp430.h>
unsigned int contador = 97;
unsigned int i;
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
BCSCTL1 = CALBC1_1MHZ; // frecuencia 1MHz
DCOCTL = CALDCO_1MHZ;
P1SEL = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
P1SEL2 = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 104; // 1MHz 9600
UCA0BR1 = 0; // 1MHz 9600
UCA0MCTL = UCBRS0; // Modulation UCBRSx = 1
UCA0CTL1 &= ~UCSWRST; // **Inicializa máquina de estado de la USCI
IE2 |= UCA0RXIE + UCA0TXIE; // habilita las interru`ciones de RX y TX
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0, interrupts enabled
}
// ISR de TX
#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR(void)
{
for(i=97; i<123; i++){
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer preparado?
if (contador <123)
{
UCA0TXBUF = i; // Envío caracter i=97
delay_cycles(1500); //tiempo para transmitir un caracter ~1,5ms
}
else if (contador==123)
{
UCA0TXBUF = 0x0D; // Retorno de carro (13 en decimal)
IE2 &= ~UCA0TXIE; //deshabilita la transmisión de caracteres
}
contador=contador+1;
}
}
// ISR de RX
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer está preparado?
UCA0TXBUF = UCA0RXBUF; // TX -> RXed
}

32   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
33. Utilizando   la   patilla   P1.2   como   salida   TA0.1,   generar   dos   frecuencias   con   un   DC=50%   y   de   1KHz   y   1,25KHz,  
respectivamente,  separadas  ente  sí  por  un  retardo  de  0,5s.  De  esta  manera  colocando  un  Altavoz  de  8Ω  en  dicha  
patillas  obtendremos  un  sonido  semejante  a  una  sirena.  El  reloj  debe  ser  SMCLK.  La  sirena  no  sonará  hasta  que  
se   solicite   la   interrupción   por   flanco   de   bajada   mediante   P1.3,   en   dicho   momento   la   alarma   se   repetirá   20   veces  
Mientras  se  está  en  reposo  la  CPU  debe  estar  en  modo  LPM2.  

SOLUCIÓN:  

33   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
 

#include <msp430.h>
int PVez=0;
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Paramos el WDT
BCSCTL1 = CALBC1_1MHZ; // f=1Mhz
DCOCTL = CALDCO_1MHZ;
P1SEL = BIT2; // Configuramos P1.2 como salida del Timer
P1DIR = BIT2; // Y la habilitamos como salida
// CONFIGURACIÓN DE LA INTERRUPCIÓN
P1DIR &=~BIT3; // P1.3 entrada
P1REN |=BIT3; // P1.3 resistencia pull-up HABILITADA
P1OUT |=BIT3; // P1.3 resistencia pull-up
P1IE |=BIT3; //Habilitamos las interrupciones,
P1IES |=BIT3; // FLANCO DE BAJADA
P1IFG &=~BIT3; // flag a cero no hay INT pendiente

// CONFIGURACIÓN DEL TIMER


TA0CCTL1 = OUTMOD_7; // Registro Captura/Compara 1 del Timer A0
// el modo Salida Reset/Set
TA0CTL = TASSEL_2 + MC_1; //modo ascendente y SMCLK fuente del reloj

// Programa principal
__bis_SR_register(LPM2_bits + GIE); // Enter LPM2 y habilita INT
__no_operation();
}

#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
int t;
for (t=0;t<20;t++){ //sonará 10s pues cada tono suena 0,5s
if (PVez==0){
TA0CCR0 = 999; //f1 = fSMCLK / TA0CCR0 = 10e6/1000=1KHZ
TA0CCR1 = 500; // DC=TA0CCR1/TA0CCR0=(500/1000)%=50%
PVez++;
__delay_cycles(500000); //duración de la frecuencia 1; 0,5s
}
else
{
TA0CCR0 = 799; //f2 = fSMCLK / TA0CCR0 =
10e6/800=1,25KHZ
TA0CCR1 = 400; // DC=TA0CCR1/TA0CCR0=(400/800)%=50%
PVez=0;
__delay_cycles(500000); //duración de la frecuencia 2; 0,5s
}
P1IFG &= ~0x08; // P1.3 IFG BORRADO, permite nueva interrupción
}
}

34   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  
34. Este  problema  reúne  los  conceptos  de  emisión-­‐recepción  serie  entre  dos  microcontroladores    

//******************************************************************************
// MSP430G2553 USCI_A0, UART 9600 Full-Duplex, 32kHz ACLK
//
// Descripción: USCI_A0 se comunica de forma contínua en modo full-duplex
// con otro microcontrolador. Está en modo LPM3, con actividad únicamente
// cuando se transmiten o se reciben datos.
// La ISR de RX transmite un carácter a 9600,8,N,1 en aproximadamente 1ms
// La ISR de TX indica a la USCI_A0 que ha recibido un carácter.
// ACLK = BRCLK = LFXT1 = 32768Hz, MCLK = SMCLK = DCO ~1MHz
// Baud rate 32768Hz XTAL @9600 = 32768Hz/9600 = 3.41
//
// MSP430G2xx3 MSP430G2xx3
// ----------------- -----------------
// | XIN|- /|\| XIN|-
// | | 32kHz | | | 32kHz
// | XOUT|- --|RST XOUT|-
// | | /|\ | |
// | RST|--- | |
// | | | |
// | | | |
// | UCA0TXD/P1.2|--------->|P1.1 |
// | | 9600 | |
// | UCA0RXD/P1.1|<---------|P1.2 |
// | | | |
// | | | |
// | GND|----------|GND |
// | | | |
// | | | |
//
//******************************************************************************
#include <io430.h>
#include "LCD4bits.c"
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog

LCD_INI (Dos_Lineas_5x8, Derecha_NoDesplaza);


LCD_Control (CurOFF_BliOFF);
LCD_Control (ClearDisplay);
__delay_cycles(500000);
P1OUT = 0x00; // P1.0/6 setup for LED output
P1DIR = BIT0 + BIT6;
P1SEL = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
P1SEL2 = BIT1 + BIT2;
UCA0CTL1 |= UCSSEL_1; // CLK = ACLK
UCA0BR0 = 0x03; // 32kHz/9600 = 3.41
UCA0BR1 = 0x00;
UCA0MCTL = UCBRS1 + UCBRS0; // Modulation UCBRSx = 3
UCA0CTL1 &= ~UCSWRST; // **Inicializa USCI máquina estados**

35   Sistemas  Electrónicos  Digitales    


HOJA  DE  EJERCICIOS  (curso  2014/15)  

IE2 |= UCA0RXIE + UCA0TXIE; // habilita interrupción USCI_A0 TX/RX

LCD_FilaColumna(0,1);
LCD_Cadena ("ESPERANDO...");
__delay_cycles(5000000);

__bis_SR_register(LPM3_bits + GIE); // Modo LPM3 e interrupciones globales


}

/* En el microcontrolador que sea transmisor hay que descomentar esta rutina


USCI A0/B0 Transmisión ISR y comentar la siguiente USCI A0/B0 Recepción ISR */

// USCI A0/B0 Transmisión ISR

//#pragma vector=USCIAB0TX_VECTOR
//__interrupt void USCI0TX_ISR(void)
//
//{
// unsigned char TxByteT=0;
// TxByteT = 'S';
// LCD_Control (ClearDisplay);
// __delay_cycles(1000000);
// LCD_FilaColumna(0,1);
// LCD_Cadena ("TRANSMIT:");
// LCD_FilaColumna(0,10);
// LCD_Caracter(TxByteT);
// __delay_cycles(500000);
//
// UCA0TXBUF = TxByteT; // Lee, y transmite
//}

/* En el receptor cargamos con la rutina USCI A0/B0 Transmisión ISR comentada


y la rutina USCI A0/B0 Recepción ISR descomentada */

// USCI A0/B0 Recepción ISR


#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
unsigned char TxByteR=0;
TxByteR=UCA0RXBUF;
LCD_Control (ClearDisplay);
__delay_cycles(500000);
LCD_FilaColumna(1,1);
LCD_Cadena ("RECIBIDO:");
LCD_FilaColumna(1,10);
__delay_cycles(500000);
LCD_Caracter(TxByteR);
__delay_cycles(5000000);
}

 
36   Sistemas  Electrónicos  Digitales    

Вам также может понравиться