Práctica 3Lab 3

E/S digital

Lectura de pt.asm y uso de la biblioteca desde CReading pt.asm and using the library from C

Localizar pines → configurar → leer y escribir → atender interrupcionesFind pins → configure → read and write → handle interrupts
Enunciado 2026/27 · §3.2–3.3

Qué trabajo nos ahorra la biblioteca

main.c · uso desde C
/* Fragmentos del programa que queremos escribir */sw1 = ptConfigura(1, 1,    PT_ENTRADA_PULLUP | PT_ACTIVOBAJA);led1 = ptConfigura(1, 0, PT_SALIDA); /* Dentro del bucle principal */ptEscribe(led1, ptLee(sw1));
Enunciado · §3.3

De dónde salen los pines y la polaridadWhere pin assignments and polarity come from

SLAU627A · LEDs · esquema, p. 31
SLAU627A · LEDs · esquema, p. 31 · clic para ampliarclick to enlarge
SLAU627A · pulsadores · esquema, p. 31
SLAU627A · pulsadores · esquema, p. 31 · clic para ampliarclick to enlarge
Mapa que usará main.c
LED1: P1.0    LED2: P9.7SW1:  P1.1    SW2:  P1.2

Los LEDs se activan en alta. Los pulsadores cierran a masa: se leen como activos en baja.

TI SLAU627A · esquema, p. 31

Por qué SW2 necesita una resistencia

P1.2 · tres decisiones de configuración
/* Pulsador de la placa: conecta P1.2 a GND */PT_ENTRADA_PULLUP   // Fijar el nivel en reposo.PT_ACTIVOBAJA       // Interpretar 0 como pulsado. /* Después de configurar el pin */int pulsado = ptLee(sw2);
SLAU627A · esquema p. 31; EntradaSalida.pdf · OUT/REN

Configurar P1.2 con direcciones fijas

Ejemplo directo · SW2 como entrada pullup
bic.b #BIT2, &P1DIRbis.b #BIT2, &P1RENbis.b #BIT2, &P1OUT
EntradaSalida.pdf · OUT, DIR y REN · pp. 1–2
EntradaSalida.pdf · OUT, DIR y REN · pp. 1–2 · clic para ampliarclick to enlarge
EntradaSalida.pdf · configuración GPIO

Modificar un pin sin alterar los otros siete

Ejemplo numérico · mismas tres escrituras
bic.b #BIT2, &P1DIRbis.b #BIT2, &P1RENbis.b #BIT2, &P1OUT
EntradaSalida.pdf · DIR, REN y OUT

Las etiquetas evitan repetir el cableado

Enunciado §2.1 · aliases del pin
.cdecls C,LIST,"msp430ports.h"SW2_BIT  .equ BIT2SW2_PORT .equ P1IN bic.b #SW2_BIT, &SW2_PORT+PDIRbis.b #SW2_BIT, &SW2_PORT+PRENbis.b #SW2_BIT, &SW2_PORT+POUT
msp430ports.h · PDIR=4, PREN=6, POUT=2

Por qué los argumentos llegan en registros

pt.h y main.c · frontera entre C y ASM
puerto_t ptConfigura(int puerto, int bit,                    uint8_t modo); sw2 = ptConfigura(1, 2,    PT_ENTRADA_PULLUP | PT_ACTIVOBAJA); /* R12=1, R13=2, R14=modo; retorno en R12 */
Enunciado · §3.2.2–3.2.3

De un registro a su direcciónFrom a register to its address

msp430ports.h · offsets respecto a PxIN
#define PIN    0#define POUT   2#define PDIR   4#define PREN   6#define PSEL0  0x0A#define PSEL1  0x0C
SLAS789D · tabla 6-56, registros P1/P2 · p. 136
SLAS789D · tabla 6-56, registros P1/P2 · p. 136 · clic para ampliarclick to enlarge
Datasheet FR6989; msp430ports.h

Por qué el índice del puerto se multiplica por dos

msp430ports.asm · tabla; debajo, código que la consulta
TabPuertos: .short PJIN            .short P1IN            .short P2IN            ; ... hasta P10IN mov.w R12, R11rla.w R11mov.w TabPuertos(R11), R11
msp430ports.asm · TabPuertos

Por qué el número de bit no es la máscara

msp430ports.asm · tabla y consulta
TabBits: .byte BIT0  ; 0000 0001         .byte BIT1  ; 0000 0010         .byte BIT2  ; 0000 0100         ; ... hasta BIT7 mov.b TabBits(R13), R15
msp430ports.asm · TabBits

Las mismas tres escrituras, ahora para un pin variable

Enunciado §2.1 · ejemplo de acceso variable
; R12=1, R13=2: queremos configurar P1.2mov.w R12, R11rla.w R11mov.w TabPuertos(R11), R11mov.b TabBits(R13), R15 bic.b R15, PDIR(R11)bis.b R15, PREN(R11)bis.b R15, POUT(R11)
Enunciado · §2.1

Un byte reúne las opciones de configuración

Ejemplo de configuración completa de SW2
sw2 = ptConfigura(1, 2,  PT_ENTRADA_PULLUP |  PT_ACTIVOBAJA |  PT_BAJADA | PT_IRQ); /* modo = 0xE1 */
Enunciado P3 · campos de modo · p. 4
Enunciado P3 · campos de modo · p. 4 · clic para ampliarclick to enlarge
Enunciado · §3.2.3

Qué conserva sw2 después de configurar el pin

C · el retorno es una referencia al pin
typedef uint8_t puerto_t; sw2 = ptConfigura(1, 2, modo);/* sw2 = 0x8A: polaridad baja, puerto 1, bit 2 */ int pulsado = ptLee(sw2);
Enunciado · §3.2.2–3.2.3

ptConfigura: validar los parámetrosptConfigura: validate parameters

pt.asm recibido · entrada y salida (cuerpo omitido)
ptConfigura:  cmp.w #MINP, R12  jl    ptConfErr  cmp.w #MAXP+1, R12  jge   ptConfErr  and.b #0x07, R13  push.w R12  ; continúa la creación del descriptorptConfErr: mov.w #-1, R12ptConfFin: ret
ptConfigura · precondiciones

Construir el descriptor sin perder el índice de la tabla

pt.asm recibido · empaquetado para SW2
rla.w R12mov.w R12, R15rla.w R12rla.w R12add.b R13, R12bit.b #MD_POL, R14jz    ptConf1bis.b #BIT7, R12
ptConfigura · puerto_t

Antes de escribir, convertir ambos índices

pt.asm recibido · comienzo de ptConf1
; R12=descriptor, R15=2*puerto, R13=numero de bitptConf1:mov.w TabPuertos(R15), R15mov.b TabBits(R13), R13 ; A partir de aquí: R15=base y R13=mascara
ptConfigura · antes de SEL0/SEL1

ptConfigura: seleccionar GPIO o periféricoptConfigura: select GPIO or peripheral

pt.asm recibido · primer bit de función
ptConfFunc:  bit.b #MD_FUNC0, R14  jz    ptResetSel0  bis.b R13, PSEL0(R15)  jmp   ptConfSel1ptResetSel0:  bic.b R13, PSEL0(R15)ptConfSel1:  ; el mismo patrón para MD_FUNC1 y PSEL1
EntradaSalida.pdf · PxSEL1/PxSEL0 · p. 2
EntradaSalida.pdf · PxSEL1/PxSEL0 · p. 2 · clic para ampliarclick to enlarge
ptConfigura · SEL0/SEL1

ptConfigura: decidir entrada o salidaptConfigura: select input or output

pt.asm recibido · tabla de saltos
ptConfDir:  mov.b R14, R11  and.b #MD_TIPO, R11  rla.b R11  add.w R11, PC  jmp   ptConfEnt  jmp   ptConfEntPU  jmp   ptConfEntPDptConfSal:  ; comienza el bloque de salida
ptConfigura · selección de tipo

ptConfigura: bloque de entrada pullupptConfigura: pullup input block

pt.asm recibido · entradas con resistencia
ptConfEntPU:  bic.b R13, PDIR(R15)  bis.b R13, PREN(R15)  bis.b R13, POUT(R15)  jmp   ptConfSF ptConfEntPD:  bic.b R13, PDIR(R15)  bis.b R13, PREN(R15)  bic.b R13, POUT(R15)  jmp   ptConfSF
ptConfigura · entrada

En una salida, apagado no siempre significa cero

pt.asm recibido · ajuste previo del valor inicial
bit.b #MD_POL, R14jz    ptConf1bis.b #BIT7, R12xor.b #MD_VINI, R14 ; El bloque de salida usará el VINI ya ajustado.
Enunciado · POL/VINI; original MD_VINI = actual MD_INI

ptConfigura: valor inicial antes de DIRptConfigura: initial value before DIR

pt.asm recibido · bloque de salida
ptConfSal:  bit.b #MD_FUNC, R14  jnz   ptConfSalF  bit.b #MD_VINI, R14  jc    ptConfSal1ptConfSal0:  bic.b R13, POUT(R15)  jmp   ptConfSalFptConfSal1:  bis.b R13, POUT(R15)ptConfSalF:  bis.b R13, PDIR(R15)
ptConfigura · salida

Flanco, permiso y evento son cosas distintas

Ejemplo de servicios · SW2 en P1.2
ptEscFlanco(sw2, 1);  // IES: detectar bajada.ptBorraIRQ(sw2);      // IFG: quitar lo pendiente.ptEscHabIRQ(sw2, 1);  // IE: permitir esta fuente. /* Solo cuando todo el sistema esté preparado: */_EINT();             // GIE: permiso del procesador.
EntradaSalida.pdf · pp. 3–4; enunciado §3.2.6–3.2.12

ptConfigura: flanco, bandera y habilitaciónptConfigura: edge, flag and enable

pt.asm recibido · fragmentos de configuración IRQ
ptConfFS:  bic.b R13, PIES(R15)  jmp   ptConfIEptConfFB:  bis.b R13, PIES(R15); ... selección de IRQ ...pfConfSiIRQ:  bic.b R13, PIFG(R15)  bis.b R13, PIE(R15)
EntradaSalida.pdf · PxIES y PxIE · p. 3
EntradaSalida.pdf · PxIES y PxIE · p. 3 · clic para ampliarclick to enlarge
ptConfigura · IRQ

Deshacer el descriptor para volver al hardware

pt.asm recibido · inicio de ptDecodifica
mov.b R12, R15and.b #0x07, R15mov.b TabBits(R15), R15rra.w R12rra.w R12rra.w R12mov.b R12, R11and.b #0x0F, R11; validar R11; buscar TabPuertos[2*R11]
ptDecodifica · extracto

Validación que debe preceder al acceso GPIOValidation before GPIO access

Propuesta de comprobación · no está en el pt.asm recibido
; Fragmento que hay que integrar en los auxiliarespush.w R10mov.b PSEL0(R11), R10bis.b PSEL1(R11), R10bit.b R15, R10pop.w R10jnz   ptError; continuar con la lectura o escritura
Enunciado · §3.2.4–3.2.11; falta detectada en la revisión

Leer un bit: dirección, contenido y máscara

pt.asm recibido · núcleo de ptLeeAlgo, tras validar
; R11=base, R13=offset, R15=mascaraadd.w R13, R11mov.b @R11, R12and.b R15, R12 ; ptLee usa PIN=0; ptLeeIRQ usa PIFG=0x1C.
ptLeeAlgo · se omiten aquí las validaciones previas

ptLee: aislar el pin y aplicar polaridadptLee: isolate the pin and apply polarity

pt.asm recibido · ptLee
ptLee:  push.w R12  mov.w #PIN, R13  call  #ptLeeAlgo  pop.w R13  bit.w #BIT7, R13  jz    ptLeeFin  xor.b R15, R12ptLeeFin:  ret
Enunciado · §3.2.4

Por qué XOR convierte el cero eléctrico en pulsado

ptLee · tramo final, con R15=BIT2
; R12 ya contiene IN AND BIT2bit.w #BIT7, R13   ; POL del descriptor guardadojz    ptLeeFinxor.b R15, R12ptLeeFin:ret
ptLee · estado físico frente a activación

Por qué escribir 123 también enciende el LED

pt.asm recibido · ptEscribe
ptEscribe:  bit.w #-1, R13  clr.w R13  rlc.w R13  bit.b #BIT7, R12  jnc   ptEscSigue  xor.b #BIT0, R13ptEscSigue:  mov.w #POUT, R14  jmp   ptEscAlgo
Enunciado · §3.2.5

Escribir solo el bit que pertenece al dispositivo

pt.asm recibido · núcleo de ptEscAlgo, tras validar
; R11=base, R14=offset, R15=mascaraadd.w R14, R11tst.w R13jnz   ptEscAlgo1bic.b R15, 0(R11)jmp   ptEscAlgoFptEscAlgo1:bis.b R15, 0(R11)ptEscAlgoF: ret
ptEscAlgo · se omiten aquí las validaciones previas

Los servicios IRQ reutilizan los auxiliaresIRQ services reuse the helpers

pt.asm recibido · las tres lecturas IRQ
ptLeeFlanco: mov.w #PIES, R13             jmp   ptLeeAlgoptLeeHabIRQ: mov.w #PIE, R13             jmp   ptLeeAlgoptLeeIRQ:    mov.w #PIFG, R13             jmp   ptLeeAlgo
Enunciado · §3.2.6–3.2.11

Cambiar el flanco, el permiso o la bandera

pt.asm recibido · las tres escrituras IRQ
ptEscFlanco: mov.w #PIES, R14             jmp   ptEscAlgoptEscHabIRQ: mov.w #PIE, R14             jmp   ptEscAlgoptBorraIRQ:  clr.w R13             mov.w #PIFG, R14             jmp   ptEscAlgo
Enunciado · §3.2.7, §3.2.9 y §3.2.11

Qué se prepara antes de habilitar las interrupciones

main-guiado.c · arranque y módulos reutilizados
WDTCTL = WDTPW | WDTHOLD;_DINT(); /* Configurar led1, led2, sw1 y sw2. *//* Comprobar los descriptores devueltos. */lcdIni();lcdPuts(" Hola ");
main-guiado.c; enunciado · §3.1 y §3.3

main: desbloquear y habilitar al finalmain: unlock and enable at the end

main-guiado.c · después de configurar puertos y LCD
PM5CTL0 &= ~LOCKLPM5;{  int activo = ptLee(sw2);  ptEscribe(led2, activo);  ptEscFlanco(sw2, !activo);}ptBorraIRQ(sw2);ptEscHabIRQ(sw2, 1);_EINT();
SLAU367P · secuencia de desbloqueo · p. 371
SLAU367P · secuencia de desbloqueo · p. 371 · clic para ampliarclick to enlarge
SLAU367P · §12.3.1

ISR de SW2: seguir el estado del pulsadorSW2 ISR: follow the button state

main-guiado.c · propuesta
#pragma vector=PORT1_VECTOR__interrupt void P1ISR(void) {  if (ptLeeIRQ(sw2)) {    int activo = ptLee(sw2);    ptEscribe(led2, activo);    ptEscFlanco(sw2, !activo);    ptBorraIRQ(sw2);  }}
Enunciado · §3.2.12 y §3.3

Por qué hay que cambiar el flanco dentro de la ISR

main-guiado.c · cuerpo de la atención de SW2
if (ptLeeIRQ(sw2)) {  int activo = ptLee(sw2);  ptEscribe(led2, activo);  ptEscFlanco(sw2, !activo);  ptBorraIRQ(sw2);}
main-guiado.c · pulsación y liberación

main: sondeo y condición de salidamain: polling and exit condition

main-guiado.c · fragmentos del flujo principal
lcdPuts(" Hola ");do {  ptEscribe(led1, ptLee(sw1));} while (!(ptLee(sw1) && ptLee(sw2)));_DINT();ptEscHabIRQ(sw2, 0);lcdPuts("Adios ");for (;;) { }
Enunciado · §3.3

Qué hay que corregir del código recibido

pt.asm recibido · contrato frente a ruta de error
; ptDecodifica promete R11=0 si hay error.ptDecErr:  clr.w R14       ; Original: limpia otro registro. ; Corrección de esa instrucción:; clr.w R11
Revisión del proyecto recibido · ver notas y revision.md

Código y documentación para la prácticaCode and documentation

Fuentes y alcance