36
HOJA DE EJERCICIOS (curso 2014/15) Sistemas Electrónicos Digitales 1 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

HOJA EJERCICIOS SOLUCIONES - RUA: Principal · _BIS_SR(LPM0_bits + GIE); // Habilita interrupciones y deshabilita la CPU y MCLK #pragma vector=PORT1_VECTOR // Rutina de servicio para

  • Upload
    vuongtu

  • View
    227

  • Download
    0

Embed Size (px)

Citation preview

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    1  

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

 

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    2  

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

SOLUCIÓN:  

 

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

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); } }  

/* 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 } }

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    3  

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  

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    4  

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:  

 

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  

#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 } } }  

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    5  

 

 

;----------------------------------------------------- #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

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    6  

 

 

;--------------------------------------------------------------------- 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

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    7  

 

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:  

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    8    

#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 }

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    9  

 

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.  

 

 

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  

 

 

 

 

 

 

 

 

Fig.1  circuito    

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    10  

 

 

 

#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 }  

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    11  

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

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

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    12  

 

 

 

 

 

 

;------------------------------------------------------------------------------- ; 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

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    13  

 

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:  

 

 

 

 

 

 

 

 

 

 

 

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

; 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

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    14  

 

 

#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;

}

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    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

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    16  

 

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

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    17  

 

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

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    18  

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  

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    19  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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.  

 

 

 

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    20  

 

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

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    21  

 

 

 

 

 

 

 

 

 

 

 

 

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

}

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    22  

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

}

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    23  

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

}

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    24  

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;

}

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    25  

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

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    26  

 

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

}

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    27  

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

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    28  

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) }

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    29  

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

}

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    30  

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

}

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    31  

 

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

}

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    32  

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 }

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    33  

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:  

 

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    34  

 

#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 } }

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    35  

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**

HOJA  DE  EJERCICIOS  (curso  2014/15)  

Sistemas  Electrónicos  Digitales    36    

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); }