HOJA DE EJERCICIOS (curso 2014/15) Sistemas

Anuncio
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
XOR.B
MOV.W
#001h,&P1OUT
#050000,R15
DEC.W
JNZ
JMP
R15
L1
INICIO
;
;
;
;
;
;
INICIO
L1
Conmuta el bit P1.0
R15=50000 para realizar un retardo
se realiza 50000 veces el bucle L1
Decrementando R15
retardo=(1+2)*50000=150000T
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;
P1DIR |= 0x01;
// Para el watchdog
// Configura P1.0 como salida direction
for (;;)
{
volatile unsigned int i;
P1OUT ^= 0x01;
// Conmuta P1.0 usando la XOR
i = 50000;
do (i--);
while (i != 0);
} // Retardo
}
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>
#include <inttypes.h>
void main(){
WDTCTL= WDTPW+WDTHOLD;
//inclusiones.
//funcion principal
//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
P1DIR
P1DIR
P1REN
P1OUT
//
//
//
//
//
&= ~0x40;
|= 0x40;
&= ~0x08;
|= 0x08;
|= 0x08;
P1.6
P1.6
P1.3
P1.3
P1.3
a cero
(LED) como salida
(push button) como entrada
(botón) resistencia habilitada
(botón) resistencia pull-up
while (1){
if( BIT3 & ~P1IN ) {
P1OUT ^= 0x40;
}
} // Si se pulsa botón
// 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 ){
P2OUT = secu[i];
RETARDO();
}
// Si NO
se pulsa botón
}
}
//----------------------------------------------------// 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
JNZ
R15
ETIQ2
RET
;------------------------------------------------------------------------------;
Tabla de 7 segmentos
;
Están ordenados g-f-e-d-c-b-a
;------------------------------------------------------------------------------TSeg
; 0, 1 , 2
DC8
, 3 , 4 ,
5 ,
6 ,
7 , 8 , 9
77h,06h,0B3h,97h,0C6h,0D5h,0F5h,07h,0F7h,0C7h
;------------------------------------------------------------------------------;
Vectores de interrupción y reset
;------------------------------------------------------------------------------ORG
0FFFEh
DW
RESET
ORG
0FFE4h
DW
P1_ISR
END
main
; Vector de reset
; Vector de interrupción para P1
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
Jmp $
#CPUOFF+GIE,SR
; CPU off, habilita Interrup
; 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;
DCOCTL = CALDCO_1MHZ;
// para el watchdog
//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
P1IE
|= 0x08;
//_BIS_SR(GIE);
__enable_interrupt() ;
20 para P1.3
// interrup locales habilita para P1.3
// GIE <--1
//es equivalente a la anterior
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;
DCOCTL = CALDCO_1MHZ;
// Paramos el WDT
//calibra la f a 1MHz
BCSCTL1 = CALBC1_1MHZ;
P1DIR |= 0x01;
TA1CCTL0 = CCIE;
// P1.0 como salida para el LED
// 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;
DCOCTL = CALDCO_1MHZ;
// Paramos el WDT
//calibra la f a 1MHz
BCSCTL1 = CALBC1_1MHZ;
P1DIR |= 0x01;
TA1CCTL0 = CCIE;
// P1.0 como salida para el LED
// 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;
case
4: break;
// Este es el caso de que se haya activado CCIFG1
// 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;
__bis_SR_register(CPUOFF + GIE);
if (ADC10MEM < 0x1FF)
P1OUT &= ~0x40;
else
P1OUT |= 0x40;
}
// inicio de muestro y conversión
// modo LPM0 e inter. globales hab.
// apagar
P1.6
// 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;
_BIS_SR(LPM0_bits);
//modo ascendente y SMCLK fuente del reloj
// 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;
_BIS_SR(LPM0_bits);
//modo ascendente y SMCLK fuente del reloj
// 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;
TA0CTL = TASSEL_2 + MC_1;
// Registro Captura/Compara 1 del Timer A0
// el modo Salida Reset/Set
//modo ascendente y SMCLK fuente del reloj
// Programa principal
__bis_SR_register(LPM2_bits + GIE);
__no_operation();
// Enter LPM2 y habilita INT
}
#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 
Descargar