Desarrollo de aplicación con MSP430F169 de TI

Anuncio
Desarrollo de aplicación con MSP430F169 de TI
TITULACIÓN: Ingeniería Técnica Industrial esp. Electrónica Industrial
AUTOR: Roser Inglés Bort, .
DIRECTOR: Jose Luis Ramirez Falo .
FECHA: Septiembre / 2005.
ÍNDICE
0. Introducción y objetivos………………………………..4
1. Conociendo el Microcontrolador……………………...6
1.1. Familia MSP430……………………………………………………...6
1.1.1 Introducción………………………………………………………………….6
1.1.2 Mapa de memoria……………………………………………………………6
1.1.3 MSP430F169………………………………………………………………....8
1.2. CPU……………………………………………………………………9
1.2.1 Introducción………………………………………………………………….9
1.2.2 Registros…………………………………………………………………….10
1.2.2.1 R0 PC (Contador de Programa)……………………………..…..10
1.2.2.2 R1 SP (Puntero de Pila)…………………………………………..10
1.2.2.3R2 SR (Registro de Estado)…………………………...………….10
1.2.3 Modos de direccionamiento………………………………………………..11
1.2.3.1 Modo Registro…………………………………...………………..11
1.2.3.2 Modo Indexado…………………………………………………...12
1.2.3.3 Modo Relativo a PC………………………………………………12
1.2.3.4 Modo Absoluto…...……………………………………………….13
1.2.3.5 Modo Registro Indirecto………………………..………………..13
1.2.3.6 Modo Indirecto con Autoincremento……………………………14
1.2.3.7 Modo inmediato…………………………………………………..14
1.2.4 Juego de instrucciones……………………………………………………...15
1.2.4.1 Operaciones de Dos Operandos……………………………….....16
1.2.4.2 Operaciones de un Operando……………………………………17
1.2.4.3 Operaciones con Bits de Estado como Operando………………18
1.2.4.4 Operaciones sin Operandos……………………………………...18
1.2.4.5 Saltos………………………………………………………………18
1.2.5 Interrupciones………………………………………………………………19
1.2.5.1 Vectores de Interrupción………………………………………...19
1.2.5.2 Procesado de Interrupciones…………………………………….20
1.3. Módulos periféricos…………………………………………………21
1.3.1 Registros de los módulos periféricos y especiales………………………...21
1.3.2 Puertos E/S………………………………………………………………….22
1.3.2.1 Introducción………………………….......……………………….22
1.3.2.2 Registros………………………………………………………......22
1.3.2.3 Interrupciones…………………………………………………….23
1.3.3 Módulo reloj básico………………………………………………………...24
1..3.1 Introducción………………………………………………………..24
1.3.3.2 Operaciones………………….........................................................24
1.3.3.3 Controlador Digital del Oscilador (DCO)………………………24
1.3.4 Timers A y B………………………………………………………………..26
1.3.4.1 Introducción………………………………………………………26
1.3.4.2 Modos de Operación……………………………………………...27
2
1.3.4.3 Bloques de captura y comparación……………………………...28
1.3.4.4 Interrupciones.…………………………………………………..29
1.4. Entorno del MSP430………………………………………………..30
2. Introducción a los sistemas RFID……………………33
2.1 ¿Qué es un sistema RFID?..................................................................33
2.2 ¿Cómo funciona?.................................................................................34
2.3 Modulaciones………………………………………………………...35
2.4 ISO 15693…………………………………………………………….36
2.4.1 Interferencias e Inicialización……..............………………………………36
2.4.2.1 Transferencia Reader->Tag……………………...………37
2.4.2.2 Transferencia Tag ->Reader……………………………..40
3. Programando el microcontrolador…………………..41
3.1. Introducción…………………………………………………………41
3.2. Elementos……………………………………………………………42
3.3. Ideas para el programa……………………………………………..45
3.4. Programa final………………………………………………………50
3.4.1 Pseudocódigo del programa..........................................................................51
3.4.2 Diagrama de flujo…………………………………………………………..53
3.5. Pruebas………………………………………………………………54
3.6. Ideas para mejorar el programa…………………………………...59
Referencias……………………………………………………….60
Anexo A: Registros periféricos y especiales……………………61
Anexo B: Data decoding…………………………………………68
3
0. Introducción y Objetivos
Este proyecto ha sido realizado como parte del proyecto “GoodFood” de la UE. El
proyecto “GoodFood” tiene como objetivo comunicar un lector con una etiqueta flexible.
Dicha etiqueta será introducida en cajas o palets de fruta para que, durante su transporte,
mida periódicamente el nivel de luminosidad, la temperatura y la presencia de gases y
almacene estos datos. Al llegar a su destino esta tarjeta será introducida en un campo de
señales Rfid y esperará órdenes del lector. El lector enviará un comando a la tarjera
flexible y ésta deberá actuar y responder según el mensaje.
Cuando hablamos de tarjeta flexible nos referimos a un papel delgado como formato del
transmisor donde se sitúan la antena, los sensores y el microcontrolador, a partir de ahora
utilizaremos el nombre de Tag. En la figura 1 se puede observar el diagrama de bloques de
la Tag. Para hablar del lector, nos referiremos con el nombre de Reader.
Figura 1: Diagrama de bloques
La comunicación está basada en los sistemas Rfid, con acoplamiento inductivo, en
concordancia con la ISO 15693 Standard [1].
Este sistema está controlado por un microcontrolador MSP430F169 de Texas Instruments
[2].
Mi parte del trabajo ha sido realizar un programa para el microcontrolador capaz de recibir
el mensaje enviado por el Reader. Para ello se ha hecho un estudio del microcontrolador y
de su entorno. En el Capítulo 1: Conociendo el microcontrolador, se explican las
nociones fundamentales para desarrollar dicho programa.
4
La comunicación está basada en los sistemas Rfid. En el Capítulo 2: Introducción a los
sistemas Rfid, se dan las bases para entender dichos sistemas y el ISO 15693 que fija las
condiciones físicas de los elementos de comunicación, así como el protocolo que deben
seguir.
El último capitulo, Capítulo 3: Programando el microcontrolador, explica el programa
realizado. Esta parte del proyecto ha sido realizado en la universidad de Perugia (Italia),
durante los meses de mayo y junio del presente año 2005.
Los objetivos planteados son:
•
•
•
•
Conocimiento de las herramientas de desarrollo del microcontrolador
MSP430F169.
Conocimiento de los sistemas Rfid .
Conocimiento del protocolo de comunicación ISO15693.
Implementación de un programa para realizar la comunicación Reader→Tag.
5
1. Conociendo el microcontrolador
1.1. Familia MSP430
1.1.1
Introducción
La familia de microcontroladores MSP430 es una familia de microcontroladores de bajo
consumo. El consumo depende del modo en el que se trabaje. Tiene cinco modos de
funcionamiento en bajo consumo y uno en activo. La diferencia entre cada uno de los
modos de funcionamiento es la cantidad de periféricos que se apagan y el tiempo que le
cuesta despertar, que como máximo es de 6µs.
Necesita una tensión de alimentación baja (1.8-3.6 V).
El ciclo de instrucción es de 125 ns.
Contiene:
• Un solo mapa de memoria de hasta 64 kB.
• Un conversor interno A/D de 12 bits.
• Dos timers de 16 bits.
• Tres osciladores independientes.
• Un circuito comparador.
• Interfaz de comunicación serie USART.
• Módulo de multiplicación.
• Registros de funciones especiales y generales de 16 bits.
1.1.2 Mapa de memoria
El microcontrolador MSP430 cuenta con un direccionamiento de 16 bits, por lo que tiene
limitada la memoria a 64 kB. El mapa de memoria se divide en RAM y flash. Como se
observa en la figura 1.1 en inicio de la flash y el fin de la RAM dependen de la cantidad de
memoria y varían según el dispositivo.
Figura 1.1. Mapa de memoria
6
La memoria flash está divida en vectores de interrupción, espacio para código y memoria
de información. La diferencia entre el sector código y el sector información es que el
primero se puede borrar en bloques de 512 bytes, en cambio el segundo se puede borrar en
bloques de 128 bytes, pero esto no impide utilizar la sección de código no utilizada para
almacenar información. En el final de la memoria flash se almacenan los vectores de
interrupción.
La memoria RAM se divide en registros especiales, periféricos de ocho bits y periféricos
de 16 bits, además de RAM de uso general. Los registros especiales están organizados por
bytes y se sitúan en las direcciones 0h-0Fh. Para periféricos de 8 bits el espacio de
memoria utilizado es desde la 010h hasta 0FFh. Estos módulos deben ser accedidos con
instrucciones byte. Al leer con instrucciones word el valor de la parte alta del word resulta
impredecible. Si se escribe con una instrucción word solo se escribe el byte bajo ignorando
el byte alto. El espacio para periféricos de 16 bits es desde la 0100h hasta la 01FFh. Estos
módulos son accedidos con instrucciones word. Si se usa instrucciones byte, solo las
direcciones pares son accesibles y la parte alta siempre vale 0.
Los bytes son localizados en direcciones pares e impares. Los words sólo se localizan en
direcciones pares, como se muestra en la figura 1.2. Cuando se usan instrucciones word,
solo se pueden utilizar direcciones pares. La parte baja de un word está siempre en
direcciones pares. La parte alta del byte siempre está en direcciones impares.
Figura 1.2. Organización de la memoria
7
1.1.3
MSP430F169
El MSP430F169, que es el microcontrolador de esta familia con el que vamos a trabajar,
tiene:
60kB (memoria de código) + 256B (memoria de información) memoria flash
2kB memoria RAM (09FFh-0200h)
Tiene:
•
•
•
•
•
•
•
•
Conversor A/D de 12 bits.
Conversor D/A de 12 bits
Seis puertos de entrada salida. Dos de ellos con capacidad de interrumpir.
Dos USART’s. (USART0 y USART1)
Un comparador
Dos timers
DMA de 3 canales
Perro guardián (Watch dog timer)
En la siguiente figura se muestra el diagrama de bloques:
Figura 1.3. Diagrama de bloques MSP430F169
8
1.2. CPU
1.2.1 Introducción
•
•
•
•
•
•
Arquitectura RISC de 16 bits con 27 instrucciones
Arquitectura ortogonal, cada instrucción se puede usar con siete modos de
direccionamiento para la fuente y cuatro para el destino
Tiene 16 registros. Las operaciones registro-registro tienen un tiempo de ejecución
de un ciclo de reloj.
Los periféricos están conectados a la CPU a través del bus de datos, de direcciones
y control, además pueden ser manejados con todas las instrucciones
Bus de direcciones de 16 bits. El espacio de memoria es lineal y no segmentado.
Bus de datos de 16 bits que permite manipulación directa de argumento de medida
word
Diagrama de bloques:
Figura 1.4: Diagrama de bloques CPU
9
1.2.2 Registros
La CPU tiene 16 registros, 4 dedicados (R0-R3), los restantes son de uso general.
Los 12 registros de uso general (R4-R15) pueden ser usados como registros de datos,
punteros de direcciones o valores indexados y pueden ser accedidos con instrucciones Byte
o Word.
1.2.2.1 R0 PC (Contador de Programa)
Apunta a la siguiente dirección a ser ejecutada. Cada instrucción usa un cierto número de
bytes (2, 4 o 6) y el PC es incrementado de acuerdo con esto. El PC puede ser direccionado
con todas las instrucciones y modos de direccionamiento
PC bits 15 al 1
Bit0=0
Tabla 1.1: Contador de programa
1.2.2.2 R1 SP (Puntero de Pila)
Es usado por la CPU para almacenar la dirección de retorno cuando se llama a una rutina
de servicio a la interrupción. El SP utiliza predecremento y postincremento. Además puede
ser usado por software con todas las instrucciones y modos de direccionamiento.
El SP debe ser inicializado en la RAM por el usuario y es alineado en las direcciones pares.
SP bits 15 al 1
Bit0=0
Tabla 1.2: Puntero de pila
1.2.2.3 R2 SR (Registro de Estado)
El registro de estado es utilizado para conocer el estado de la CPU. En él podemos
observar como ha resultado la última operación, con los bits de overflow, negativo, zero y
carry. Éstos son utilizados para saltos condicionales. Se puede seleccionar el modo de bajo
consumo en el que queremos trabajar, con los bits SCG1 y 0 (ver apartado 2.6). El estado
del oscilador LFXT1 y de la CPU. Se puede usar como fuente o destino usando el
direccionamiento de registro siempre con tamaño word.
Tabla 1.3: Registro de estado
V: Bit de overflow. Este bit es puesto a 1 cuando el resultado de una operación aritmética
desborda el rango de la variable.
SGG1: Reloj generador de sistema 1. Cuando este bit es 1 apaga el reloj de sub sistema.
SGG0: Reloj generador de sistema 0. Cuando este bit es 1 apaga el oscilador interno
(DCO).
OSC OFF: Cuando este bit es 1 apaga el oscilador LFXT1
CPU OFF: Cuando está a 1 la CPU está apagada.
GIE: Interruptor general de habilitación. Cuando está a 1 están permitidas las
interrupciones.
N: Bit negativo. Se pone a 1 cuando el resultado de una operación B o W es negativo y a 0
cuando no lo es
Z: Bit cero. Se pone a 1 cuando el resultado de una operación B o W es 0, vale 0 cuando es
diferente de 0.
C: Bit de carry. Se pone a 1 cuando el resultado de una operación produce acarreo
10
1.2.3 Modos de direccionamiento
Hay siete modos de direccionamiento
destino:
As/Ad Modo
Sintaxis
direccionamiento
00/0
Registro
Rn
01/1
Indexado
X(Rn)
01/1
01/1
10/11/-
11/-
para el operando fuente y cuatro para el operando
Descripción
El registro contiene los operandos
(Rn+X) apunta al operando, X está almacenado en
la próxima palabra
Relativo a PC
ADDR
(PC+X) apunta al operando. X está almacenado en
la próxima palabra
Absoluto
&ADDR La siguiente palabra a la instrucción contiene la
dirección absoluta
Registro indirecto @Rn
Rn es usado como puntero al operando
Indirecto
con @Rn+
Rn es usado como puntero al operando. Rn es
autoincremento
incrementado después la operación. En 1 si era
operación B, en 2 si era W
Inmediato
#N
La siguiente palabra a la instrucción contiene el
operando
Tabla 1.4: Modos de direccionamiento
NOTA: En los siguientes ejemplos se usan las etiquetas EDE, TONI, TOM y LEO que son
usadas como etiquetas genéricas, no tienen ningún significado.
1.2.3.1 Modo Registro
Su longitud es de 1 o 2 W, es válido en la fuente y en el destino.
Se puede usar en tamaño B o W, si se usa tamaño B el Byte alto será 0.
Ejemplo: MOV R10, R11
Antes
Después
11
1.2.3.2 Modo Indexado
Su longitud es de 2 o 3 W, es válido en la fuente y en el destino.
Ejemplo: MOV 2(R5), 6(R6)
Antes:
Espacio @
Después:
Registros Espacio @
Registros
1.2.3.3 Modo Relativo a PC
Su longitud es de 2 o 3 W, es válido en la fuente y en el destino.
Las palabras después de la instrucción contienen la diferencia entre PC y la dirección.
Ejemplo: MOV EDE, TONI ;
Antes:
Espacio @
EDE=0F016h
TONI=01114h
Después:
Espacio @
12
EDE=PC+X
TONI=PC+X
1.2.3.4 Modo Absoluto
Su longitud es de 2 o 3 W, es válido en la fuente y en el destino.
Las palabras después de la instrucción contienen las direcciones.
Este modo es usado por módulos periféricos que están localizados en una dirección
absoluta fija.
Ejemplo: MOV &EDE, &TONI;
Antes:
Espacio @
EDE=0F016h
TONI=01114h
Después:
Espacio @
1.2.3.5 Modo Registro Indirecto
Su longitud es de 1 o 2 W, es válido solo para la fuente.
Ejemplo: MOV.B @R10, 0(R11)
Antes:
Espacio @
Después:
Registros Espacio @
Registros
13
1.2.3.6 Modo Indirecto con Autoincremento
Su longitud es de 1 o 2 W, es válido solo para la fuente.
El autoincremento ocurre después de haber capturado el operando.
Ejemplo: MOV @R10+, 0(R11)
Antes:
Espacio @
Después:
Registros Espacio @
Registros
1.2.3.7 Modo inmediato
Su longitud es de 2 o 3 W, puede ser una menos si se usa constante de CG1 o CG2. Es
válido solo para la fuente.
Ejemplo: MOV #45h, TONI
Antes:
Espacio @
Después:
Espacio @
14
1.2.4. Juego de Instrucciones
Consiste en 27 instrucciones básicas. Existen tres formatos de instrucción: dos operandos,
un operando y saltos. Todas pueden trabajar con operandos tamaño byte o word (por
defecto, se utiliza tamaño word).
La fuente y el destino de una instrucción están definidos por los siguientes campos:
src: operando fuente definido por As y S-reg
dst: operando destino definido por Ad y D-reg
As: los bits direccionados responsables del modo de direccionamiento usado por
la fuente (src)
S-reg: registro de trabajo usado por la fuente (src)
Ad: los bits direccionados responsables del modo de direccionamiento usado por
la fuente (dst)
D-reg: registro de trabajo usado por el destino (dst)
B/W: operación B/W. Un 1 indica operación Byte
Nota: El destino puede ser cualquier dirección del mapa de memoria, por ello cuando se
utilizan instrucciones que cambian su contenido se debe estar seguro de que éste es
modificable.
Se han hecho unas tablas con tal de recoger todas las operaciones posibles ya que en las
tablas de la guía de usuario del microcontrolador no se recogen todas. Estas tablas están
clasificadas por el número de operandos, operaciones con bits de estado y saltos. En ellas
se observa la operación realizada por cada una y la afectación de los bits de estado.
Un “*” indica que el bit se ve afectado, un “–” indica que no se ve afectado.
15
1.2.4.1 Operaciones de Dos Operandos
Formato:
15
12 11
Código operación S-reg
8 7
Ad
6
5
4 3
B/W As
D-reg
0
Tabla 1.5: Formato operaciones dos operandos
Instrucciones:
Mnemónico
MOV src, dst
ADD src, dst
ADDC src, dst
SUB src, dst
SUBC src, dst
CMP src, dst
DADD src, dst
BIT src, dst
BIC src, dst
BIS src, dst
XOR src, dst
AND src, dst
Operación
src->dst
src+dst->dst
src+dst+C->dst
dst+not scr+1->dst ó
dst-src->dst
dst+not scr+C->dst ó
dst-src-1->dst
dst-src
src+dst+C->dst (decimal)
src and dst
not src and dsr->dst
src or dst->dst
src xor dst->dst
src and dst->dst
Bits de estado
V N
Z
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
0
*
0
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
Tabla 1.6: Opoeraciones dos operandos
16
C
1.2.4.2 Operaciones de un Operando
Formato:
15
Código operación
7 6
B/W
5
4 3
Ad
D/S-reg
0
Tabla 1.7: Formato operaciones un operando
Instrucciones:
Mnemónico
Operación
RRC dst
Bits de estado
V N
Z C
*
*
*
*
RRA dst
0
*
*
*
*
*
*
*
*
*
*
*
-
-
-
-
0
*
*
*
*
*
*
*
*
*
*
0
-
*
*
*
*
*
*
*
*
*
-
*
*
*
*
*
*
*
*
*
-
*
*
*
*
*
*
*
*
1
-
-
-
-
-
Equivale a dividir por 2
RLC dst
Equivale a multiplicar por 2 y
sumar el bit Carry
RLA dst
SWPB dst
CALL dst
SXT dst
BR dst
ADC dst
CLR dst
DADC dst
DEC dst
DECD dst
INC dst
INCD dst
INV dst
SBC dst
TST dst
POP dst
PUSH dst
Equivale a multiplicar por 2
Intercambia B alto por B bajo
SP-2->SP; PC+2->@SP;
dst->PC
Extiende signo (Bit7->Bit8>.....->Bit15)
dst->PC
dst+C->dst
0->dst
dst+C->dst (decimal)
dst-1->dst
dst-2->dst
dst+1->dst
dst+2->dst
Not dst->dst
dst+0FFFFh/0FFh+C->dst
cmp #0,dst
@SP->temp; SP+2->SP;
temp->dst
SP-2->SP; dst->@SP
Tabla 1.8: Operaciones un operando
Nota: En las instrucciones PUSH y POP los incrementos/decrementos son de 2 sea cual sea
el tamaño de la operación
17
1.2.4.3 Operaciones con Bits de Estado como Operando
Mnemónico
Operación
Bits de estado
V N
Z
CLR C
0->C
CLR N
0->N
0
CLR Z
0->Z
0
SET C
1->C
SET N
1->N
1
SET Z
1->Z
1
C
0
1
-
Tabla 1.9: Operaciones con bits de estado como operando
1.2.4.4 Operaciones sin Operandos
Mnemónico
Operación
DINT
EINT
NPO
RET
RETI
Bits de estado
V N
Z
0->GIE
1->GIE
Nada, usada para retardos
@->SP; SP+2->SP
TOS->SP; SP+2->SP; TOS- >PC; SP+2->SP
C
-
Tabla 1.10: operaciones sion operandos
1.2.4.5 Saltos
Formato:
15
Código operación
13
12
C
10 9
0
10 bits Offset PC
Tabla 1.11: Formato saltos
Saltos relativos a PC:
Mnemónico
JEQ/JZ etiqueta
JNE/JNE etiqueta
JC etiqueta
JNC etiqueta
JN etiqueta
JGE etiqueta
JL etiqueta
JMP etiqueta
Operación
Salta a la etiqueta si bit zero=1
Salta a la etiqueta si bit zero=0
Salta a la etiqueta si bit carry=1
Salta a la etiqueta si bit carry=0
Salta a la etiqueta si bit negativo=1
Salta a la etiqueta si bit NxorV=0
(si es más grande o igual)
Salta a la etiqueta si bit NxorV=1
(si es más pequeño)
Salta siempre
Tabla 1.12: Saltos relativos a PC
Nota: Los saltos condicionales soportados por el programa saltan en relación a PC y no
afectan a los bits de estado. El rango de salto es de -511 a 512 W relativo al valor de PC.
Los 10 bits de PC Offst son un valor de 10 bits que es doblado y añadido a PC:
PCnuevo= PCviejo+2+ PCoffsetx2
Salto:
Mnemónico
Operación
BR dst
Salta al destino (dst->PC)
Tabla 1.13: Salto
18
1.2.5 Interrupciones
Hay tres tipos de interrupciones: Reset del sistema, no enmascarables (NMI) y
enmascarables.
Las enmascarables puedes ser habilitadas o deshabilitadas individualmente o mediante el
flag e habilitación general (GIE). Son generadas por periféricos con capacidad de
interrumpir.
En cambio las no enmascarables sólo puedes ser habilitadas o deshabilitadas
individualmente (NMIIE, ACCVIE, OFIE). El flag de habilitación general no les afecta.
Cuando una NMI es aceptada, todos los bits de NMI son automáticamente reseteados. La
ejecución del programa empieza en la dirección almacenada en el vector de NMI, 0FFFCh.
Una NMI puede ser generada por tres fuentes: Un flanco en el pin RST/NMI cuando está
configurado en modo NMI; un fallo en el oscilador o condiciones de error con el cristal
oscilador; violación acceso a la memoria flash, cuando se quiere leer o borrar la flash desde
la memoria RAM mientras BUSY=1, escritura del registro de control 1 (FCTL1) mientras
WAIT=0 o escritura registro de control 2 (FTL2) mientras BUSY=1.
1.2.5.1 Vectores de Interrupción
Los vectores de interrupción están localizados en el rango de direcciones de 0FFFFh0FFE0h. El vector contiene los 16 bits de la dirección de la rutina de servicio a la
interrupción.
Fuente int.
Flag int.
Sistema int.
@ (h)
Prioridad
Encendido,
Reset
Reset
0FFFE 15, máxima
externo, WDT
WDTIFG
Memoria Flash
KEYV*
NMI
NMIFG*
NMI
0FFFC 14
Fallo oscilador
OFIFG*
NMI
Violación acceso flash
ACCVIFG*
NMI
Timer_B
TBCCR0 CCIFG
Enmascarable 0FFFA 13
Timer_B
TBCCR1 al TBCCR6 Enmascarable 0FFF8 12
CCIFGs, TBIFG*
Comparador_A
CAIFG
Enmascarable 0FFF6 11
Watch dog timer
WDTIFG
Enmascarable 0FFF4 10
Recepción USART0
URXIFG0
Enmascarable 0FFF2 9
Transm. USART0
UTXIFG0
Enmascarable 0FFF0 8
ADC12
ADC12IFG*
Enmascarable 0FFEE 7
Timer_A
TACCR0 CCIFG
Enmascarable 0FFEC 6
Timer_A
TACCR1 al TACCR2 Enmascarable 0FFEA 5
CCIFGs, TAIFG*
Puerto E/S P1
P1IFG.0 al P1IFG.7*
Enmascarable 0FFE8 4
Recepción USART1
URXIFG1
Enmascarable 0FFE6 3
Transm. USART1
UTXIFG1
Enmascarable 0FFE4 2
Puerto E/S P2
P2IFG.0 al P2IFG.7*
Enmascarable 0FFE2 1
DAC12
DAC12_0IFG,
Enmascarable 0FFE0 0, mínima
DAC12_1IFG;
DMA
DMA0IFG
al
DMA2IFG*
Tabla 1.14: Vectores de interrupción. Un “ * ” Indica múltiples fuentes de interrupción
19
1.2.5.2 Procesado de Interrupciones
Cuando una interrupción es requerida por un periférico, está habilitada la interrupción y el
bit GIE=1, se salta a la rutina de servicio a la interrupción. En el caso de NMI sólo hace
falta que esté a 1 el bit de habilitación individual.
Aceptación de una Interrupción
El tiempo de aceptación de una interrupción son seis ciclos de reloj, contando desde la
aceptación de la petición de interrupción hasta el inicio de la primera instrucción de la
rutina de servicio a la interrupción.
1) Finaliza instrucción en ejecución, si la interrupción está habilitada y el bit GIE=1 se
acepta la interrupción.
2) Se pone en pila PC.
3) Se pone en pila SR.
4) Se selecciona la interrupción más prioritaria de las que pidan servicio.
5) El flag de petición de interrupción es reseteado automáticamente. Los demás flags
siguen pidiendo interrupción.
6) El SR es limpiado a excepción del SCG0, el cual no cambia. Esto termina cualquier
modo de bajo consumo.
7) El contenido del vector de interrupción es volcado en PC, el programa continua con
la ejecución de la rutina de servicio a la interrupción.
Vuelta de una Interrupción
La interrupción debe terminar con la instrucción: RETI. El retorno tarda 5 ciclos en
ejecutar las siguientes acciones:
1) SR es retornado de pila
2) PC es tomado de pila y empieza la ejecución en la siguiente instrucción donde fue
interrumpido
Anidamiento de Interrupciones
El anidamiento de una interrupción es habilitado si se aserta el bit GIE=1 dentro de la
rutina de servicio a la interrupción, ya que GIE ha sido puesto a 0 al resetear SR.
20
1.3 Módulos periféricos
Existen varios módulos periféricos, en esta apartado se explicarán los puertos de
entrada/salida, el módulo reloj básico y los Timers, ya que son los que nos interesan para la
realización de este proyecto final de carrera..
1.3.1 Registros de los periféricos y especiales.
En el Anexo A se muestran unas tablas que recogen los registros de todos los módulos
periféricos y registros especiales. En estas tablas están todos los datos necesarios de cada
registro, así que nos serán muy útiles a la hora de programar los periféricos. El nombre
dado a los registros es el mismo que en las librarías del microcontrolador. Para cada
registro se especifica la dirección y el tipo de registro, es decir, si es de lectura/escritura,
sólo lectura o sólo escritura. También se especifica su estado inicial y el significado de
cada uno de sus bits.
En algunos registros el byte alto es utilizado como contraseña. A la hora de escribir en
ellos el byte alto debe valer el valor especificado en la contraseña, si no no se escribe y se
produce una violación de contraseña (KEYV).
21
1.3.2 Puertos E/S
1.3.2.1 Introducción
Los mecanismos MSP430 tienen implementados seis puertos digitales de E/S, P1-P6. Cada
puerto tiene ocho pins de E/S. Cada pin es configurable individualmente para entrada o
salida.
Los puertos P1 y P2 tienen capacidad para generar interrupciones. Cada línea de
interrupción para los puertos P1 y P2 puede ser individualmente habilitada y configurada
para proporcionar una interrupción por flanco ascendente o descendente en una señal de
entrada. Todas las líneas de P1 tienen un sólo vector de interrupción y todas las líneas de
P2 tienen otro vector de interrupción diferente.
Características de los puertos digitales de E/S:
- son programables individualmente
- aceptan cualquier combinación de E/S
- interrupciones configurables individualmente en P1 y P2
- registros de datos independientes
1.3.2.2 Registros
El puerto digital de E/S es configurado por software por el usuario.
Registros de entrada PxIN (registros sólo de lectura)
Cada bit del registro PxIN refleja el valor de la señal de entrada correspondiente si está
configurado en este modo. Bit=0 => entrada baja. Bit=1 => entrada alta
Registros de salida PxOUT
Cada bit del registro PxOUT es el valor a reflejar en la salida correspondiente. Bit=0 =>
salida baja. Bit=1 => salida alta
Registro de direcciones PxDIR
Cada bit del registro PxDIR selecciona la dirección del correspondiente pin, entrada o
salida, independientemente de la función del pin, entrada/salida o módulo periférico
funcional. Bit=0 => entrada.
Registro de selección de función PxSEL
Los pins del puerto están a menudo multiplexados con otros módulos de funciones de
periféricos. Cada bit del registro PxSEL es usado para seleccionar la función del pin-puerto
o módulo funcional periféricos. Bit=0 => función E/S. Bit=1 => módulo funcional
periférico. (Véase figura 1.5) Cuando un bit se ocupa para controlar un periférico no se
configura automáticamente como de entrada o salida, sino que es trabajo del programador
seleccionar el sentido correcto.
22
Figura 1.5: Designación de pines del microcontrolador
1.3.2.3. Interrupciones
Cada pin de los puertos P1 y P2 tiene capacidad para interrumpir, configurando los
registros PxIFG, PxIE y PxIES. El registro PxIFG puede ser testeado para determinar la
fuente de interrupción de P1 o P2.
Registros de los flags de interrupción P1IFG y P2IFG
Cada bit de PxIFGx es el flag de interrupción para el correspondiente pin de E/S y es
asertado cuando la señal de entrada seleccionada tiene un flanco en el pin. Todos los flags
de interrupción generan una petición de interrupción cuando sus correspondientes bits
PxIE y GIE están asertados.
Cada PxIFG debe ser reseteado por software. También se puede asertar, por software, para
generar una interrupción.
Las interrupciones son causadas por transición. Si algún flag es asertado durante la rutina
de servicio a la interrupción o después de RETI, el PxIFGx genera otra interrupción. Esto
asegura que cada transición es recibida.
Registro de flanco P1IES, P2IES.
Cada bit de PxIES selecciona el flanco de interrupción correspondiente. Bit=0 =>flanco
ascendente, bit=1 =>flanco descendente.
Registro de habilitación de interrupción P1IE, P2IE
Cada bit de PxIE habilita el flag de interrupción asociado a PxIFG. Bit=1 =>habilitado.
23
1.3.3 Módulo reloj básico
1.3.3.1 Introducción
Utiliza tres señales de relojes internos, el usuario puede seleccionar el mejor equilibrio de
rendimiento y bajo consumo.
Las fuentes de reloj son las siguientes:
• Un reloj que puede funcionar con cristales o resonadores cerámicos de baja
frecuencia o de alta frecuencia (LFXTCLK). El modo se selecciona por
software.
• Un reloj de alta frecuencia que usa cristales o resonadores cerámicos de alta
frecuencia (XT2CLK).
• Un oscilador interno de características RC controlado digitalmente mediante
registros de control (DCOCLK).
Con estas fuentes el módulo de reloj genera las siguientes tres señales:
• Reloj maestro (MCLK): que alimenta la CPU y el sistema y se puede generar
a partir de la señal de baja frecuencia, la de alta frecuencia o el oscilador
digital; que pueden dividirse por un factor de 1, 2, 4 u 8.
• Reloj de sub sistema (SMCLK): que alimenta a los periféricos seleccionados
por software. Se puede generar a partir de la señal de baja frecuencia, la de
alta frecuencia o el oscilador digital; que pueden dividirse por un factor de
1, 2, 4 u 8.
• Reloj auxiliar (ACLK): que alimenta a los periféricos seleccionados por
software. Se genera a partir de la señal de baja frecuencia dividida por un
factor de 1, 2, 4 u 8.
Esta flexibilidad en el sistema de reloj está especialmente indicada para ahorrar energía, ya
que se puede utilizar un cristal de baja frecuencia, por ejemplo 32 KHz, para los
periféricos, mientras la CPU se opera mediante el oscilador interno a una frecuencia que
puede ir de los 80 KHz a los 8 MHz, dependiendo de la configuración y características del
dispositivo en particular.
1.3.3.2 Operaciones
Después del encendido del sistema (PUC), MCLK y SMCLK son cargados con DCOCLK
a 800 kHz y ACLK es cargado desde LFXT1 en modo LF (“Low frecuency”).
Para configurar el reloj básico se usan los registros DCOCTL, BDSCTL1 Y 2. Estos
registros pueden ser reconfigurados por software durante la ejecución del programa.
1.3.3.3 Controlador Digital del Oscilador (DCO)
Características típicas RC. La frecuencia de DCO puede ser ajustada por software usando
los bits DCOx, MODx y RSELx.
Después de un encendido del sistema (PUC): RSELx=4 y DCOx=3
En la siguiente figura se observan los rangos de DCOx y RSELx:
24
Figura 1.6: Rangos de frecuencia según los bits DCOx y RSELx
Conectando una Rosc de 100kO desde el pin 25 (Periférico 2 bit 5) hasta el pin 1 (+Vcc) se
puede subir el rango de frecuencias ya que se disminuye el coeficiente de temperatura, así
se observan los valores de la siguiente tabla:
Voltaje
2
2
3.6
3.6
3.6
3.6
3.6
Rsel
7
7
7
6
7
7
6
DCO
7
6
6
6
7
5
7
Frecuencia (Mhz)
8.6
7.59
8.79
6.73
10
7.84
7.6
Tabla 1.23: Frecuencias obtenidas con un resistor externo de 100 kO
En la tabla observamos que se puede trabajar hasta los 10 MHz, pero la circuitería interna
del microcontrolador permite trabajar con seguridad hasta los 8 MHz y no se recomienda
utilizar frecuencias más altas.
25
1.3.4 Timers A y B
1.3.4.1 Introducción
Son temporizadores o contadores con registros de captura o comparación con la capacidad
de generar múltiples salidas e interrupciones.
El Timer_A es un contador de 16 bits con tres registros de captura/compara. Puede
soportar varias capturas/comparaciones, salidas PWM e intervalo de cronometraje.
También tiene capacidad de interrumpir. Las interrupciones son generadas desde el
contador al desbordarse o desde cada uno de los registros de captura/comparación.
Características:
• Timer de 16 bits asíncrono con 4 modos de operación
• Fuente de reloj seleccionable y configurable.
• Tres registros configurables de captura/comparación (TACCR0, TACCR1,
TACCR2)
• Capacidad de configurar la salida con PWM
• Entrada y salida asíncrona
• Registro de vector de interrupciones para una rápida decodificación de todas las
interrupciones del Timer_A
El registro de 16 bits del contador, TAR, se incrementa o decrementa dependiendo del
modo de operación, con cada flanco de subida de la señal de reloj. TAR puede ser leído o
escrito por software. Además, el timer puede generar una interrupción cuando se desborda.
El contador, TAR, puede ser borrado poniendo a 1 el bit TACLR. Asertando este bit
también se limpia el divisor del reloj y la dirección del contador para el modo arriba y
abajo.
Para modificar los registros es recomendable apagar el timer para evitar errores, a
excepción de la habilitación de interrupción y del flag de interrupciones.
Cuando el TACLK es asíncrono con el reloj de la CPU, cualquier lectura del TAR debería
hacerse con el timer parado o el resultado es impredecible. Cualquier escritura de TAR
tomará efecto inmediatamente.
El timer TACLK puede tener como fuente ACLK, SMCLK o vía externa el TACLK o
INCLK. La fuente de reloj es seleccionada con los bits TASSELx. La fuente de reloj
seleccionada debe pasar directamente al timer dividida por 2, 4 o 8 usando los bits IDx.
El Timer_B es idéntico al Timer_A con las siguientes excepciones:
• Tiene siete registros de captura o comparación
• La longitud del Timer_B es programable a 8, 10, 12 ó 16 bits
• Los registros TBCCRx son de doble buffer y pueden ser agrupados
• Todas las salidas del Timer_B pueden ser puestas en estado de alta impedancia
• En el Timer_B no está implementada la función del bit SCCI
26
1.3.4.2 Modos de Operación
El timer tiene cuatro modos de operación seleccionables por los bits MCx, se muestran en
la siguiente tabla:
MCx
00
01
10
11
Modo
Parado
Arriba
Continuo
Arriba/abajo
Descripción
El timer está suspendido
El timer repite cuentas de 0 al valor de TACCR0
El timer cuenta repetidamente de 0 a 0FFFFh
El timer cuenta repetidamente desde 0 al valor de
TACCR0 y desciende hasta 0
Tabla 1.24: Modos de operación del timer
El timer puede ser encendido o reiniciado por los siguientes medios:
• El timer cuenta cuando MCx>0 y la fuente de reloj está activa
• Cuando se trabaja en modo arriba o arriba/abajo, el timer se para escribiendo un 0
en TACCR0. Para encenderlo basta escribir un valor diferente de 0 en TACCR0.
En este caso, el timer empieza a contar desde 0.
Modo continuo
En el modo continuo, el timer cuenta repetidamente de 0 a 0FFFFh y reinicia desde 0 como
se muestra en la siguiente figura:
Figura 1.7: Modo continuo
El modo continuo puede ser usado para generar intervalos de tiempo independientes y
frecuencias de salida. Para generar intervalos de tiempo cargamos en el registro TACCRx
el valor del intervalo. Cada vez que el tiempo alcanza un intervalo, una interrupción es
generada. El próximo intervalo de tiempo debe ser añadido en los registros TACCRx en la
rutina de servicio a la interrupción. La siguiente figura muestra dos intervalos de tiempo t0
y t1 empezando en la carga de los registros de captura/compara.
Figura 1.8: Generación de intervalos de tiempo modo continuo
27
En este caso los intervalos de tiempo son controlados por hardware, no por software. Por
tanto no hay impacto en el tiempo de latencia de la interrupción, es decir no influye el
tiempo de entrada y salida de la rutina de servicio a la interrupción. Hasta tres intervalos de
tiempo o frecuencias de salida pueden ser generados usando los tres registros de
captura/compara.
1.3.4.3 Bloques de Captura y Comparación
Hay tres bloques idénticos, TACCRx, en el timer A. Cualquiera de ellos puede ser usado
para capturar la cuenta o para generar intervalos de tiempo.
Modo captura
Este modo guarda el tiempo en el que suceden algunos flancos en la señal de entrada
seleccionada. Para configurar el modo captura se utiliza el registro TACCTLx. El modo
captura es seleccionado cuando CAP=1. (Véase apartado 3.1).
Con los bits CCISx seleccionamos la señal de entrada. Se pueden utilizar señales externas,
configuradas en pines, o internas. Los bits CMx seleccionan la captura de la señal por
flanco ascendente, descendente o ambos.
Si una captura ocurre:
• El valor del timer es copiado en el registro TACCRx
• El flag de interrupciones CCIFG es puesto a 1.
El nivel de la señal de entrada puede ser leído en cualquier momento vía el bit CCI.
La captura de la señal puede ser asíncrona al tiempo de reloj. Poniendo un 1 en el bit SCS
se sincroniza la captura con la próxima señal de reloj. Es recomendable sincronizar la
captura con la señal de reloj.
Existe desbordamiento si se intenta guardar el valor de una captura y el valor de la captura
anterior no ha sido leído. El bit COV es 1 cuando esto ocurre, este bit debe ser puesto a 0
por software. En la siguiente figura se observa un ciclo de captura:
Figura 1.9: Ciclo de captura
En nuestro caso utilizaremos el modo captura en el registro 1 del Timer_A. La señal de
captura será la TA1, que encontramos en el pin 14 del microcontrolador, donde tenemos
conectada la señal DATA3 [Léase Capitulo 3]. Seleccionamos flanco ascendente. Así a
cada flanco ascendente de dicha señal se copia el valor del timer en el registro TACCR1 y
se provoca una interrupción. En ésta interrupción deberemos actuar en función de la
diferencia entre dos interrupciones consecutivas.
28
Modo comparación
El modo comparación es seleccionado cuando CAP=0. El modo comparación es usado
para generar señales de salida PWM o generar interrupciones a un específico tiempo.
1.3.4.4 Interrupciones
Hay dos vectores de interrupción asociados al Timer_A:
• Vector de interrupción TACCR0 para TACCR0 CCIF
• Vector de interrupción TAIV para todo los otros flags CCIFG y TAIFG
En modo captura cualquier flag CCIFG es asertado cuando el valor de un timer es
capturado en el registro asociado TACCRx.
En modo comparación, cualquier flag CCIFG es asertado si el contador TAR llegar al
valor asociado TACCRx. Por software se puede poner a 1 o a 0 cualquier flag CCIFG.
Todos los flags CCIFG piden una interrupción cuando su correspondiente bit CCIE y GIE
están asertados.
El flag TACCR0 CCIFG tiene la interrupción de más prioridad del Timer_A y tiene un
vector de interrupciones dedicado. El flag TACCR0 CCIFG es automáticamente reseteado
cuando la petición de interrupción TACCR0 es servida.
Los flags TACCR1 CCIFG, TACCR2 CCIFG y TAIFG son priorizados y combinados
para utilizar una sola fuente de interrupción y un vector. El registro TAIV es usado para
determinar que flag pidió interrupción. Este número puede ser evaluado o puesto en el
contador del programa para entrar automáticamente en la rutina de servicio. Deshabilitar
las interrupciones del Timer_A no afecta al valor del TAIV.
Cualquier acceso, de lectura o escritura, al registro TAIV resetea automáticamente la
petición de interrupción más prioritaria. Si otro flag es asertado, otra interrupción será
generada inmediatamente después de servir a la interrupción inicial.
29
1.4. Entorno del MSP430
Para crear programas se utiliza el: IAR Embedded Workbench 4.0. Este tiene una ayuda
muy completa, pero este documento pretende ser un resumen para iniciarse en su
programación.
Se pueden probar los ejemplos del kit, ofrecidos en la página web: www.msp430.com.
Para empezar necesitamos crear un “workspace”. Para hacer esto en el menú “File”,
“New” y seleccionamos “workspace”. El “workspace” será nuestro entorno de trabajo,
donde podemos ver los proyectos, los archivos de nuestro proyecto y modificarlos.
Figura 1.10: Crear un “workspace”
En un proyecto cargaremos todos los códigos fuente que sean necesarios y las librerías
para la correcta ejecución del programa.
Para crear un proyecto seleccionamos en el menú “Project” seleccionar “Create a New
Project” o “add existing project”.
Figura 1.11: Crear un proyecto
30
Entonces debemos agregar los archivos para el proyecto. Se puede crear un nuevo
documento fuente, para ello clicamos en nuevo y creamos un documento “source”, puede
ser en lenguaje c o ensamblador. Para agregarlos en el proyecto en el menú “Project”
seleccionamos “Add files”.
Antes de compilar hay que configurar algunas opciones del proyecto para ello, clicar en el
botón derecho del ratón y en el menú opciones proseguir con los siguientes pasos:
Ø En el menú general, pestaña Target, seleccionar el micro del que se dispone.
ATENCION si se ha programado en ensamblador clicar “Assembler only project”
si no al linkar nos saldrá un error.
Ø En el menú DEBUGGER seleccionar el driver deseado “Simulator” si solo
queremos probarlo sin el micro, pero ATENCION, los timers no cuentan en este
formato. [Pág 2-3 7] Si se desea simular en el micro seleccionar “Flash emulation
tool” y seleccionar el micro que tenemos conectado.
Un programa hecho en código C tiene limitaciones, como máximo puede ser de 4 K bytes.
Programado en ensamblador no tiene limitación.
Una vez hechas estas modificaciones ya podemos compilar y linkar el proyecto. Entonces
accedemos al “Debug” desde el menú “project” o clicando el icono (indicado en la figura
con un circulo rojo).
Figura 1.12: Acceder al “Debug” o compilador
Una vez aquí podemos ejecutar el programa:
• Paso a paso, en el menú “Debug” clicamos “Step over” o el icono indicado en la figura
1.13 con un circulo rojo. Ejecutando el programa de esta manera ejecutamos
instrucción a instrucción sin entrar en las llamadas a las funciones.
• Paso a paso entrando, en el menú “Debug” clicamos “Step into” o el icono indicado en
la figura 1.13 con un circulo azul. Ejecutamos el programa instrucción a instrucción y
cuando encuentra una llamada a una función entramos a ejecutarla paso a paso.
• Ejecutar, en el menú “Debug” clicamos “Go” o el icono indicado en la figura 1.13 con
un círculo verde. De esta manera se ejecuta el programa entero.
• Ejecutar hasta punto de ruptura, en el menú “Debug” clicamos “Go to cursor” o el
icono indicado en la figura 1.13 con un circulo amarillo. Ejecuta el programa hasta el
punto de ruptura.
31
Figura 1.13: Barra de herramientas del compilador
Figura 1.14: Menú del compilador
Se pueden editar condiciones de los puntos de ruptura, ver la memoria, los registros, ver
como van cambiando de valor las variables, ver la ventana de salida, ver el programa
desensamblado, editar posiciones de memoria.
Son muy útiles los puntos de ruptura condicionales, que por ejemplo paran el programa
cuando el Registro6==5, para generar estos puntos de ruptura en el menú ”View”,
“Breakpoints”, en la ventana seleccionamos con el botón derecho del ratón y “add
breakpoint conditional”.
32
2. Introducción a los Sistemas RFID
2.1 ¿Qué es un sistema RFID?
Los sistemas RFID (“Radio Frequency Identification”) consisten en tarjetas identificadoras
sin contacto con sistema de lectura. Estos dispositivos están sustituyendo a los códigos de
barras y a las tarjetas magnéticas ya que contienen toda la información del producto y
pueden ser leídas a distancia esto es una gran ventaja ya que es mucho más rápido.
En los sistemas RFID identificamos dos componentes:
• Etiqueta o Tag: es un chip con memoria y una antena, que puede ser leído/escrito a
distancia por el lector.
• Lector o Reader: es la unidad que transmite y/o recibe información de la etiqueta.
Es el interrogador.
Estos sistemas pueden ser clasificados de diferentes formas:
• Activos/Pasivos: una etiqueta activa usa batería, mientras que una pasiva no. Una
etiqueta pasiva emplea la energía recibida de la antena lectora rectificando su onda.
La consecuencia es que son más pequeñas y menos costosas, aunque cuentan con
un rango de menor distancia de lectura, y teóricamente tienen una vida indefinida.
• Sólo lectura/lectura-escritura: las etiquetas de sólo lectura son programadas durante
su manufactura y sus datos no pueden ser cambiados. Las etiquetas de lecturaescritura pueden actualizar o agregar información y por tanto son aplicables para
requerimientos de información variable.
Las ventajas son muchas:
• No es necesario que entre la tarjeta en contacto directo con el lector por eso es
mucho más rápida la adquisición de datos.
• Los chips pueden albergar gran cantidad de información
• Es un antirrobo muy sofisticado.
• Se pueden leer a través de muchos materiales, como la pintura, algo que no se
puede hacer con el código de barras.
La tecnología RFID no es sólo aplicable al etiquetado de productos, se puede utilizar en
muchas otras situaciones: para chips identificadores de mascotas, sistemas de acceso a
zonas restringidas, peajes en carreteras, facturación de equipajes más eficaz, para evitar
falsificación de moneda o de entradas en grandes eventos, etc.
Un obstáculo para su implantación es su precio, actualmente una etiqueta cuesta entre 20
céntimos y 50 euros, en función del número de unidades fabricadas. Eso sin contar lo que
lo valen los lectores. Los precios bajan continuamente, pero hasta que no cuesten uno o dos
céntimos no será rentable sustituir los códigos de barras.
33
2.2 ¿Cómo funciona?
El Reader o interrogador genera un campo de radiofrecuencia conmutando una bobina a
alta frecuencia. Las frecuencias usuales van desde 125 KHz hasta 2.4 GHz.
El campo de radiofrecuencia genera una corriente eléctrica sobre la bobina de recepción de
la tarjeta. En las tarjetas pasivas se rectifica esta señal para alimentar el circuito. Para
mejorar la eficiencia del circuito equivalente se conecta una capacidad en paralelo a la
bobina receptora para formar un circuito resonante. En la figura 2.1 observamos que en la
frecuencia de resonancia el circuito resonante tiene un pico de voltaje.
Figura 2.1: Trazo del voltaje en la bobina del transmisor en un rango de frecuencia de 1 a 100 MHz dando una fuerza
constante H. Una bobina con circuito paralelo resonante muestra un claro pico en la frecuencia de resonancia, 13.56
MHz.
El interrogador detecta los datos transmitidos como una perturbación del nivel de la señal.
34
2.3 Modulaciones
Normalmente el sistema de modulación usado par la transmisión de datos desde la tarjeta
al lector es modulación de amplitud con codificación tipo Manchester.
Para la transmisión de datos del lector a la tarjeta se utiliza modulación por amplitud
(ASK). Con esta modulación la amplitud de la portadora oscila entre dos estados u0 y u1
para un código binario. U1 puede tomar valores entre u0 y 0. La proporción de u0 y u1 es
conocida como el factor m.
Para encontrar el factor m calculamos la media aritmética de los valores de la señal
portadora:
û m= (û 0 + û 1 )/2
El factor se calcula desde la proporción de la amplitud de û 0 - û m a el valor medio û m.
m= ? û m / û m = (û 0 - û m )/ û m = (û 0 - û 1)/( û 0 + û 1)
En 100% ASK la amplitud de la portadora varia entre 2 û m y 0. Esto corresponde a un
factor m=1.
Figura 2.3: En modulación ASK la amplitud varía entre dos estados.
35
2.4. ISO 15693
El estándar ISO 15693 titulado ‘Tarjetas identificación-“contactless” tarjetas con circuitos
integrados- tarjetas cercanas’ describe el método de funcionamiento y operación de
pequeñas tarjetas acopladas. Estas pequeñas tarjetas con un rango de distancia de más de 1
m, son como las usadas en sistemas de control de acceso.
El estándar esta formado por las siguientes partes:
• Parte 1: Características físicas
• Parte 2: energía radio-frecuencia, interferencias y marco (todavía en preparación)
• Parte 3: Protocolos (en preparación)
• Parte 4: Registro de aplicaciones/emisores
Parámetro
Suministramiento
Modulación transferencia
Reader->Tag
Codificacion bit
Valor
13.56 MHz ± 7 kHz
10%ASK, 100%ASK
Comentario
Acoplamiento inductivo
La tarjeta soporta ambas
Modo larga distancia: 1 de 156
La tarjeta soporta ambas
Modo rápido: 1 de 4
Baud rate
Modo larga distancia: 1.65 Kbit/s
Modo rápido: 26.48 Kbit/s
Modulación transferencia Carga modulada con subportadora
Tag->Reader
Codificacion bit
Manchester, subportadora modulada con
ASK (423 kHz) o FSK (423/485 kHz)
Baud rate
Modo larga distancia: 6.62 Kbit/s
Seleccionado por el reader
Modo rápido: 26.48 Kbit/s
Tabla 2.1: Modulación y codificación utilizados en el ISO 15693 (Berger, 1998)
2.4.1 Interferencias e Inicialización
La energía de suministro de un acoplamiento inductivo en una tarjeta cercana (vicinity card
CICC) es provista por el campo magnético del lector (PCD) en una transmisión de
frecuencia 13.56 MHz. Las tarjetas cercanas incorporan una antena con una gran área para
su propósito, típicamente con 3-6 espiras conductoras.
Figura 2.4: Diseño de una tarjeta de contacto: con módulo transmisor y antena.
36
Figura 2.5: Tarjeta de contacto semitransparente.
2.4.2.1 Transferencia Reader -> Tag
Ambas modulaciones 10% ASK y 100% ASK son usadas para la transferencia de datos
desde el lector a la tarjeta. Indiferentemente de la modulación seleccionada, dos códigos
diferentes pueden ser seleccionados: ‘1 de 256’ o ‘1 de 4’.
Una tarjeta de proximidad debe, en principio, soportar ambos procesos: modulación y
código. Sin embargo, 10% ASK en combinación con ‘1 de 256’ es preferible en ‘modo
larga distancia’. En contraste, 100%ASK con ‘1 de 4’ puede ser usado para reducir el
rango o lectores protegidos.
código ‘1 de 256’ Este procedimiento es una modulación por posición de pulso (PPM).
Esto significa que el valor del digito a ser transferido es definido en un rango de valores de
0-255 por la posición en el tiempo del pulso. Así, 8 bits ( 1 byte) son transferidos. El
tiempo total de la transmisión para un byte es de 4833 ms. Esto se corresponde con el
tiempo de 512 slots de 9.44 µs.
Figura 2.6: En la codificación 1 de 256 se utilizan 512 slots de 9.44 µs. Se codifica de 0-255, es decir 1 byte.
Un pulso puede tener lugar en cualquier slot (incluyendo el 0). El valor n del digito
transferido puede ser fácilmente determinado con la posición del pulso:
Posición del pulso= 2n + 1
La velocidad de transferencia de un byte es 1.65 Kbit/s.
37
El inicio y el final de la transmisión son identificados como: “start of frame” (SOF) y “end
of frame” (EOF). Las señales para identificar SOF y EOF son seleccionadas en el estándar
como los dígitos que no pueden ocurrir durante la transmisión.
Figura 2.7: Estructura de un mensaje
La señal SOF del código ‘1 de 256’ consiste en dos pulsos de 9.44 µs separados por un
tiempo de slot de 56.65 µs (9.44 µs*6)
Figura 2.8: SOF en codificación 1 de 256
La señal de EOF consiste en un solo pulso de 9.44 µs, el cual es enviado en un slot llano
para diferenciarlo de un byte.
Figura 2.9: EOF, consiste en un pulso de modulación en posición par, para diferenciarlo de los otros datos.
código ‘1 de 4’ En esta codificación, la posición del pulso determina el valor de un digito.
Dos bits son transmitidos simultáneamente en un solo escalón: el valor de los bits
transferidos están en el rango 0-3. El tiempo total de la transmisión para un byte es de
75.52 µs, el cual corresponde al tiempo de ocho slots. Un pulso puede ser transmitido en
cualquier slot (empezando en 0). El valor de n puede ser determinado con la posición del
pulso:
Posición del pulso= 2n + 1
La velocidad de transmisión es 26.48 Kbit/s.
En el código ‘1 de 4’ la codificación para SOF esta hecha con dos pulsos de 9.44 µs
separados por un intervalo de 37.76 µs (9.44 µs*4).
Figura 2.10: SOF codificación 1 de 4
38
El primer digito es recibido después de una pausa de 18.88 µs después del segundo pulso
del bit de start.
Figura 2.11: Codificación 1 de 4. Se codifica de 0-3, es decir dos bits.
El fin de la transmisión es definido por EOF
39
2.4.2.2 Transferencia Tag-> Reader
La carga modulada con una subportadora es usada para transmitir desde una tarjeta a un
lector. La modulación resistiva o capacitiva puede ser escogida. La subportadora es
modulada con la codificación Manchester usando modulación ASK o FSK
Frecuencia subportadora
Proporción de divisor fc=12.56 MHz
ASK
423.75 kHz
fc/32
FSK
423.75kHz/484.28 kHz
fc/32; fc/28
Tabla 2.2: Frecuencias para subportadoras en modulación ASK o FSK
La modulación producida es seleccionada por el lector usando un bit de control en el titulo
de la transmisión del protocolo definido en la parte 3 del estándar. Por eso, ambos procesos
deben ser soportados por la misma tarjeta.
El ritmo de los datos puede ser escogido entre dos valores. El lector selecciona el ritmo a
través del bit de control en el titulo del protocolo de la transmisión, la tarjeta debe soportar
también ambos procesos.
Tipo de datos
Modo larga distancia
Modo rápido
ASK
6.62 Kbit/s
26.48 Kbit/s
FSK
6.62 Kbit/s/6.68 Kbit/s
26.48 Kbit/s/26.72 Kbit/s
Tabla 2.3: Tipos de datos de los modos de transmisión
40
3. Programando el Microcontrolador
3.1. Introducción
Este capítulo explica todos los elementos utilizados para realizar la comunicación Reader>Tag:
- Transmisor: Reader comercial de Texas Instruments
- Receptor: kit de desarrollo del MSP430F169 programado por nosotros (URV en
colaboración con la universidad de Perugia (Italia)), antena diseñada en la
universidad de Bologna (Italia) y GAL diseñada y programada en la universidad
de Barcelona (España).
Se dispone de la placa con la GAL programada en Barcelona. Esta GAL transforma la
señal modulada en tres señales de entrada al microcontrolador (DATA1-3). Estas señales
van conectadas a un puerto de E/S del microcontrolador. Forman un contador de 8 bits, que
en presencia de señal modulada se va incrementando cada 1.18 µs, en caso contrario, es
decir, en ausencia de señal, dichas señales permanecen con un valor constante. [4]
El mensaje enviado por el Reader seguirá la norma ISO15693, por tanto será una señal de
13.56 MHz con modulación ASK 100%.
La codificación de bit podrá ser 1 de 4 ó 1 de 256. Estos son procesos de modulación por
posición de pulso (PPM). Esto significa que los valores de los dígitos transferidos, 2 ó 8
bits respectivamente, vienen definidos por la posición del pulso. El tiempo está definido
por slots de 9.44 µs. Un pulso puede tener lugar en cualquier slot (incluso el cero) y a
partir de dicha posición obtendremos el valor de los bits enviados.
A continuación se explicará cada uno de los elementos para dicha comunicación. Acto
seguido se plantearán unas cuantas ideas para programar el micro, y las razones por las que
han sido rechazadas. Finalmente, se explica el programa definitivo y se muestran las
pruebas realizadas en la universidad de Perugia (Italia).
41
3.2. Elementos
El kit utilizado para la programación se muestra en la figura 3.1, en el se puede observar la
alimentación para la placa, que debe ser 3.6 V, el Reader, que va a ser el que envíe el
mensaje, la antena, la GAL y el microcontrolador.
Figura 3.1: Kit
En las pruebas realizadas en la universidad de Perugia (Italia) se ha utilizado un Reader de
Texas Instruments, “High Frecuency Midrange Reader Evaluation Kit” el cual tiene un
software para seleccionar el mensaje a enviar, los flags, el comando, la codificación y todo
lo relacionado con el mensaje. El mensaje que se ha enviado en las pruebas tiene las
siguientes características:
Figura 3.2: Software utilizado para el Reader (ISO MODE)
42
Figura 3.3: Software utilizado para el Reader (ISO OPCIONS 2)
Figura 3.4: Software utilizado para el Reader (COMANDS OPTIONS)
La GAL tiene los conectores para la antena, con ésta recibirá la señal Rfid. Está
programada para que DATA1-3 (fc/32, fc/64 y fc/128, señales de entrada al
microcontrolador) trabajen como un contador de base 8, que cuando exista señal modulada
se incremente y en ausencia de ella permanezca constante. Véase figura 3.8
Figura 3.5: La GAL
43
El kit de desarrollo del microcontrolador se muestra en la figura 3.6. Las señales DATA1-3
le entran en los pines 12-14 del periférico de E/S 1.
Figura 3.6: El microcontrolador
El mensaje enviado por el reader, según el ISO15693-3 [5], tiene el siguiente formato:
SOF
Flags
8 bits
Comando
8 bits
Parámetros
Datos
CRC
16 bits
EOF
Tabla 3.1: Formato de la pregunta enviada por el Reader
Un campo de un único byte se transmite con el bit de menos peso primero.
Un campo de varios bytes se transmite con el byte de menos peso primero, y cada byte se
transmite con el bit de menos peso primero.
Definamos cada campo:
• Flags: En las tablas 3, 4 y 5 del ISO 15693-3 [5] se define el valor de estos flags
según las condiciones marcadas para la respuesta que el tag debe enviar y para
utilizar un código de identificación cuando la pregunta va dirigida a un tag
específico
• Comandos: en la tabla 8 del ISO 15693-3 [5] se define el valor de este byte según
el comando que debe realizar la tag. Existen comandos obligatorios, opcionales y
sin uso, los cuales se pueden definir para crear unos comandos específicos para
nuestro tag.
• Parámetros y datos: Dependen del comando, vienen definidos en el apartado 10.3
del ISO 15693-3 [5].
• CRC: Código cíclico redundante de 16 bits que sirve para detectar errores en el
mensaje. Se calcula a partir de lo especificado en el anexo C del ISO 15693-3 [5]
44
3.3. Ideas para el programa
El objetivo es realizar un programa que sea capaz de recibir el mensaje enviado por el
reader. Como se ha dicho anteriormente dicho mensaje nos llegará en forma de contador de
8 bits. Es decir en los pines 12-14 del microcontrolador tenemos tres señales de diferente
frecuencia que se irán incrementando como un contador de base 8. Cuando exista “dead
zone” estos contadores permanecerán en un valor fijo y cuando termine la “dead zone”
volverán a incrementarse.
En la figura 3.7 observamos la señal Rfid en el canal 2 del osciloscopio. Nótese que hay
unos momentos en los que la señal se hace nula, al ser una modulación 100 % ASK. A
estos momentos les llamamos “dead zones” y determinaremos a partir de su posición los
bits enviados. La señal del canal 1 es DATA3, que es la más lenta de las enviadas por la
GAL al microcontrolador. Su periodo vale 9.44 µs. Observar que cuando hay señal Rfid
DATA3 va cambiando, en ausencia de ésta se queda constante en el último valor.
La primera idea, pensada en Perugia, a partir de la información enviada de la Universidad
de Barcelona[6], era generar un contador interno que contase igual que DATA1-3. El
problema es que el microcontrolador no puede contar a tanta velocidad, ya que DATA1
(fc/32) corresponde 423 kHz es decir a un periodo de 2.36 µs. Por tanto cada 1.18 µs
deberíamos cambiar el contador. Teniendo en cuenta que hay que entrar y salir de la rutina
de servicio a la interrupción, lo que conlleva 11 ciclos de reloj (en un reloj a 8 MHz
necesitamos 1.375 µs), el microcontrolador no tiene tiempo.
Una vez desechada la primera idea se propuso [6] que cuando el microcontrolador fuera
avisado de que había una nueva “dead zone” se procediera a decodificar los bits enviados.
El problema en este caso es que el microcontrolador no es avisado cuando hay “dead
zone”, ya que ésta se caracteriza por una permanencia en nivel. El microcontrolador es
interrumpido a cada flanco de la señal.
45
DEAD ZONE
Figura 3.7: Canal 1 DATA3. Canal 2 señal Rfid.
46
Los programadores de la GAL (UB) [4] han propuesto un programa que mira
periódicamente, cada 9.44 µs, el valor de los contadores y mientras éste permanezca
constante es que no hay dato ya que los contadores han completado el ciclo de cuentas.
Cuando se encuentra un valor diferente es porque el contador ha parado, por tanto detecta
una “dead zone” Es decir la primera vez que se lee el valor se adjudica ese valor como el
esperado, y las siguientes veces se compara con dicho valor. Veámoslo en la siguiente
imagen:
9.44us
Y=0
X=0
9.44us
Y=0
X=0
Y?X
Symbol Detected
Figura 3.8: Simulación con la GAL enviada desde Barcelona (UB)
El problema es que el tiempo que los contadores permanecen constantes es superior a 9.44
µs por lo tanto se podrían hacer las dos capturas en este tiempo. Se observará el valor
esperado pensado que desde la última captura ha realizado el ciclo de cuentas y en cambio
ha estado en una “dead zone” que se ha perdido:
47
9.44us
Y=6
X=6
9.44us
Y=6
X=6
Y=6
X=6
!
Figura 3.9: Simulación con la GAL enviada desde Barcelona (UB) modificada al caso en el que da problemas
Otro problema es el generar 9.44 µs ya que para ello se debe utilizar el timer a 6.78 MHz o
3.39 MHz, pero con estos valores, teniendo en cuenta el tiempo de entrada y salida de la
interrupción (11 ciclos de reloj) tenemos 53 y 21 ciclos de reloj, respectivamente, lo cual
corresponde a aproximadamente 10 y 4 instrucciones, con lo que no tenemos tiempo hacer
todo lo necesario.
Además para que esto fuera factible necesitaríamos un reloj sin error, ya que necesitamos
observar el valor de los contadores cada 9.44 µs exactamente y esto no es posible con el
reloj del microcontrolador ya que hay que tener en cuenta la tolerancia de éste. Según su
data sheet Pág. 37[2], cargando el timer con el oscilador (DCO) y funcionando con una
resistencia externa de 100 kO, dicho timer tiene una tolerancia del ±15 %, además de ±0.1
%/ºC +10%/V, y por lo tanto no es seguro que los intervalos sean exactamente de 9.44 µs.
48
3.4. Programa final
Finalmente he pensado utilizar la señal DATA3, que se encuentra en la entrada del
microcontrolador correspondiente a TA1, como entrada del timer A. Se configura el timer
A en modo captura para que se produzca interrupción en el flanco ascendente de dicha
señal. Guardaremos los tiempos en que ocurren dichas interrupciones, compararemos el
valor entre dos flancos consecutivos para detectar las “dead zones”.
Cuando hay señal Rfid este valor será de 9.44 µs. En ausencia de señal este valor debe
estar entre 9.44µs+ t2 y 9.44µs+t1+t4 (t1 y t4 quedan especificados en la fig 1 [7]). Por
tanto se ha escogido 10 µs. Si la diferencia entre dos flancos es más pequeña, no haremos
nada, ya que se trata de momento en el que no hay dato, si es mayor, indica que ha habido
ausencia de señal, por tanto se ha recibido un dato. Dependiendo del momento en el que
nos encontremos, (SOF, recibiendo datos o EOF) se actuará de una manera o de otra.
Para reconocer estos momentos se utilizan unos flags, que decidimos ubicar en el registro
8:
Bit 15 Bit 14
Bit 13 Bit 12 Bit 11
Bit 0
SOF
Reciving 1de4
EOF
error
Tabla 3.6: Flags utilizados para la transmisión (R8)
Bit 15; SOF: Cuando este bit vale 1 indica que se ha recibido la primera “dead
zone” y estamos esperando la segunda para identificar el carácter SOF.
Bit 14; Revicing: Cuando este bit vale 1 indica que se está recibiendo el mensaje, es
decir que nos encontramos entre SOF y EOF.
Bit 13; 1of4: Cuando este bit vale 1 indica que se está trabajando en codificación 1
de 4, en caso contrario se trabaja con 1 de 256.
Bit 12; EOF: Cuando este bit vale 1 indica que se ha finalizado la recepción de
“dead zones”, si el bit de error está asertado indica que se ha recibido el EOF
correctamente.
Bit 11; error: Este bit vale 1 cuando se ha recibido la “dead zone” en posición par.
Necesitamos un contador de slots para detectar la posición de la “dead zone” y poder
decodificar el valor de los caracteres recibidos.
Se utilizarán dos registros para almacenar el valor del timer entre dos flancos consecutivos
de DATA3 y así poder calcular su diferencia, para la cual se utilizará un registro auxiliar.
El valor del timer en el flanco anterior estará en R4, el valor actual en R5 y la variable
auxiliar para los cálculos será el R9.
El Timer_A debemos inicializarlo para que trabaje con la resistencia externa. Se ha
escogido una frecuencia de 7.68 MHz, ya que es la más cercana que se ha conseguido a 8
MHz (frecuencia con la que se quería trabajar) sin superarla, porque en las especificaciones
del microcontrolador se recomienda que no trabaje a más de dicha frecuencia. Lo
configuramos en modo captura, donde DATA3 debe ser la señal de entrada,
CCI1A=DATA3.
49
Guardaremos los bits/bytes recibidos a partir de la dirección 0200h, al principio de la
RAM. Utilizamos un registro R7 como puntero a esta dirección, que se irá incrementando
tal y como vayamos guardando datos. Así al finalizar la recepción del mensaje tendremos
los bits/bytes recibidos entre las direcciones 0200h y (R7-1).
50
3.4.1 Pseudocódigo del programa.
Rutina servicio a la interrupción Timer_A
{
si (Dead_zone())
{
si ( primera_dead_zone())
{
recibiendo_SOF();
}
sino
{
si ( segunda_dead_zone())
{
inicialización_recepción();
}
sino
{
salvar_bits/byte();
si (contador_par())
{
error();
}
actualizar_contador();
}
}
}
sino
{
si (contamos_slots())
{
incrementar_contador ();
si (contador_slots_desvordado())
{
fin_recepción();
}
}
}
}
Explicación de las funciones:
§ Dead_zone(): esta función actualiza los valores del timer y calcula la diferencia entre
ellos. Si la diferencia es más grande que el valor esperado la función es evaluada como
cierto, en caso contrario se evalúa falso. El valor esperado es 10 µs*fCLK. Por tanto este
programa tan solo funciona bien para frecuencias de reloj fijas y predeterminadas. Este
será uno de los puntos a tratar en el apartado de propuestas para mejorar el programa.
§ Primera_dead_zone(): en esta función se mira si está a 1 alguno de los bits SOF,
Reciving o EOF. Si ninguno vale 1 es que es la primera vez que se entra, por tanto se
trata de la primera “dead zone” y devuelve cierto, en caso contrario devuelve falso.
§ Recibiendo_SOF(): esta función pone a 1 el flag SOF, realiza las inicializaciones
pertinentes y empezamos a contar slots, ya que el número de slots entre la primera y la
segunda “dead_zone” nos indicará la codificación en la que se recibe el mensaje.
§ Segunda_dead_zone(): Esta función mira si el bit SOF vale 1, si es así se evalúa como
cierto, ya que estamos esperando la segunda “dead zone” de este carácter. En caso
contrario se evalúa como falso.
§ Inicialización_recepción(): Esta función pone a 0 el flag SOF, ya que ya se ha recibido
dicho carácter y pone a 1 el flag Reciving. Según el valor del contador de slots adjudica
51
§
§
§
§
§
§
§
§
la codificación utilizada, 1 de 4 ó 1 de 256. Se realizan las inicializaciones pertinentes
para empezar a recibir caracteres del mensaje y se sigue contando slots.
Salvar_bits/byte(): esta función guarda el valor de los caracteres recibidos en una
posición de memoria e incrementa el puntero a dicha posición. Se realizan las
inicializaciones pertinentes para seguir recibiendo caracteres.
Contador_par(): Esta función mira si el contador de slots se encuentra en posición par,
en cuyo caso se evalúa como cierto. En caso contrario se evalúa falso.
Error(): Esta función decrementa en uno el contador, vuelve a calcular el valor del
carácter recibido y lo guarda en la posición donde se guardó el dato erróneo. Pone a 1 el
bit de error. Esto sucederá en el caso de recibir el EOF, por tanto cuando tengamos el bit
de error a 1 y el flag de SOF a 1 se habrá recibido el mensaje correctamente.
Actualizar_contador(): Esta función pondrá el contador en el valor necesario para
recibir el siguiente carácter correctamente. Al inicio de la recepción de un nuevo
carácter el contador deberá valer 0 e ir incrementándose a cada slot. Cuando recibimos
la “dead zone” deberemos ponerle el valor necesario para que al inicio del próximo
carácter adquiera el valor 0.
Contamos_slots(): esta función mira si es necesario contar slots, es decir si el bit SOF o
Reciving vale 1, en cuyo caso se evalúa como cierto. Es necesario contar slots cuando
se está recibiendo “dead zones” para situarlas y poder decodificar los bits recibidos.
Incrementar_contador(): Esta función incrementa el valor del contador de slots.
Contador_slots_desvordado(): En esta función miramos si el contador de slots ha
sobrepasado el máximo número de slots de un carácter. Para la codificación 1 de 4 el
máximo es 8, ya que es el número de slots de un carácter. Para la codificación 1 de 256
el máximo es 513.
Fin_recepción(): esta función pone a 1 el bit EOF. Si este bit y el bit de error están a 1
es que se ha recibido el mensaje correctamente. Si el bit EOF vale 1 y el bit de error
vale 0 es que la comunicación se ha cortado o no se ha recibido correctamente el
carácter EOF.
52
3.4.2 Diagrama de flujo del programa.
RSI_TA
DEAD ZONE?
Entramos en la rutina de servicio a interrupción a cada flanco ascendente de DATA3
NO
SI
1º DEAD ZONE?
NO
NECESITAMOS
CONTAR SLOTS?
SI
SI
RECIBIENDO SOF
NO
NO
2º DEAD ZONE?
SALVAR
BITS/BYTE
INICIALIZACIÓN
RECEPCIÓN
SI
CONT. EN
POSICION PAR?
INCREMENTAR
CONTADOR
NO
SI
NO
ERROR
Nº SLOTS > MÁXIMO?
SI
ACTUALIZAR
CONTADOR
FIN
RECEPCIÓN
FIN
53
3.5. Pruebas
Estas pruebas han sido realizadas en la universidad de Perugia (Italia) los meses de mayo y
junio del 2005. Para ellas se ha utilizado el Reader comercial de Texas Instruments, la
antena diseñada en la universidad de Perugia, la GAL diseñada y programada en Barcelona
y el microcontrolador MSP430F169 con nuestro programa.
En la figura 3.10 observamos un SOF y los primeros bits recibidos (11.00). En esta prueba
se utiliza la codificación 1 de 4:
SOF
11
00
Figura 3.10: Imagen capturada por el osciloscopio donde observamos SOF y los primeros 4 bits enviados
El mensaje que estamos enviando viene definido por lo siguientes parámetros:
Los flags serán de menos a más significativo:
11.00.00.00
El código del comando leer un solo bloque, de bit menos significativo a más significativo:
00.00.10.00
El numero del bloque:
00.00.00.00
El CRC, no se calcula en el estado actual del proyecto.
54
Enviamos el comando Read Single Block codificado en 1de4, por lo tanto debemos recibir:
3.0.0.0.0.0.2.0.0.0.0.0.x.x.x.x.x.x.x.x.0. (Figura 3.11). Observamos que en la dirección
200h de la RAM se ha recibido el mensaje correctamente (Abajo izquierda recuadro rojo).
Los registros se pueden ver a la derecha de la imagen (Recuadro azul). Obsérvese que el
contador de slots, R6, ha llegado a 9 valor inalcanzable si se sigue recibiendo mensaje, por
esa razón se ha parado de recibir. Además en el R8 observamos que el bit de error (bit 11)
vale 1, así que la “dead zone” anterior se encontraba en posición par. El puntero a la
dirección donde está el mensaje apunta a la dirección 0215h, por tanto el mensaje está
entre la dirección 0200h y la 0214h, ya que el último carácter recibido es el EOF.
Se ha pegado el cuadro de configuración del ISO del reader para observar la codificación
del mensaje. (Recuadro amarillo)
Figura 3.11: Read Single Block codificado en 1de4
55
Enviamos el comando Write Single Block, en codificación 1de4, debemos recibir:
3.0.0.1.1.0.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.x.x.x.x.x.x.x.x.0.
Figura
3.12.
Observamos que en la dirección 200h de la RAM se ha recibido el mensaje correctamente
(Abajo izquierda). Los registros se pueden ver a la derecha de la imagen. Obsérvese que el
contador de slots, R6, ha llegado a 9 como se ha comentado anteriormente. Además en el
R8 observamos que el bit de error (bit 11) vale 1, así que la “dead zone” anterior se
encontraba en posición par. El puntero a la dirección donde está el mensaje apunta a la
dirección 0225h, por tanto el mensaje está entre la dirección 0200h y la 0224h, ya que el
último carácter recibido es el EOF.
Se ha pegado el cuadro de configuración del ISO del reader para observar la codificación
del mensaje.
Figura 3.12: Write Single Block codificado en 1de4
56
Enviamos Read Single Block codificado en 1de256: 03.20.00.x.x.0. Figura 3.13
Observamos que en la dirección 200h de la RAM se ha recibido el mensaje correctamente
(Abajo izquierda). Los registros se pueden ver a la derecha de la imagen. Obsérvese que el
contador de slots, R6, ha llegado a 201h valor inalcanzable si se siguen recibiendo
mensaje, por esa razón se ha parado de recibir. Además en el R8 observamos que el bit de
error (bit 11) vale 1, así que la “dead zone” anterior se encontraba en posición par. El
puntero a la dirección donde está el mensaje apunta a la dirección 0206h, por tanto el
mensaje está entre la dirección 0200h y la 0205h, ya que el último carácter recibido es el
EOF.
Se ha pegado el cuadro de configuración del ISO del reader para observar la codificación
del mensaje.
Figura 3.13: Read Single Block codificado en 1de256
57
Enviamos Write Single Block codificado en 1de256, debemos recibir:
43.21.00.00.00.00.00.x.x.0. Figura 3.14
Observamos que en la dirección 200h de la RAM se ha recibido el mensaje correctamente
(Abajo izquierda). Los registros se pueden ver a la derecha de la imagen. Obsérvese que el
contador de slots, R6, ha llegado a 201h valor inalcanzable si se siguen recibiendo
mensaje, por esa razón se ha parado de recibir. Además en el R8 observamos que el bit de
error (bit 11) vale 1, así que la “dead zone” anterior se encontraba en posición par. El
puntero a la dirección donde está el mensaje apunta a la dirección 020Ah, por tanto el
mensaje está entre la dirección 0200h y la 0209h, ya que el último carácter recibido es el
EOF.
Se ha pegado el cuadro de configuración del ISO del reader para observar la codificación
del mensaje.
Figura 3.14: Write Single Block codificado en 1de256
58
3.6 Ideas para mejorar el programa
La primera cosa que debemos mejorar es que el programa pueda trabajar a frecuencias de
reloj variables. Para ello se debería crear una función que, al entrar en zona RFID,
calculase el número de ciclos de reloj entre dos flancos consecutivos de DATA3. Este
valor seria con el que deberíamos comparar a la hora de detectar “dead zones”.
Además se tendría que hacer un programa cíclico si se quiere recibir más de un mensaje.
Ya que el elaborado tan sólo puede recibir un mensaje.
59
Referencias
[1]. Klaus Finkenzeller, RFID Handbook: Fundamentals and Applications in Contactless
Smart Cards and Identification, John Wiley & Sons, Ltd.ISBN: 0-470-84402-7
[2].MSP430x15x, MSP430x16x, MSP430x161x MIXED SIGNAL
MICROCONTROLLER. SLAS368C. OCTOBER 2002. REVISED MARCH 2005
http://www.cs.utah.edu/classes/cs7962/lab1/msp430f1611.pdf (Septiembre 2005)
[3]. MSPX1XX FAMILY USER’S GUIDE. MIXED SIGNALMICROCONTROLLER.
SLAU049C.
http://www.ece.uah.edu/~raskovd/cpe421/manuals/slau049c.pdf (Septiembre 2005)
[4]. Documento interno: FLEXIBLE TAG REV1 DOCUMENTATION
[5]. ISO/IEC 15693-3:2001 Identification cards - Contactless integrated circuit(s) cards Vicinity cards -- Part 3: Anticollision and transmission protocol
[6]. Documento interno: FLEXIBLE TAG DOCUMENTATION
[7]. ISO/IEC 15693-2:2000 Identification cards -- Contactless integrated circuit(s) cards - Vicinity cards -- Part 2: Air interface and initialization
60
Anexo A: Registros de los periféricos y especiales
NOMBRE
CORTO
@
(h)
TI
PO
Control
WDT
WDTCTL
0120
L/E
ESTAD
O
INICIA
L
06900
PUC
WATCHDOG
FUNCIÓN
REGISTRO
15
8
7
6
5
4
3
2
1
0
WDTPW
WDTHOLD
WDTNMIES WDTNMI
WDTTMSEL
WDTCNTCL
WDTSSEL
WDTISx
WDTPW: Contraseña, es leída como 069h, debe ser escrita como 05Ah
WDTHOLD: Utilizado para parar el WDT si vale 1 WDT parado
WDTNMIES: Selecciona si la NMI es por nivel o por flanco, si vale 1 es por flanco.
WDTNMI: Selecciona la función del bit RST/NMI, si vale 1 función NMI
WDTTMSEL: Selecciona el modo del timer, watchdog o intervalo, si vale 1 modo intervalo
WDTCNTCL: Asertándolo a 1 limpia el valor del contador a 0000h. Es reseteado automáticamente
WDTSSEL: Selecciona la fuente de reloj, SMCLK o ACLK, si vale 1 ACLK
WDRISx: Seleccionan el intervalo. 00= fuente del reloj/32768, 01= fuente del reloj/8192, 10= fuente del reloj/512, 11= fuente del reloj/64
MÓDULO RELOJ BÁSICO
Tabla A.1: Registros Watchdog
Controlador reloj 2
BCSCTL2
058
L/E
RESET X POR
Controlador reloj 1
BCSCTL1
057
L/E
084h X PUC
Controlador DCO
DCOCTL
056
L/E
060h X PUC
7
6
5
4
3
2
1
0
SELMx
DIVMx
SELS
DIVSx
DCOR
SELMx: Selecciona la fuente del reloj maestro. 00=01= DCOCLK, 10 XT2CLK y 11= LFXT1CLK
DIVMx: Divisor parael reloj maestro. 00= /1, 01= /2, 10= /4 y 11= /8.
SELS: Selecciona la fuente del reloj de sub sistema. 0= DCOCLK, 1= XT”CLK
DIVSx: Divisor para el reloj de sus sistema. 00= /1, 01= /2, 10= /4 y 11= /8.
DCOR: Selecciona el resistor del DCO: 1= externo, 0= interno
7
6
5
4
3
2
1
0
XT2OFF
XTS
DIVAx
XT5V
RSELx
XT2OFF: Este bit apaga el oscilador XT2. Cuando es 1 apagado
XTS: Selecciona el modo LFXT1. 1 altas frecuencias, 0 bajas frecuencias.
DIVAx; Divisor para el reloj auxiliar. 00= /1, 01= /2, 10= /4 y 11=/8.
XT5V: Sin usar. Debe ser siempre 0.
RSELx: Selector de resistencia. Esta resistencia interna selecciona una de las ocho frecuencias.
7
5
4
0
DCOx
MODx
DCO: Selector de frecuencia. Estos tres bits seleccionan una de las ocho frecuencias según el valor de RSELx seleccionado.
MODx: Selecciona el modulador. Definen cuantas veces la frecuencia fDCO+1 es usada en un periodo de 32 ciclos de DCOCLK. No se utiliza si
DCOx=07h ya que entonces siempre es el más alto rango.
Tabla A.2: Registros Módulo reloj básico
61
TIMER B7
Vector interrupciones
Timer B
TBIV
011E
L
RESET X
POR
Control Timer_B
TBCTL
0180
L/E
RESET X
POR
15
4 3
1
0
0
TBIVx
0
TBIVx: Valor del vector de interrupción
Contenido TBIV (h)
Fuente de interrupción
Flag de interrupción
Prioridad de la interrupción
00
No hay interrupción
pendiente
02
Captura/compara 1
TBCCR1 CCIFG
Máxima
04
Captura/compara 2
TBCCR2 CCIFG
06
Captura/compara 3
TBCCR3 CCIFG
08
Captura/compara 4
TBCCR4 CCIFG
0A
Captura/compara 5
TBCCR5 CCIFG
0C
Captura/compara 6
TBCCR6 CCIFG
0E
Tiempo desbordado
TBIFG
Mínima
15
8
Sin uso
TBCLGRPx
CNTLx
Sin uso
TBSSELx
7
0
IDx
MCx
Sin uso
TBCLR
TBIE
TBIFG
TBCLGRP: estos bits indican los registros TBCLx que son agrupados
TBCLGRPx
AGRUPADOS
CONTROL
00
Ninguno
Individual
01
TBCL1+TBCL2
TBCCR1
TBCL3+TBCL4
TBCCR3
TBCL5+TBCL6
TBCCR5
TBCL0 independiente
10
TBCL1+TBCL2+TBCL3
TBCCR1
TBCL4+TBCL5+TBCL6
TBCCR4
TBCL0 independiente
11
TBCL0+TBCL1+TBCL2+
TBCCR1
TBCL3+TBCL4+TBCL5+TBCL6
CNTLx: Indican la longitud del contador: 00=16 bits( TBRmax= FFFFh); 01=12 bits, (TBRmax= FFFh); 10=10 bits, (TBRmax= 03FFh);
11=8 bits, (TBRmax= 0FFh)
TBSSELx= Indican la fuente de reloj: 00= TBCLK; 01= ACLK; 10= SMCLK; 11=INCLK
IDx: Estos bits indican el valor del divisor del reloj. 00: /1; 01= /2; 10= /4; 11= /8
MCx: Estos bits indican el modo de control. Cuando vale 00 el Timer_B está apagado y por tanto no consume; 01 está en modo arriba;
10 está en modo continuo y 11 está en modo arriba/abajo
TBCLR: Asertando este bit se resetea TBR, el divisor del reloj y la dirección de la cuenta. Es automáticamente reseteado y al leerlo
siempre se lee 0
TBIE: Habilitación de las interrupciones TBIFG. Cuando está a 1 las interrupciones están habilitadas.
TBIFG: Cuando está a 1 indica que hay alguna interrupción pendiente.
Tabla A.3: Registros Timer B
62
TIMER B7
Control cap/com 0
Control cap/com 1
Control cap/com 2
Control cap/com 3
Control cap/com 4
Control cap/com 5
Control cap/com 6
TBCCTL0
TBCCTL1
TBCCTL2
TBCCTL3
TBCCTL4
TBCCTL5
TBCCTL6
0182
0184
0186
0188
018A
018C
018E
L/E
L/E
L/E
L/E
L/E
L/E
L/E
RESET X POR
RESET X POR
RESET X POR
RESET X POR
RESET X POR
RESET X POR
RESET X POR
Contador Timer_B
TBR
0190
L/E
RESET X POR
Cap/com 0
Cap/com 1
Cap/com 2
Cap/com 3
Cap/com 4
Cap/com 5
Cap/com 6
TBCCR0
TBCCR1
TBCCR2
TBCCR3
TBCCR4
TBCCR5
TBCCR6
0192
0194
0196
0198
019A
019C
019E
L/E
L/E
L/E
L/E
L/E
L/E
L/E
RESET X POR
RESET X POR
RESET X POR
RESET X POR
RESET X POR
RESET X POR
RESET X POR
15
8
CMx
CCISx
7
SCS
CLLDx
CAP
0
OUTMODx
CCIE
CCI
OUT
COV
CCIFG
CMx: Indican el modo de captura: 00 no se captura; 01 captura en flanco ascendente; 10 captura en flanco descendente; 11 captura en ambos flancos
CCISx: Estos bits seleccionan la señal de entrada de TBCCRx. 00 CCIxA; 01 CCIxB; 10 GND; 11 Vcc.
SCS: Este bit es usado para sincronizar la señal de entrada de una captura con el reloj. Cuando vale 1 están sincronizados.
CLLDx: Estos bits seleccionan el momento de carga.
CLLDx Descripción
00
El nuevo dato es transferido desde TBCCRx a TBCLx inmediatamente cuando TBCCRx es escrito.
01
El nuevo dato es transferido desde TBCCRx a TBCLx cuando la cuenta de TBR se hace 0.
10
El nuevo dato es transferido desde TBCCRx a TBCLx cuando la cuenta de TBR se hace 0 para
modo continuo. El nuevo dato es transferido desde TBCCRx a TBCLx cuando la cuenta de TBR se
hace el antiguo valor de TBCL0 o 0 para el modo arriba/abajo
11
El nuevo dato es transferido desde TBCCRx a TBCLx cuando la cuenta de TBR se hace el antiguo
valor de TBCLx
CAP: Cuando este bit está a 1 se está en modo captura.
OUTMODx: Indican el modo de salida. Los modos 2, 3, 6 y 7 no son útiles para TBCL0 porque EQUx=EQU0.
000
Salida
001
Asertado
010
Permanece/Desasertado
011
Asertado/Desasertado
100
Permanece
101
Desasertado
110
Permanece/asertado
111
Desasertado/asertado
CCIE: Cuando está a 1 están habilitadas las interrupciones correspondientes al flag CCIFG
CCI: el canal de entrada seleccionado puede ser leído en este bit
OUT: este bit indica el estado de la salida: para modo de salida 0 este bit controla directamente el estado de la salida
COV: este bit a 1 indica que ha ocurrido una captura. Debe ser reseteado por software
CCIFG: Este bit indica que hay una interrupción pendiente de captura/compara
15
0
TBRx
TBRx: valor del contador del Timer_B
-
Tabla A.4: Registros Timer B II
63
TIMER A3
Vector interrupciones
Timer_A
TAIV
012E
L
RESET X POR
Control Timer_A
TACTL
0160
L/E
RESET X POR
15
4 3
1
0
0
TAIVx
0
TAIVx: Valor del vector de interrupción
Contenido TAIV (h)
Fuente de interrupción
Flag de interrupción
Prioridad de la interrupción
00
No hay interrupción
pendiente
02
Captura/compara 1
TACCR1 CCIFG
Máxima
04
Captura/compara 2
TACCR2 CCIFG
06
Reservado
08
Reservado
0A
Tiempo desbordado
TAIFG
0C
Reservado
0E
Reservado
Mínima
15
8
Sin uso
TASSELx
7
0
IDx
MCx
Sin uso
TACLR
TAIE
TAIFG
TASSELx= Indican la fuente de reloj: 00= TACLK; 01= ACLK; 10= SMCLK; 11=INCLK
IDx: Estos bits indican el valor del divisor del reloj. 00: /1; 01= /2; 10= /4; 11= /8
MCx: Estos bits indican el modo de control. Cuando vale 00 el Timer_A está apagado y por tanto no consume; 01 está en modo arriba;
10 está en modo continuo y 11 está en modo arriba/abajo
TACLR: Asertando este bit se resetea TAR, el divisor del reloj y la dirección de la cuenta. Es automáticamente reseteado y al leerlo
siempre se lee 0
TAIE: Habilitación de las interrupciones TAIFG. Cuando está a 1 las interrupciones están habilitadas.
TAIFG: Cuando está a 1 indica que hay alguna interrupción pendiente
Tabla A.5: Registros Timer A
64
Control cap/com 0
Control cap/com 1
Control cap/com 2
TACCTL0
TACCTL1
TACCTL2
0162
0164
0166
L/E
L/E
L/E
RESET X POR
RESET X POR
RESET X POR
15
8
CMx
CCISx
SCS
7
SCCI
Sin uso
CAP
0
OUTMODx
CCIE
CCI
OUT
COV
CCIFG
CMx: Indican el modo de captura: 00 no se captura; 01 captura en flanco ascendente; 10 captura en flanco descendente; 11 captura en
ambos flancos
CCISx: Estos bits seleccionan la señal de entrada de TACCRx. 00 CCIxA; 01 CCIxB; 10 GND; 11 Vcc.
SCS: Este bit es usado para sincronizar la señal de entrada de una captura con el reloj. Cuando vale 1 están sincronizados.
SCCI: Sincroniza la señal de entrada captura/comparación. La señal de entrada seleccionada CCI es lacheada cuando la señal EQUx.
CAP: Cuando este bit está a 1 se está en modo captura.
OUTMODx: Indican el modo de salida. Los modos 2, 3, 6 y 7 no son útiles para TACL0 porque EQUx=EQU0.
000
Salida
001
Asertado
010
Permanece/Desasertado
011
Asertado/Desasertado
100
Permanece
101
Desasertado
110
Permanece/asertado
111
Desasertado/asertado
CCIE: Cuando está a 1 están habilitadas las interrupciones correspondientes al flag CCIFG
CCI: el canal de entrada seleccionado puede ser leído en este bit
OUT: este bit indica el estado de la salida: para modo de salida 0 este bit controla directamente el estado de la salida
COV: este bit a 1 indica que ha ocurrido una captura. Debe ser reseteado por software
CCIFG: Este bit indica que hay una interrupción pendiente de captura/compara
Reservado
Reservado
Reservado
Reservado
Contador Timer_A
TAR
0168
016A
016C
016E
0170
L/E
RESET X POR
15
0
TARx
TIMER A3
TARx: valor del contador del Timer_A
Cap/com 0
Cap/com 1
Cap/com 2
Reservado
Reservado
Reservado
Reservado
TACCR0
TACCR1
TACCR2
0172
0174
0176
0178
017A
017C
017E
L/E
L/E
L/E
RESET X POR
RESET X POR
RESET X POR
Tabla A.6: Registros Timer A II
65
PUER
TO P6
PUER
TO P5
PUER
TO P4
PUER
TO P3
PUERTO P2
PUERTO P1
Puerto seleccionado
Dirección
Salida
Entrada
Puerto seleccionado
Dirección
Salida
Entrada
Puerto seleccionado
Dirección
Salida
Entrada
Puerto seleccionado
Dirección
Salida
Entrada
Puerto seleccionado
Habilitación int.
Selector nivel int.
Flag de interrupción
Dirección
Salida
Entrada
Puerto seleccionado
Habilitación int.
Selector nivel int.
Flag de interrupción
Dirección
Salida
Entrada
P6SEL
P6DIR
P6OUT
P6IN
P5SEL
P5DIR
P5OUT
P5IN
P4SEL
P4DIR
P4OUT
P4IN
P3SEL
P3DIR
P3OUT
P3IN
P3SEL
P2IE
P2IES
P2IFG
P2DIR
P2OUT
P2IN
P1SEL
P1IE
P1IES
P1IFG
P1DIR
P1OUT
P1IN
037
036
035
034
033
032
031
030
01F
01E
01D
01C
01B
01A
019
018
02E
02D
02C
02B
02A
029
028
026
025
024
023
022
021
020
L/E
L/E
L/E
L
L/E
L/E
L/E
L
L/E
L/E
L/E
L
L/E
L/E
L/E
L
L/E
L/E
L/E
L/E
L/E
L/E
L
L/E
L/E
L/E
L/E
L/E
L/E
L
RESET X PUC
RESET X PUC
NO CAMBIA
RESET X PUC
RESET X PUC
NO CAMBIA
RESET X PUC
RESET X PUC
NO CAMBIA
RESET X PUC
RESET X PUC
NO CAMBIA
RESET X PUC
RESET X PUC
NO CAMBIA
RESET X PUC
RESET X PUC
NO CAMBIA
RESET X PUC
RESET X PUC
NO CAMBIA
RESET X PUC
RESET X PUC
NO CAMBIA
-
Cada bit es usado para seleccionar su función. Bit=0 E/S. Bit=1 módulo funcional periférico.
Cada bit selecciona la dirección del correspondiente pin. Bit=0 Entrada. Bit=1 Salida
Cada bit corresponde con el valor a reflejar en el pin correspondiente
Refleja el valor de la entrada si está en este modo.
Ídem P6SEL
Ídem P6DIR
Ídem P6OUT
Ídem P6IN
Ídem P6SEL
Ídem P6DIR
Ídem P6OUT
Ídem P6IN
Ídem P6SEL
Ídem P6DIR
Ídem P6OUT
Ídem P6IN
-Ídem P6SEL
Cada bit habilita la interrupción cuando el correspondiente PxIFG es asertado. Bit=1 Int. Habilitada
Cada bit selecciona el flanco del pin Bit=0 Ascendente. Bit= Descendente.
Cada bit corresponde con su pin, es asertado cuando la señal de entrada tiene un flanco. Debe ser reseteado por software.
Ídem P6DIR
Ídem P6OUT
Ídem P6IN
Ídem P6SEL
Ídem P2IE
Ídem P2IES
Ídem P”IFG
Ídem P6DIR
Ídem P6OUT
-
Tabla A.7: Registros Puertos 1-6 Entrada/Salida
66
ESPECIALES
Habilitación modulo
2
ME2
005
L/E
000h x PUC
Habilitación modulo
1
ME1
004
L/E
000h x PUC
Flag interrupción 2
IFG2
003
L/E
020h x PUC
Flag interrupción 2
IFG1
002
L/E
082h X PUC
WDTIFG reset x
POR
Habilitación
interrupción 2
IE2
001
L/E
000h x PUC
Habilitación
interrupción 1
IE1
000
L/E
RESET X PUC
7
6
4
3
2
1
0
URXE1
USPIE1
URXE1: USART1, habilitada recepción UART
UTXE1: USART1, habilitada transmisión UART
USPIE1: USART1, habilitada recepción y transmisión SPI (synchronous peripheral interface)
7
6
5
4
3
2
1
0
UTXE0
URXE0
USPIE0
URXE0: USART0, habilitada recepción UART
UTXE0: USART0, habilitada transmisión UART
USPIE0: USART0, habilitada recepción y transmisión SPI (synchronous peripheral interface)
7
6
5
4
3
2
1
0
UTXIFG1 URXIFG1
URXIFG1: Flag de recepción USART1, UART, y SPI
UTXIFG1: Flag de transmisión USART1, UART, y SPI
7
6
5
4
3
2
1
0
UTXIFG0 URXIFG0
NMIIFG
OFIFG
WDTIFG
WDTIFG: Asertado cuando se ha sobrepasado el tiempo de conversión, en modo watchdog o se ha violado un acceso. Reset cuando se enciende.
OFIFG: Flag fallo del oscilador
NMIIFG: Asertado vía pin RST/NMI
URXIFG0: Flag recepción USART0, UART, y SPI
UTXIFG0: Flag transmisión USART0, UART, y SPI
7
6
5
4
3
2
1
0
UTXIE1
URXIE1
URXIE1: habilitación interrupción recepción USART1, UART, y SPI
UTXIE1: habilitación interrupción transmisión USART1, UART, y SPI
7
6
5
4
3
2
1
0
UTXIE0
URXIE0
ACCVIE
NMIIE
OFIE
WDTIE
WDTIE: habilitación interrupción Watch Dog Timer. Inactivo si es seleccionado modo Watchdog. Activo si está en modo intervalo
OFIE: habilitación interrupción fallo del oscilador
NMIIE: habilitación interrupción no enmascarable
ACCVIE: habilitación interrupción acceso a la memoria flash violado
URXIE0: habilitación interrupción recepción USART0, UART, y SPI
UTXIE0: habilitación interrupción transmisión USART0, UART, y SPI
-
-
5
UTXE1
Tabla A.8: Registros Especiales
67
Anexo B: Data Decoding
Este es un documento interno de la universidad, para cualquier consulta diríjanse al director
de este proyecto.
68
Descargar