Diseño y realización de un instrumento musical MIDI basado en control de inclinación
description
Transcript of Diseño y realización de un instrumento musical MIDI basado en control de inclinación
UNIVERSIDAD DE SEVILLA
ESCUELA TÉCNICA SUPERIOR DE INGENIEROS
Departamento de ingeniería electrónica
PROYECTO FINAL DE CARRERA
Diseño y realización de un instrumento musical
MIDI basado en control de inclinación
Autor: Luis Eduardo González Blanco
Tutor: Manuel Ángel Perales Esteve
Sevilla, Julio 2013
Índice
3
Í ndice
Índice de contenidos
1. Memoria justificativa _____________________________________________ 7
Objetivo ___________________________________________________ 7
Metas del proyecto __________________________________________ 7
Descripción ________________________________________________ 7
2. MIDI __________________________________________________________ 9
2.1. ¿Qué es el MIDI? _____________________________________________ 9
2.2. Un poco de historia ___________________________________________ 10
2.3. Hardware __________________________________________________ 11
2.3.1. Cables y conectores ___________________________________ 12
2.3.2. Conexiones __________________________________________ 12
2.3.3. Los canales MIDI _____________________________________ 14
2.4. Software ____________________________________________________ 15
2.4.1. Los mensajes MIDI ___________________________________ 15
2.4.2. Estructura del mensaje _________________________________ 16
2.4.3. Tipos de mensajes _____________________________________ 17
3. Hardware ______________________________________________________ 25
3.1. Microcontrolador MCF51QE128 de Freescale _____________________ 25
3.1.1. Definición de microcontrolador __________________________ 25
3.1.2. El microcontrolador MCF51QE128 _______________________ 25
3.1.3. Modos de funcionamiento ______________________________ 27
3.1.4. Registros de la CPU ___________________________________ 33
3.2. Módulo LCD _______________________________________________ 36
4. Desarrollo práctico ______________________________________________ 39
4.1. Configuración del microprocesador para su funcionamiento como
controlador MIDI ________________________________________________ 39
Índice
4
4.2. Pantalla LCD _______________________________________________ 40
4.2.1. Configuración de la pantalla LCD ________________________ 40
4.2.2. Inicialización de la pantalla LCD _________________________ 41
4.3. Montaje ____________________________________________________ 42
4.3.1. Conexión de los elementos ______________________________ 42
4.3.2. Rutado en PCB, diseño revelado de la placa ________________ 44
4.4. Funcionamiento del programa __________________________________ 45
4.4.1. Main.c ______________________________________________ 46
4.4.2. Funciones_2.c ________________________________________ 50
4.4.3. Interrupciones (MCUinit.c) _____________________________ 53
5. Resultados experimentales ________________________________________ 55
5.1. Montaje en la placa de pruebas__________________________________ 55
5.2. Visualización de resultados en el PC _____________________________ 59
5.3. Comprobación de las señales eléctricas ___________________________ 61
6. Montaje físico __________________________________________________ 63
6.1. Revelado del PCB ____________________________________________ 63
6.2. Realización del montaje _______________________________________ 64
6.2.1. Componentes utilizados ________________________________ 64
6.2.2. Montaje paso a paso ___________________________________ 65
6.3. Aspecto final y funcionamiento del dispositivo _____________________ 69
7. Conclusiones ___________________________________________________ 73
8. Bibliografía ____________________________________________________ 75
9. Anexos ________________________________________________________ 77
9.1. Código fuente del controlador MIDI _____________________________ 77
9.2. Esquemas _________________________________________________ 112
Índice
5
Índice de figuras
Figura 1 Interfaz MIDI .................................................................................................... 12
Figura 2 Tipos de conectores MIDI ................................................................................. 13
Figura 3 Estructura binaria de un mensaje MIDI ............................................................ 16
Figura 4 El microcontrolador MCF51QE128 .................................................................. 26
Figura 5: Módulo LCD ST7066U ................................................................................... 36
Figura 6 Conexiones entre la tarjeta DEMOQE y la pantalla ......................................... 41
Figura 7: Conexión de todos los elementos ..................................................................... 43
Figura 8: Componentes PCB ........................................................................................... 44
Figura 9: Cara inferior PCB............................................................................................. 44
Figura 10: Cara superior PCB ......................................................................................... 45
Figura 11 Freescale Codewarrior 5.9 .............................................................................. 45
Figura 12 Diagrama de flujo main.c ................................................................................ 48
Figura 13 Diagrama de estados del pulsador cambio de instrumento ............................. 49
Figura 14 Diagrama de estados del pulsador MUTE ...................................................... 50
Figura 15 Diagrama de flujo de la interrupción .............................................................. 54
Figura 16 Protoboard (Placa de pruebas) ....................................................................... 55
Figura 17 Cables de colores arduino ............................................................................... 55
Figura 18 Transformador de corriente ............................................................................. 56
Figura 19: Tarjeta de sonido M-Audio Fast Track Pro ................................................... 57
Figura 20 Montaje en placa de pruebas ........................................................................... 57
Figura 21 Montaje detallado en placa de pruebas ........................................................... 58
Índice
6
Figura 22 MIDI-OX monitorizando las señales .............................................................. 59
Figura 23 Sintetizador ..................................................................................................... 60
Figura 24 Señal visualizada en el osciloscopio ............................................................... 61
Figura 25 Corte de la placa ............................................................................................. 63
Figura 26 Eliminación del cobre .................................................................................... 64
Figura 27 Realización agujero pantalla ........................................................................... 65
Figura 28 Realización agujero Puerto MIDI ................................................................... 66
Figura 29 Limado agujero Puerto MIDI .......................................................................... 66
Figura 30 Soldador JBC .................................................................................................. 67
Figura 31 Realización de soldaduras ............................................................................... 67
Figura 32 Ensamblado de las piezas ................................................................................ 68
Figura 33 Aspecto final: vista frontal .............................................................................. 69
Figura 34 Aspecto final: vista lateral ............................................................................... 70
Figura 35 Instrumento conectado y funcionando ............................................................ 71
Índice de tablas
Tabla 1 Cuadro sinóptico de los mensaje MIDI .............................................................. 17
Tabla 2 Modos de funcionamiento del microprocesador ................................................ 28
Tabla 3: Descripción de los pines del módulo LCD ........................................................ 37
Tabla 4 Mensajes inicialización pantalla LCD ................................................................ 42
Memoria justificativa
7
1. Memoria justificativa
Objetivo
El objetivo del proyecto es el diseño y la realización de un instrumento musical
MIDI basado en control de inclinación.
Metas del proyecto
• Diseñar e implementar un controlador MIDI, que consistirá en una superficie de control
en combinación con la tarjeta DEMOQE con el microcontrolador MCF51QE128 de
Freescale.
• La superficie de control, que estará situada en la parte frontal del instrumento,
contará con un botón giratorio, que servirá para controlar el volumen del
instrumento; 2 botones, que servirán para silenciar y para cambiar el tipo de
instrumento respectivamente; y una pantalla LCD para controlar todos los
eventos.
• El microcontrolador será el encargado de transmitir los mensajes MIDI a un
dispositivo externo
Descripción
Descrito de forma sencilla, un controlador MIDI no es más que un dispositivo
lógico o físico (según esté implementado en software o hardware respectivamente) que
va a producir mensajes MIDI a partir de la ocurrencia de una serie de eventos
producidos por la interacción con un usuario.
Podemos considerar que un evento no es más que un hecho que sucede en un
determinado instante, al que vamos a asociar la ejecución de una cierta acción. Por
ejemplo, si se inclina el instrumento se ejecutará una determinada porción de código.
Memoria justificativa
8
El hecho de definir un evento es porque queremos saber en qué momento tiene
lugar, para actuar en consecuencia, y poder definir los eventos que queremos controlar.
En nuestro caso, un evento será cualquier hecho relacionado con la interfaz del
instrumento, que provocará algún cambio en el sonido que emite el instrumento. Por
ejemplo, un evento será el movimiento de la rueda para bajar o subir el volumen. Por lo
tanto, concluimos que los eventos se producirán al actuar sobre los botones, el control
giratorio de volumen o al inclinar el instrumento.
Estas señales se enviarán hacia un sintetizador MIDI que será el encargado de
interpretarlas y de emitir los sonidos. Más adelante entraremos en detalle con todo lo
acontecido en este apartado.
MIDI
9
2. MIDI
2.1 ¿Qué es el MIDI?
MIDI son las siglas de la Interfaz Digital de Instrumentos Musicales (Musical
Instrument Digital Interface). Se trata de un protocolo de comunicación serie estándar
que permite a los computadores, sintetizadores, secuenciadores, controladores y otros
dispositivos musicales electrónicos comunicarse y compartir información para la
generación de sonidos.
No es una forma de compresión de audio digital ni tampoco un lenguaje musical,
ni describe directamente los sonidos musicales. En realidad, es un protocolo digital de
comunicaciones, surgido del entendimiento entre fabricantes de equipos musicales
electrónicos, que permitió que todos estos instrumentos se pudieran comunicar entre
ellos y que, por extensión, se comunicaran con los ordenadores.
Estos instrumentos y componentes electrónicos se comunican también con el
ordenador personal, pudiéndose mandar mensajes MIDI a desde el PC al instrumento y
viceversa.
Al contrario de lo que se pueda pensar, cuando hablamos de MIDI y música
electrónica, lo que se está transmitiendo no son notas musicales sino mensajes digitales,
datos y eventos cuyo significado depende de la programación interna del dispositivo
conectado.
Gracias a las fuentes consultadas, podemos entrar más en detalle acerca del
estándar MIDI, tanto Hardware como Software:
http://es.wikipedia.org/wiki/MIDI
http://www.ccapitalia.net/reso/articulos/audiodigital/14/otrosoftwaremidi.htm
Sergi Jordà Puig, Audio digital y MIDI, Guías Monográficas Anaya Multimedia,
Madrid 1997
MIDI
10
En los apartados siguientes se detallará de forma completa esta serie de puntos
importantes:
• Hardware (instrumentos, cables, conectores...) y software MIDI.
• Estructura de los mensajes MIDI, detallando acto seguido los mensajes de canal,
mensajes de control de cambio, como por ejemplo, el mensaje de cambio de
volumen, dentro de los últimos mencionados. MIDI.
• Por último se comentarán ciertos mensajes y características especiales del MIDI,
(running status) así como lo que es una hoja de Implementación MIDI.
2.2 Un poco de historia
La música electrónica es bastante anterior al MIDI. En los años sesenta surgen
los primeros sintetizadores comerciales. Eran instrumentos analógicos y monofónicos,
es decir, sólo podían emitir una sola nota a la vez.
Por ese motivo, se pensó en conectarlos para permitir el control de distintos
instrumentos desde el teclado de uno de ellos y conseguir, de este modo, más notas
sonando simultáneamente, así como sonidos más ricos. Las primeras comunicaciones
entre estos aparatos fueron analógicas, de forma que el voltaje de la señal era
proporcional a la frecuencia deseada (y, por consiguiente, a la altura de la nota pulsada).
Sin embargo, de esta forma se seguía sin poder disparar más de una nota (pues la suma
de dos voltajes produciría una nota más aguda, no dos notas separadas); la solución
estaba en un protocolo digital, y en 1981 surgió el primero, bautizado como USI
(Universal Synthesizer Interface).
Lamentablemente, este protocolo no fue universal, y por ese motivo durante los
dos años siguientes se creó una comisión de fabricantes japoneses y norteamericanos de
instrumentos electrónicos para definir el protocolo estándar que iba a permitir la
conexión entre estos aparatos, independientemente del fabricante.
MIDI
11
Así surgió el MIDI, en el año 1983, y fue tal el éxito que obtuvo y el importante
mercado que se generó que, aunque las especificaciones técnicas hayan quedado
obsoletas para las posibilidades tecnológicas de hoy, la normativa no ha cambiado en
ningún punto, aunque sí que se han ido añadiendo detalles que no se contradicen con la
especificación original.
2.3 Hardware
Muchos de los dispositivos MIDI son capaces de enviar y recibir información
MIDI, pero dependiendo de si están recibiendo o enviando información, tendrán una
función u otra. El que envía los mensajes de activación se denomina Maestro (‘master’)
y el que responde a esa información Esclavo (‘slave’). En nuestro proyecto, el maestro
será el controlador MIDI diseñado, que enviará los diferentes mensajes MIDI al PC a
través de la interfaz MIDI-USB.
Los Dispositivos MIDI se pueden clasificar en tres grandes grupos:
• Controladores: generan los mensajes MIDI (activación o desactivación de una
nota, variaciones de tono, etc). El controlador más conocido tiene forma de
teclado de piano, aunque hoy en día tenemos una gran variedad de controladores
e instrumentos con capacidad de transmisión vía interfaz MIDI: guitarras,
parches de percusión, clarinetes electrónicos, incluso gaitas MIDI, y más.
• Unidades generadoras de sonido: también conocidas como módulos de sonido,
reciben los mensajes MIDI y los transforman en señales sonoras (recordemos
que MIDI no transmite audio, sino paquetes de datos digitales).
• Éstos son los tres grandes tipos de aparatos MIDI. Aun así, podemos encontrar
dispositivos que tengan dos o incluso las tres funciones anteriores. Por ejemplo,
los órganos electrónicos disponen de un controlador (el propio teclado) y una
unidad generadora de sonido; algunos modelos también incluyen un
secuenciador.
MIDI
12
2.3.1 Cables y conectores
Un cable MIDI utiliza un conector del tipo DIN de 5 pines o contactos. La
transmisión de datos sólo usa uno de éstos, el número 5. Los números 1 y 3 se
reservaron para añadir funciones en un futuro. Los restantes (2 y 4) se utilizan como
blindaje y para transmitir una tensión de +5 voltios, para asegurarse que la electricidad
fluya en la dirección deseada. La finalidad del cable MIDI es la de permitir la
transmisión de los datos entre dos dispositivos o instrumentos electrónicos.
En la actualidad, los fabricantes de equipos económicos de empresas tales como
Yamaha, Casio, Korg y Roland han previsto la sustitución de los cables y conectores
MIDI estándar, por los del tipo USB que son más fáciles de hallar en el comercio y que
permiten una fácil conexión a las computadoras personales.
2.3.2 Conexiones
El sistema de funcionamiento MIDI es de tipo simplex, es decir, sólo puede
transmitir señales en un sentido. La dirección que toman las señales es siempre desde un
dispositivo 'maestro' hacia un dispositivo 'esclavo'. El primero genera la información y
el segundo la recibe.
Para entender bien el sistema de conexión, debemos saber que en un dispositivo
MIDI se pueden encontrar tres tipos de conectores distintos:
Figura 1 Interfaz MIDI
MIDI
13
• MIDI OUT: Conector del cual salen los mensajes generados por el dispositivo
maestro.
• MIDI IN: Sirve para introducir mensajes al dispositivo esclavo.
• MIDI THRU: También es un conector de salida, pero en este caso se envía una
copia exacta de los mensajes que entran por MIDI IN.
El formato más simple de conexión es el formado por un dispositivo maestro
(por ejemplo, un controlador) y un esclavo (como un sintetizador). En este caso, el
maestro dispondrá de un conector MIDI OUT, de donde saldrán los mensajes MIDI
generados, el cual deberemos unir al conector MIDI IN en el esclavo.
MIDI admite la conexión de un solo maestro a varios dispositivos esclavos en
cascada. Para esos casos se utilizará MIDI THRU, uniendo el maestro con una de las
unidades del modo descrito anteriormente. En el conector MIDI THRU de esa unidad se
obtiene una copia de los mensajes MIDI que se introducen a través de MIDI IN, por lo
que ese MIDI THRU se conectará con MIDI IN de otra de las unidades. A esto se le
llama Daisy Chain.
Figura 2 Tipos de conectores MIDI
MIDI
14
Supongamos que uno de los esclavos también incluye un controlador (como un
sintetizador con teclado). Éste dispondrá de conector MIDI OUT. En ese caso,
obtendremos los mensajes generados desde controlador en MIDI OUT, mientras que los
mensajes correspondientes al controlador situado al inicio de la cadena aparecerán
en MIDI THRU.
Por último, si se dispone de un aparato secuenciador (capaz de almacenar y
reproducir información MIDI recibida), se conectará entre el controlador y la primera
unidad generadora de sonido. En ese caso, el secuenciador dispondrá de
conectores MIDI OUT y MIDI IN.
Aunque existe la posibilidad de la conexión en cascada de varios aparatos MIDI,
es cierto que existe una limitación. Las características eléctricas de los conectores MIDI
hacen la señal proclive a la degradación, por lo que son pocos los aparatos que se
pueden conectar en cascada antes de notar pérdidas apreciables de información.
2.3.3 Los canales MIDI
El protocolo MIDI permite que los mensajes se envíen a través de dieciséis
canales diferentes. Estos canales no corresponden a conexiones físicas separadas, ya
que comparten un único cable, sino más bien a direcciones lógicas.
El concepto de canales MIDI es similar al de los canales de televisión. Muchas
cadenas televisivas transmiten sus respectivos programas al mismo tiempo. Esto
significa que una antena de televisión debe recibir todos estos canales a la vez. No
obstante, puesto que todas las cadenas transmiten por un canal diferente, simplemente es
necesario seleccionar el canal que desea verse.
El instrumento MIDI maestro puede decidir el canal que transmitirá, igual que si
seleccionara la cadena de televisión que desea ser. Por su parte, el instrumento esclavo
puede comportarse como el televisor y seleccionar el canal MIDI que desea “oír”.
Aunque se reciba información en todos los 16 canales MIDI, el esclavo sólo
“oirá” el canal seleccionado, igual que el televisor.
MIDI
15
2.4 Software
2.4.1 Los mensajes MIDI
La especificación MIDI incluye un aspecto de software que parte de la misma
organización de los bytes.
La transmisión de los datos se efectúa en serie, de manera asíncrona, lo que
obliga a agregar un bit de inicio y otro de parada. Para clarificar lo dicho, se puede decir
sencillamente que una transmisión asincrónica de datos se da cuando el receptor no
"sabe" cuándo vendrá el siguiente dato, así que se encuentra en estado constante de
espera, ya sea en nivel alto o en bajo, hasta que se produzca un cambio de estado, que
indique el inicio de un nuevo mensaje. Este bit primero debe ser siempre el mismo, para
que sea siempre diferente al estado "por defecto", así que este bit no puede formar parte
del byte recibido. A este bit que sirve para indicar la llegada de un dato y permite al
aparato receptor prepararse para la cadena de bits que viene después, se le conoce como
"bit de inicio".
En la especificación MIDI, la entrada se encuentra en un estado alto por defecto,
así que el bit de inicio es un 0. El bit de parada sirve para dar tiempo al aparato receptor
de decidir qué hacer con la información una vez recibida. En el caso del MIDI, este bit
es siempre 1. La velocidad de recepción/transmisión de los datos MIDI se definió en
31.250 baudios, o bits por segundo, así sólo deben transcurrir 32 microsegundos entre
un bit y el siguiente; ni más ni menos.
Los mensajes MIDI están formados por dos o tres bytes, dependiendo del tipo de
mensaje que se envíe.
Estos bytes pueden ser de dos clases:
• De estado -status byte-
• De información -data byte-.
Se diferencian por el primer bit: si es un 1, tenemos un byte de estado, y si es un
0, es un byte de datos. Al generar un mensaje MIDI, siempre enviamos un byte de
estado, que puede estar seguido de cierta cantidad de bytes de datos.
MIDI
16
A su vez, los mensajes de estado se dividen en dos grupos:
• Mensajes de canal
• Mensajes de sistema
Los mensajes de canal se envían a un dispositivo específico, mientras que los
mensajes de sistema son recibidos por todos los equipos.
A continuación veremos más en detalles todos los bytes y mensajes MIDI.
2.4.2 Estructura del mensaje
Todo mensaje MIDI se compone de un primer byte de status (que determina el
tipo del mensaje) y uno o dos bytes restantes de datos (dependiendo del tipo de
mensaje).
En el byte de status, tan solo tres, de los siete bits disponibles (no olvidemos que
el más significativo está siempre a 1), son los que determinan el tipo de mensaje. Los
cuatro restantes indican el canal al que el mensaje va dirigido, lo que explica porque son
dieciséis (24) los canales MIDI posibles. En la figura 3 se puede apreciar la estructura
binaria de un mensaje genérico.
Como se puede observar en la siguiente figura,
los tres bits que siguen al primero, identifican el mensaje, por lo cual, habrá solo ocho
tipos de mensajes, en tanto que los cuatro bits restantes identifican el canal, es decir
habrá dieciséis canales posibles para transmitir.
Figura 3 Estructura binaria de un mensaje MIDI
MIDI
17
2.4.3 Tipos de mensajes
Como ya se comentó anteriormente, los mensajes pueden ser de 8 tipos
diferentes, que se resumen en la tabla siguiente:
Nombre Binario Hex Data 1 Data 2
Note Off 1000 nnnn 8 N Altura Velocidad
Note On 1001 nnnn 9 N Altura Velocidad
Poly. Aftertouch 1010 nnnn A N Altura Presión
Control Change 1011 nnnn B N Tipo de control Intensidad
Chan. Aftertouch 1100 nnnn C N Presión
Pitch Bend 1101 nnnn D N MSByte LSByte
Program message 1110 nnnn E N Programa
System message 1111 nnnn F N
Tabla 1 Cuadro sinóptico de los mensaje MIDI
• nnnn son los cuatro bits que determinan el canal al que se aplica el mensaje, de
forma que 0000 es el canal 1, y 1111 el canal 16.
• N corresponde al carácter hexadecimal de este canal (0-F).
• Todos los bytes de datos tienen una resolución de siete bits, con valores
decimales comprendidos entre 0 y 127.
• Cuando en la tabla el segundo byte de datos está en blanco (Channel Aftertouch
y Program Change), significa que el mensaje utiliza un único byte de datos.
• En el mensaje Pitch Bend, los dos bytes de datos se combinan para formar un
único valor con catorce bits de resolución, comprendido entre -8192 y +8191.
Un dispositivo MIDI no tiene porque utilizar todos los mensajes. Cuando un
dispositivo MIDI recibe un mensaje que no es capaz de interpretar, simplemente lo
ignora y (si dispone de un puerto MIDI THRU) lo reenvía al igual que cualquier otro
mensaje, y si no dispone del puerto MIDI THRU, pasa al siguiente mensaje.
MIDI
18
Veamos más en detalle los más importantes de estos ocho mensajes de canal,
que serán los usados en el programa de este proyecto, aquellos que van dirigidos a un
canal en concreto:
- Note On
Este mensaje le indica al dispositivo, que debe iniciar una nota. Se genera
cuando se aprieta una tecla desde un teclado.
• El primer Byte nos indica la altura de la nota, de lo que se deduce que el MIDI
contempla 128 posibles notas, siendo la 0 la nota más grave y la 127 la más
aguda. Teniendo en cuenta que existen doce notas por octava, el MIDI tiene
pues una tesitura de más de diez octavas (un piano de cola sólo tiene siete) que
se corresponde aproximadamente con el número de octavas que el oído humano
es capaz de captar. Aunque es posible modificar el mapa de asignación, por
defecto, los múltiplos de 12 corresponden a notas Do, siendo la nota 60 el Do
central de un piano.
• El segundo byte indica la velocidad de ataque, que viene determinada por la
fuerza con que se ha apretado la tecla. Es decir, se podría decir que se
corresponde con la intensidad sonora. El valor cero es un carácter especial, pues
no se corresponde con ninguna nota, sino que podría entenderse como un
interruptor, cuya función lo que hace es “apagar” o desactivar la nota que estaba
sonando.
- Note Off
Funciona de forma similar al Note On con velocidad 0, es decir se envía un dato
de valor cero. Para liberar la nota pulsada.
• El primer byte es la altura de la nota.
• El segundo byte es la velocidad de liberación.
MIDI
19
La inmensa mayoría de dispositivos no generan ni responden a la velocidad de
liberación, por lo que es un mensaje muy poco utilizado. En su lugar, cuando se libera
una tecla, la mayoría de teclados envían un Note On con velocidad 0, que todos los
sintetizadores entienden.
- Program Change
Este mensaje modifica el programa activo. Puede ser enviado desde los botones
de un teclado, aunque hoy en día es más frecuente enviarlo desde el propio ordenador,
editándolo en el secuenciador.
El único byte utilizado define un número de programa.
Algunos sintetizadores disponen de más de 128 programas diferentes. En estos
casos, los programas suelen agruparse en varios bancos, de hasta 128 programas cada
uno. Algunos sintetizadores numeran sus sonidos comenzando por el 1 y terminando
por el 128.
- Los mensajes de Control Change (cambio de control)
El mensaje de Control Change forma parte de los mensajes de canal que se ha
descrito en el apartado anterior. Este engloba 128 posibles mensajes de control
diferentes. Todos ellos afectan de alguna forma a la calidad del sonido; existen controles
para modificar el volumen, la modulación, la reverberación, etc. Su estructura es la
siguiente:
• El primer byte indica el tipo de control. De los 128 controles posibles, tan solo
una pequeña parte está asignada, por lo que todavía quedan muchos por definir
en un futuro.
• El segundo byte indica el valor de este control. La mayoría de controles utiliza la
escala del 0 al 127, pero algunos funcionan sólo de forma binaria (on/off).
MIDI
20
Este tipo de mensajes se puede enviar de varias formas distintas.
Existen varias alternativas para enviar estos mensajes. De la dos ruedas que
suelen disponer los teclados, una acostumbra a enviar mensajes de Control Change de
tipo 1 (la otra ya habíamos visto que se utiliza para el Pitch Bend), aunque en muchos
teclados este número de control puede ser modificado por el usuario. Existen también
paneles de control MIDI, con varios botones o potenciómetros configurables, de forma
que el usuario puede decidir el canal y el tipo de control al que asigna cada
potenciómetro.
A continuación se describen algunos de los tipos de control más utilizados.
• Control Change 0: Cambio de banco
Si el sintetizador dispone de varios bancos, éste es el mensaje de control que nos
permite acceder a todos ellos, ya que el valor del tercer byte indica el número de banco
deseado. Este mensaje suele ir seguido de un mensaje de cambio de programa. A veces
en alguno sintetizadores el cambio de control no se consigue con el valor cero, sino con
el 32 o una combinación de los dos, todo dependerá del tipo de sintetizador que se esté
usando.
• Control Change 1: Modulación
Este es el control que se envía por defecto desde una de las dos ruedas de los
teclados. El efecto sonoro producido puede variar de un sintetizador a otro y
frecuentemente es programable por el usuario. Entre los efectos más frecuentes está la
modulación de amplitud (trémolo), la modulación de altura (vibrato), o la modulación
de la frecuencia de corte del filtro (wah-wah).
• Control Change 7: Volumen
Este es uno de los controles más utilizados. Mientras que la velocidad de
pulsación del mensaje de Note On afecta a la intensidad de una sola nota, el control 7
modifica el volumen del canal en general, como si fuera un mezclador. Cuando por
ejemplo, enviamos un mensaje de Control 7 con un valor 0, el canal dejará de oírse a
pesar de que se siguen emitiendo notas, hasta que enviemos un nuevo Control 7 no nulo
que invalide el anterior. Muchos secuenciadores incorporan una ventana “mezclador”
MIDI
21
con dieciséis potenciómetros, que se utiliza para enviar este control a cualquiera de los
dieciséis canales MIDI. Asimismo, si el secuenciador dispone de un editor gráfico de
controles, se pueden dibujar curvas de volumen para modificar el ataque y la evolución
de algunas notas o fragmentos.
• Control Change 10: Panorama
Este control permite definir la posición de sonido de un canal, en un ámbito de
180 grados. Un valor 0, sitúa la fuente de sonido a la izquierda, 64 la centra y 127 la
sitúa a la derecha. Enviando valores diferentes es posible conseguir que las notas
"bailen" entre los dos altavoces.
• Control Change 11: Expresión
Aunque muchos usuarios desconocen este control, su uso en secuenciadores con
posibilidades de edición de controles, puede simplificar la mezcla final. La expresión
está pensada para trabajar en colaboración con el volumen (Control 7). Cuando la
expresión vale 127 (valor defecto) el volumen general del canal viene determinado por
el valor del Control 7, pero a medida que el valor de la expresión desciende, también lo
hace el volumen general del canal, de forma que podemos establecer la siguiente
ecuación:
Volumen general de un canal = Control7 x Control11 + 127
Esto permite utilizar el Control 7 para controlar la mezcla global (desde la
ventana mezclador del secuenciador o asignando un único valor inicial), y el Control 11
para controlar la articulación particular de algunos fragmentos (dibujando su evolución
con el ratón), teniendo muy en cuenta que, si no se utiliza, el valor del Control 11
debería permanecer a 127.
• Control Change 64: Sostenido
Es similar al pedal de sostenido de los pianos. A diferencia de los anteriores, este
control sólo tiene dos posiciones: apagado (0-63) o encendido (64-127). Estando
activado, las notas se mantienen más tiempo.
MIDI
22
• Control Change 91: Reverberación
Muchos sintetizadores modernos incorporan este efecto. La reverberación (o
reverb en el argot del músico informático) indica la proporción entre el sonido directo y
el sonido reflejado. Este efecto se utiliza para simular la acústica de las salas de
concierto. De forma simplificada, cuanto mayor sea una sala mayor reverberación
ofrecerá. Asimismo, cuanto más distante sea una fuente sonora, más reverberada llegará
a nuestros oídos, ya que la proporción de sonido reflejado por las paredes de la sala será
superior. Por ello, cuanto mayor sea el valor de este controlador, más distante parecerá
la fuente sonora.
• Control Change 93: Chorus
Este es otro efecto utilizado regularmente en las grabaciones en estudio, y que,
como el anterior, también incorporan muchos sintetizadores modernos. El chorus
produce un efecto parecido al que se obtiene duplicando los instrumentos, por lo que
cuanto mayor sea el valor de este controlador, más “grueso” parecerá el sonido.
• Mensajes de Modo
Aunque la implementación MIDI 1.0 no los considera como mensajes de control
estrictos, los incluimos aquí para simplificar. Esta denominación especial, corresponde a
los controles 121 a 127, de los cuales comentaremos tan sólo dos:
· Control Change 121: Reset-All Controllers. Este mensaje restaura todos los restantes
controles a sus valores defecto (banco=0, programa=0, modulación=0, volumen=100,
panorama=64, expresión=127, etc.). Si desde el secuenciador finalizamos por ejemplo
un tema con fundidos de volumen (el Control 7 va descendiendo hasta llegar a 0) y el
tema siguiente no contiene ningún valor inicial de volumen, posiblemente cuando
intentemos reproducirlo no oigamos nada. La causa es que los volúmenes siguen
estando a cero. Una solución que la mayoría de secuenciadores contemplan como
opción, es la de enviar este mensaje después de terminar un tema (o inmediatamente
antes de comenzarlo), y restaurar así todos los parámetros.
MIDI
23
· Control Change 123: All Notes Off. A veces una nota puede quedarse colgada
sonando porque se haya perdido el mensaje de Note Off que debía cortarla. En este caso
puede ser de ayuda el Control 123, que desactiva automáticamente todas las notas.
Hardware
25
3. Hardware
3.1 Microcontrolador MCF51QE128 de FreeScale
3.1.1 Definición de Microcontrolador
Un microcontrolador (abreviado μC, UC o MCU) es un circuito integrado
programable, capaz de ejecutar las órdenes grabadas en su memoria. Está compuesto de
varios bloques funcionales, los cuales cumplen una tarea específica. Un
microcontrolador incluye en su interior las tres principales unidades funcionales de
una computadora: unidad central de procesamiento (CPU), memoria y periféricos de
entrada/salida.
Se puede decir que es una evolución del microprocesador, al añadirle a este
último las funciones que antes era necesario situar externamente con otros circuitos. El
ejemplo típico esta en los puertos de entrada/salida y en la memoria RAM, en los
sistemas con microprocesadores es necesario desarrollar una lógica de control y unos
circuitos para implementar las funciones anteriores, con un microcontrolador no hace
falta porque lo lleva todo incorporado, además en el caso de tener que ampliar el
sistema ya ofrece recursos que facilitan esto.
En resumen, un microcontrolador es un circuito integrado independiente, que no
necesita memoria ni puertos externos pues los lleva en su interior, que facilita la tarea de
diseño y reduce el espacio, traduciéndose todo a una aplicación final más económica y
fiable
3.1.2 El microcontrolador MCF51QE128
Una de las mayores ventajas de los microcontroladores Freescale son los bajos
precios de éstos, la alta potencia en operación y el bajo consumo cuando se opera a
máxima frecuencia de trabajo, especialmente cuando se lleva la operación a baja
velocidad. Para este proyecto hemos elegido el microcontrolador MCF51QE128.
Hardware
26
Es un microcontrolador con procesador interno (CPU) tipo COLDFIRE V1, y
perteneciente a la familia FLEXIS, que surge con la innovación introducida por
Freescale para permitir una fácil migración del mundo de los 8 bits al de los 32
bits. Esto asegura una gran compatibilidad con microcontrolador con núcleo de 8 bits,
permitiendo migrar con muy pocos cambios en software y hardware.
Sus características más importantes son:
• Núcleo ColdFire V1 de 46 Dhrystone (2.1 MIPS) a 50 MHz.
• Rango de operación de 1.8-3.6V.
• Hasta 8K bytes SRAM y 32K bytes de flash.
• 2 Módulos Seriales de comunicación (SCI)
• 2 interfaces I2C
• 2 Interfaces Seriales Sincrónicas (SPI).
• 2 módulos de interrupciones de teclado (KBI) de ocho canales cada uno.
• Timers de 16 bits: uno de 6 canales y dos de 3 canales
• Conversor A/D de 12 bits de resolución de 20 canales.
Figura 4 El microcontrolador MCF51QE128
Hardware
27
• Dos comparadores analógicos.
• Hasta 54 Input / Output (I/O) generales.
• Sistemas Integrados (PLL, software watchdog).
• Internal clock source
• Regulador de tensión con fast start up y regulación de baja tensión.
• Oscilador de 32 kHz de low power.
3.1.3 Modos de funcionamiento
Las máquinas ColdFire® V1 tienen la capacidad de trabajar en distintos modos
de funcionamiento (Ver tabla 2), dentro de los cuales se pueden mencionar:
• Modo de depuración para desarrollo de código: Manejado directamente por el
módulo BDC (Background Debug Controller), el trabajo importante de este
modo es el de poder analizar las operaciones del microcontrolador durante la
ejecución del software del usuario. Por medio de este modo es posible descargar
el bootloader o la aplicación del usuario dentro de la memoria FLASH. Este
modo también puede ser usado para borrar y reprogramar la FLASH después de
que esta ha sido programada con anterioridad.
• Modo seguro: Mientras que el microcontrolador se encuentre en modo seguro,
existen restricciones aplicadas a los comandos del depurador.
• Modo RUN: Es el modo normal de operación y el más común, porque es el
modo en el que el usuario puede ejecutar su código. La máquina reconoce la
solicitud de entrada al modo cuando el pin BKGD/MS es llevado a alto con el
flanco de bajada de la señal interna de RESET. Este modo presenta las
siguientes variaciones:
o Modo RUN normal: Una vez la CPU ha salido del estado de RESET,
carga el registro SR (Status Register) y el registro PC (Program Counter)
con el contenido de las direcciones 0x(00)00_0000 y 0x(00)00_0004 de
la memoria y ejecuta la primera instrucción apuntada por el PC. Es
importante saber que la arquitectura ColdFire® V1 usa
direccionamientos por byte en el modo big endian.
Hardware
28
o Modo RUN en bajo consumo (LPRUN: low Power RUN): En este
modo el regulador interno se lleva al estado de standby y de esta manera
ubicar la CPU en modo de bajo consumo. Es importante saber que el
sistema queda alimentado de manera no regulada y que todos los
periféricos no usados son privados de la señal de reloj, vía los registros
SCGC1 y SCGC2. También es importante saber que la CPU no puede
entrar en modo LPRUN cuando el sistema se encuentra en uso del BDM
(Background Debug Module).
Tabla 2 Modos de funcionamiento del microprocesador
Hardware
29
Antes de ingresar al modo LPRUN, las siguientes acciones deberán ser
ejecutadas:
- El FLL (Frecuency Loop Locked) del módulo ICS (Internal Clock Source) es
llevado a un estado de bypass, para la adopción de un modo de operación de
bajo consumo llamado FBELP (FLL Bypassed External Low Power)
- El bit HGO del registro ICSC2 es aclarado, para configurar un oscilador
externo de bajo consumo.
- La frecuencia del bus es menor que 125 kHz.
- El módulo conversor análogo a digital (ADC) deberá trabajar en baja potencia
o ser deshabilitado.
- El módulo de detección de bajo voltaje deberá ser deshabilitado, debido a la
condición de standby del regulador interno.
- No se tiene disponibilidad sobre la programación o borrado de la FLASH.
Finalmente, se puede ingresar al modo, llevando un “1” al bit LPR del registro
SPMSC2 (System Power Management Status and Control 2 Register).
Para regresar al modo normal de RUN, es necesario aclarar el bit LPR. El bit
LPRS indicará si el regulador está en modo normal de funcionamiento y la
máquina podrá correr a la máxima velocidad configurada. Si una interrupción se
presenta, la máquina podrá salir del estado de LPRUN, esto se puede lograr
poniendo en”1” el bit LPWUI del registro SPMSC2 y dentro de la rutina de
atención a la interrupción se podrá habilitar la operación del ICS (Internal Clock
Source) a máxima velocidad.
• Modos de WAIT: Para entrar en este modo de bajo consumo es necesario
ejecutar la instrucción STOP, después de configurar la máquina como se ilustra
en la Tabla 2.
Hardware
30
o Modo normal de WAIT: La CPU queda en modo STOP y el consumo
se reduce significativamente, dado a que el reloj es interrumpido. La
arquitectura ColdFire® V1 no hace diferencia entre elmodo STOP y el
modo WAIT, ambos son catalogados como modos de STOP, desde la
perspectiva del núcleo. La diferencia entre ambos modos sólo se aprecia
desde el suministro del reloj a los periféricos del sistema. En modo
STOP, la mayoría de los periféricos son desalimentados de reloj,
mientras que en modo WAIT el reloj alimenta la mayoría de los módulos.
Si es necesario que el sistema responda a comandos en el modo BDM,
será prioritario poner a “1” el bit ENBDM.
Al presentarse un evento de interrupción, estando la máquina en modo
WAIT, la CPU ejecuta un proceso de excepción, comenzando con un
servicio de apilamiento de información valiosa y luego conduciendo la
máquina a un servicio de atención a la interrupción.
o Modo LPWAIT: La diferencia respecto al modo normal de WAIT es
que el regulador de la CPU sale de regulación y queda en estado de
standby. Lo anterior reduce enormemente el consumo de la máquina,
consumo que puede ser reducido aún más deshabilitando los módulos
que no se utilicen. Esta última operación se puede lograr poniendo a cero
los bits de los módulos a inactivar en el registro SCGC.
Las restricciones vistas en el modo LPRUN se aplican al modo LPWAIT.
Si el bit LPWUI es puesto a “1”, cuando la máquina ha ejecutado la
instrucción STOP, el regulador regresa a su estado de regulación y el ICS
puede ser llevado a su máxima velocidad en la entrada a la rutina de
atención a la interrupción, que determinó la salida del estado de WAIT.
Si el bit LPWUI es puesto a “0”, cuando la máquina ha ejecutado la
instrucción STOP, la CPU regresa al modo LPRUN.
• Modos de STOP: Existen tres modos de operación en STOP, siempre y cuando
el bit STOPE del registro SOPT1 se encuentre en “1”. El bit WAITE del registro
SOPT1 deberá ser aclarado, excepto cuando se desee trabajar en modo WAIT.
Hardware
31
En el modo STOP3 las fuentes de reloj de la CPU son interrumpidas.
Los diferentes modos de STOP son seleccionados mediante el bit PPDC del
registro SPMSC2.
La mayoría de los comandos del modo background (BDM) no son reconocidos
en los modos de STOP, pero el comando BACKGROUND puede sacar la CPU
del modo STOP4 y entrar en modo HALT. Quedando la CPU en el modo HALT
y estando el bit ENBDM en “1”, todos los comandos del BDM se podrán
utilizar.
o Modo STOP2: La tabla 2 detalla la forma de ingresar al modo STOP2,
en donde la mayoría de los módulos de la CPU son apagados, con
excepción de la memoria RAM y el módulo RTC (Real Time Clock) de
manera opcional. Al entrar a este modo, la CPU almacena el estado de
los pines I/O en la RAM, con el propósito de recuperar su estado una vez
se decida salir del modo.
Para salir de este modo, es necesario introducir un flanco de bajada en el
pin de RESET del sistema o generar un evento de excepción por
interrupción en el módulo RTC, siempre y cuando esté habilitado.
También, al salir del modo STOP2, la máquina ejecuta un estado de POR
(Power On Reset) conformado por los siguientes eventos:
- Todos los módulos de control y los registros de estado son
inicializados por el controlador de manejo de la potencia, por el
RTC y por el buffer de trazo del depurador (Debug Trace Buffer).
Más adelante, en el texto, serán tratados otros registros afectados
por este evento.
- La función de RESET por LVD será habilitada y la CPU se
quedará en estado de RESET si el voltaje de la fuente VDD queda
por debajo del voltaje de comparación (LVD trip point).
- La CPU comienza un proceso de excepción por RESET,
realizando la captura de los vectores en las direcciones
Hardware
32
0x(00)00_0000 y 0x(00)00_0004.
Adicionalmente la bandera PPDF del registro SPMSC2 es puesta a “1”.
Esta bandera es servida para que el usuario pueda ejecutar una rutina de
recuperación por salida del modo STOP2.
Para mantener el estado de los pines de I/O antes de entrar al modo
STOP2, es necesario recuperar su estado desde la memoria RAM hacia
los registros de los puertos. Esta acción exige que se escriba un “1”, antes
de la recuperación, sobre el bit PPDACK del registro SPMSC2. En caso
de no escribirse un “1” sobre el bit PPDACK, el estado de los pines I/O
será asumido como el indicado para un RESET normal o por defecto.
Para aquellos pines que están trabajando como servicio a los módulos, es
necesario reconfigurar el periférico antes de escribir en el bit PPDACK.
Si en el modo STOP2 se tiene la opción de oscilador para bajo rango (bit
RANGE = 0 del registro ICSC2), como reloj para el RTC, es necesario
reconfigurar el registro ICSC2 antes de escribir en el bit PPDACK. Para
deshabilitar el reloj en el modo STOP2, es necesario conmutarse al modo
FBI o FEI del módulo SCI, antes de ejecutar la instrucción STOP.
o Modo STOP3: La tabla 2 detalla la forma de ingresar al modo STOP3,
en donde el estado de todos los registros internos, el contenido de la
memoria RAM y el estado de los pines I/O, se mantienen. El regulador
interno entra a operar en modo de standby.
Para salir de este modo, es necesario introducir un flanco de bajada en el
pin de RESET del sistema o generarse un evento de excepción por
interrupción de los siguientes módulos: RTC, ADC, ACMP, IRQ, SCI o
KBI. Si se sale del modo STOP3 vía evento de RESET, el MCU es
reinicializado y las operaciones son resumidas después de cargarse el
vector de RESET. Si se sale del modo STOP3 vía evento de excepción
por fuente de interrupción, el MCU cargará el vector adecuado,
dependiendo del módulo que generó la interrupción.
Hardware
33
o Modo STOP4: A diferencia de los modos STOP2 y STOP3, en este
modo el regulador trabaja a plena regulación. Este modo es también
llamado modo HALT y está relacionado directamente con la entrada a
modo BDM desde STOP o por un evento de LVD desde STOP.
Si el bit ENBDM está en “1” cuando la CPU ejecuta la instrucción
STOP, el sistema suministra reloj a la lógica de control del modo
background (BDM) de modo que ésta permanece activa durante el modo
STOP. Si el usuario intenta entrar a STOP2 o STOP3 cuando el bit
ENBDM está en “1”, el sistema queda en STOP4 (ver Tabla 2 para
detalles).
El ingreso a este modo también se obtiene si los bits LVDE o LVDSE del
registro SPMSC1 están en “1” y se presenta un evento por de bajo voltaje
con el módulo LVD, previamente habilitado. Es importante anotar que el
LVD trabajará correctamente si el regulador interno se encuentra
operando a plena regulación, lo cual descarta los modos STOP2 y STOP3
para esta condición. El LVD puede generar un evento de excepción de
RESET o de interrupción.
Para salir del modo STOP4 es necesario que se produzca un evento de
RESET o alguna de las siguientes excepciones de interrupción: RTC,
LVD, LVW, ADC, ACMP, IRQ, SCI o KBI.
3.1.4 Registros de la CPU
Heredando de la máquina M68000, la arquitectura ColdFire® V1 no especifica
registros acumuladores ni registros punteros (índices o bases), para la manipulación de
datos y decodificación de las instrucciones en memoria. Esta arquitectura contiene un
juego de registros generales, que cumplen con funciones de manipulación de datos y
direccionamiento de memoria llamados los Dn y An, respectivamente.
Hardware
34
El modelo de programación depende del concepto de nivel de privilegio, que el
programador elige de la máquina. Existen dos niveles de privilegio llamados nivel de
usuario y nivel de supervisor, que a continuación se describen.
• Registros para nivel de supervisor únicamente: Están restringidos para el
software de control de programa, en donde son implementadas funciones
restringidas sobre la operación del sistema, funciones de control sobre los pines
I/O y manipulación de la memoria. Los registros relacionados con el nivel de
supervisor son:
o Registro de Estado (SR: State Register): Utilizado para almacenar el
estado del procesador y que a su vez incluye:
- El registro CCR (Code Condition Register), que no es más que
el registro de las banderas principales de la CPU.
- Los bits de máscara de prioridad para los eventos de excepción
por interrupción.
- Otros bits de control en el nivel de supervisión.
o Registro de Configuración de la CPU (CPUCR: CPU Configuration
Register): Este registro suministra al nivel de supervisor la opción de
configuración de funciones del núcleo. Ciertas características del
hardware pueden ser habilitadas o inhibidas de forma individual, según
sea el valor de los bits del CPUCR
o Registro Base a Vector (VBR: Vector Base Register): Este registro
contiene la dirección base a los vectores de excepción localizados en la
memoria. Para acceder a la tabla de vectores, el desplazamiento de un
vector es adicionado al VBR. Para los procesadores ColdFire®, los 20
bits de menor peso del VBR no son utilizados. Esto fuerza a que la tabla
de vectores esté alineada con 16 bloques de 1MB
Los 8 bits superiores del registro VBR son forzados a cero debido a que
el núcleo del ColdFire® direcciona en 24 bits, es decir hasta 16 MB. El
VBR puede ser utilizado para relocalizar la tabla de vectores de
Hardware
35
excepción, desde su dirección inicial dentro de la FLASH
(0x(00)00_0000) hacia la base de la RAM (0x(00)80_0000), si fuera
necesario.
• Registros para nivel de supervisor y usuario: Se acceden desde el nivel de
supervisor o usuario, sin ninguna restricción. Estos registros son:
o Registros de Dato (D0 – D7): Estos registros son para hacer
operaciones sobre datos en formatos de 8, 16 o 32 bits. También, estos
registros pueden ser usados como registro índice.
Ante un evento de excepción por RESET, los registros D0 y D1 se
precargan con un valor de configuración del hardware implementado en
el núcleo ColdFire® V1.
o Registros de Dirección (A0 – A6): Estos registros son usados como
punteros pila por software, registro índice o registros base a direcciones.
También, estos registros pueden ser usados como registros tipo dato para
operaciones de 16 o 32 bits
o Puntero a Pila del Usuario y el Supervisor (A7 y OTHER A7): El MCU
ColdFire® V1 soporta dos punteros a pila de manera independiente. El
puntero a pila para el nivel de supervisor es conocido como SSP
(Supervisor Stack Pointer). Para el nivel de usuario el puntero a pila es
USP (User Stack Pointer).
El modelo de programación del BDM soporta lecturas y escrituras
directas sobre el SSP y el USP, siendo responsabilidad del sistema de
desarrollo externo, basado en el estado del bit S del registro SR, hacer la
elección apropiada.
o Registro de Código de Condiciones (CCR: Condition Code
Register):Configura el byte de menor peso del registro SR e informa
sobre el resultado de operaciones aritméticas y lógicas de la CPU
Hardware
36
o Contador de Programa (PC: Program Counter): Este registro contiene
la dirección de la siguiente instrucción a ser ejecutada (ver Figura 5.10).
Durante la ejecución de una instrucción, el procesador incrementa
automáticamente la dirección del PC (el incremento no necesariamente es
1, depende de la posición de la siguiente instrucción) o localiza un nuevo
valor de dirección en el PC, si se trata de un salto, llamado a subrutina o
atención a un proceso de excepción.
El PC será cargado durante el proceso de excepción por RESET con el
contenido de la dirección 0x(00)00_0004 (recordar que la carga es en
modo big endian).
3.2 Módulo LCD
La pantalla se trata de un módulo LCD ST7066U, cuyo fabricante es Powertip
Technology Corporation, de 4 líneas de 20 caracteres que va alimentado a 5 V.
Figura 5: Módulo LCD ST7066U
Hardware
37
La pantalla cuenta con 16 patas, de las cuales, y según el manual que se nos ha
facilitado, sólo 14 de ellas cuentan con una funcionalidad concreta que pasamos a
detallar a continuación:
Pin Símbolo Descripción
1 Vss Tierra de alimentación
2 Vdd Alimentación de +5V
3 V0 Contraste del cristal líquido. Normalmente se conecta a un
potenciómetro a través del cual se aplica una tensión variable
entre 0 y +5V que permite regular el contraste del cristal líquido.
4 RS Selección del registro de control/registro de datos:
RS=0 Selección del registro de control
RS=1 Selección del registro de datos
5 R/W Señal de lectura/escritura
R/W=0 El Módulo LCD es escrito
R/W=1 El Módulo LCD es leído
6 E Señal de activación del módulo LCD:
E=0 Módulo desconectado y no funcionan las demás señales
E=1 Modulo conectado
7-14 D0-D7 Bus de datos bidireccional. A través de estas líneas se realiza la
transferencia de información entre el módulo LCD y el sistema
informático que lo gestiona
Tabla 3: Descripción de los pines del módulo LCD
Desarrollo práctico
39
4. Desarrollo pra ctico
4.1 Configuración del microcontrolador para su funcionamiento como controlador
MIDI
El proyecto consistirá en una caja electrónica que emitirá datos MIDI a través de
su interfaz MIDI OUT en función de su inclinación. Para ello, nos serviremos del
acelerómetro integrado en el microcontrolador. Además, tendrá los siguientes
elementos:
- Una pantalla LCD en la que se podrá ver el estado actual del volumen y el
instrumento que está sonando, así como la inclinación de la caja.
- Un control giratorio que servirá para controlar el volumen del sonido emitido.
- Un botón de mute, para cambiar la característica del mute
- Un botón de instrumento, para cambiar de instrumento cada vez que se pulse.
Además tendrá un puerto MIDI de salida para conectar con otro dispositivo (un
ordenador, una tarjeta de sonido…) y un puerto para conectar el cable de alimentación.
Puesto que hemos decidido integrar la placa dentro de una caja electrónica en la
que se van a implantar los botones a usar, necesitamos conectar dichos botones
(incluido el control giratorio) a los puertos analógicos de la placa, para que los datos
puedan ser leídos, ya que no se podrán usar ni el potenciómentro ni los botones
integrados en la propia placa. Así pues, hemos elegido el puerto PTF2 para el mute, que
corresponde al pin 43 de la placa; el PTF3 para el cambio de instrumento,
correspondiente al pin 41, y el PTG3 para leer el valor de volumen, que corresponde al
pin 55.
Desarrollo práctico
40
4.2 Pantalla LCD
4.2.1 Configuración de la pantalla LCD
El primer paso lógico antes de empezar con la programación es conocer el
funcionamiento de la pantalla LCD, que debemos ser capaces de manejar antes de pasar
a la programación en sí.
En nuestro proyecto, usaremos el puerto serie SPI del microcontrolador para
comunicarnos con el módulo LCD. Además, para nuestra aplicación, no es necesario
que la pantalla intercambie información con el microcontrolador, sólo hace falta una
comunicación unidireccional. Es decir, que el microcontrolador que tenemos que
programar transmita los datos al microcontrolador que lleva incluida la pantalla, que es
el que se encargará de configurarla o de mostrar caracteres según la información que le
pasemos. Podría haberse programado para que se recibieran datos, pero era innecesario.
La alimentación de la pantalla la haremos a través de una fuente de alimentación
a +5V y, como aconseja el manual, le colocaremos un potenciómetro al montaje para
poder cambiar el contraste de la pantalla. Además, como sólo necesitaremos escribir en
el módulo LCD, colocaremos permanentemente la pata R/W a tierra. Después de esto
necesitaremos un total de 10 señales entre nuestro micro y la pantalla.
El primer obstáculo con el que nos encontramos es que, como se indica
previamente, la pantalla funciona a una tensión de 5 V, mientras que la tarjeta
DEMOQE sólo trabaja con un máximo de 3,3 V. Así que ha sido necesario subir las
señales de comunicación con la pantalla para que ésta pueda recibir la información de
forma adecuada. La solución que se ha propuesto es la que aparece en la figura 6.
Para los bits RS y E, hemos hecho uso de una puerta inversora 74HC14, que
admite valores típicos de 3,3 V como entradas y da valores alrededor de los 5 V como
salidas. Con esto, podemos pasar la señal dos veces por los inversores y obtener la
subida de voltaje necesaria. En el caso de los bits D0 a D7, era necesario emplear un
registro de desplazamiento 74HC595 para volcar directamente los datos a la pantalla. El
registro de desplazamiento funciona con tres señales del módulo SPI2 del
microcontrolador, MOSI2, SPSCK2 y SS2. A cada pulso del reloj SPSCK, el valor de
MOSI va cambiando de valor para los 8 bits que queremos transmitir por el bus de
Desarrollo práctico
41
datos. La señal de SPSCK se emplea para almacenar los datos de MOSI en el registro de
desplazamiento uno a uno. Una vez se han terminado de transmitir los datos, el micro
pone SS a nivel alto. Esta última señal la empleamos para que el 74HC595 pase los
datos al módulo LCD. A su vez, este elemento sube la tensión a los 5 V necesarios en la
pantalla del mismo modo que lo anterior, por lo que no es necesario emplear más
puertas inversoras.
4.2.2 Inicialización de la pantalla LCD
Para configurar la pantalla antes de poder escribir en ella, es necesario enviar
una serie de mensajes por el bus de datos poniendo RS=0. Esto prepara la pantalla en
cuestiones como si se muestra y/o parpadea el cursor, vaciarla de contenido, el tamaño
de los caracteres, si se escribe incrementando o decrementando el cursor, si se activa la
pantalla, etc. Los pasos a seguir en la secuencia de inicialización son los siguientes (las
esperas entre paréntesis son necesarias para que la pantalla reconozca y procese la
orden):
Figura 6 Conexiones entre la tarjeta DEMOQE y la pantalla
Desarrollo práctico
42
• Function Set: Establece conexión con el bus de datos (40 s).
• Clear Display: Borramos de contenido la pantalla (15 s).
• Function Set: Ajusta bus, caracteres y nº de líneas (40 s).
• Display On/Off Control: Encender pantalla y eliminar cursor (40 s).
• Entry Mode Set: Ajustar movimiento del cursor hacia la derecha (15 s).
D7 D6 D5 D4 D3 D2 D1 D0
Function Set 0 0 1 1 1 0 0 0
Clear Display 0 0 0 0 0 0 0 1
Function Set 0 0 1 1 1 0 0 0
Display On/Off Control 0 0 0 0 1 1 0 0
Entry Mode Set 0 0 0 0 0 1 1 0
Tabla 4 Mensajes inicialización pantalla LCD
4.3 Montaje
4.3.1. Conexión de los elementos
En la siguiente figura se muestra como queda el conexionado de todos los elementos
una vez que ya lo tenemos todo funcionando correctamente y está listo para pasarlo de
la placa de pruebas a un plaza de circuito impreso, con los componentes soldados. El
esquemático ha sido dibujado con una herramienta del programa P-CAD 2006.
Desarrollo práctico
43
Figura 7: Conexión de todos los elementos
Desarrollo práctico
44
4.3.2 Rutado en PCB, diseño revelado de la placa
En el momento de diseñar una placa de circuito impreso se deben tener en
cuenta todos los integrados que se soldarán a la placa y su tamaño, en vistas de
optimizar en la medida de lo posible la compatibilidad y ergonomía del dispositivo.
Además, para conectar la tarjeta MIDI directamente al microcontrolador se
empleará un integrado consistente en un puerto MIDI cuyos pines utilizables, definidos
en apartados anteriores, se unen al microcontrolador resistencia mediante. Sin embargo,
como éste va incrustado en nuestro montaje, hay que extraer los pines a alguna zona de
la PCB para conectar dicho integrado.
Los componentes quedarán distribuidos de la siguiente forma:
Y el resultado final real de la placa de circuito impreso será el siguiente:
Figura 8: Componentes PCB
Figura 9: Cara inferior PCB
Desarrollo práctico
45
4.4 Funcionamiento del programa
En este apartado explicaremos en detalle el funcionamiento del programa que,
posteriormente, se cargará en la memoria del microcontrolador. Para ello nos basaremos
especialmente en los diagramas de flujo que se muestran a continuación.
El programa se ha realizado, compilado y ejecutado utilizando el programa
Freescale Codewarrior en su versión 5.9, disponible para descargar desde la propia
página web del fabricante.
Figura 10: Cara superior PCB
Figura 11 Freescale Codewarrior 5.9
Desarrollo práctico
46
4.4.1. Main.c
Al comienzo de esta función, se inicializan tanto la pantalla como todas las
variables que usaremos en el programa. Pese a que contamos con 16 canales MIDI, para
todo el desarrollo del proyecto usaremos el canal 1.
La función principal del programa, main, consiste en un bucle for sin
condiciones, por lo que se ejecuta de forma indefinida. Dentro de dicho bucle, se
definen una serie de estados en los que se entrará si se activan unas banderas definidas
en forma de variable entera (si el valor de la bandera cambia a 1), cuyo valor por
defecto es cero. Estos estados son:
• Cambio de nota: Si la bandera estado_nota se activa, entraremos en este bucle
if. La nota que esté sonando en ese momento se apagará mediante la función
N_OFF, y se encenderá otra nota mediante la función N_ON. Tanto el valor de
la bandera como los argumentos de ambas funciones son modificados por
interrupción. A continuación se llama a la función escribeinclinacion, que
enviará a la pantalla LCD un conjunto de barritas en función de la nota
encendida. Al final del bucle, la bandera estado_nota vuelve a desactivarse,
cambiando su valor a cero.
• Actualización del volumen: Entraremos en este bucle cuando se active la
bandera estado_volumen. Se enviará por pantalla el valor del volumen
mediante la función escribevolumen para, a continuación, enviar el valor de la
variable volumen mediante el comando control change, primero los 7 bits más
significativos y a continuación, los 7 bits menos significativos, de acuerdo con el
estándar MIDI. Tanto el valor de la bandera como el de la variable volumen son
modificados por interrupción. Al final del bucle, la bandera estado_volumen
vuelve a desactivarse, cambiando su valor a cero.
Desarrollo práctico
47
• Cambio de mute: Se accederá a este estado cuando se active la bandera
estado_mute, que desactivará el sonido si éste está activado y viceversa. El
funcionamiento de este bucle es igual que el anterior, solo que en este caso la
variable volumen se verá modificada en otra parte del código que veremos más
adelante, no por interrupción. A continuación se llamará a la función
escribemute que enviará por pantalla el estado de mute, y se desactivará la
bandera estado_mute.
• Cambio de instrumento: Se accederá a este estado cuando se active la bandera
estado_instrumento. Por defecto está activado el piano, que implica que el
valor de la variable instrumento sea cero. De aquí cambiará al violín y, desde
éste, a la flauta. Al volver a entrar, volverá al instrumento inicial, el piano. Solo
se producirá un cambio de instrumento cada vez que se entre en este bucle. A
continuación se llamará a la función escribeinstrumento que enviará por
pantalla el tipo de instrumento en funcionamiento, y se desactivará la bandera
estado_instrumento.
• Cambio de modulación: Si la bandera estado_modulacion se activa,
entraremos en este bucle if. Se enviará el valor de la modulación con un
comando control change, de acuerdo al estándar MIDI. Tanto el valor de la
bandera como el de la variable modulacion son modificados por interrupción. A
continuación se llama a la función escribeinclinacion, que enviará a la pantalla
LCD un conjunto de barritas en función de la nota encendida. Al final del bucle,
la bandera estado_modulacion vuelve a desactivarse, cambiando su valor a cero.
Desarrollo práctico
48
A continuación, dentro de la función principal, también se realiza la
comprobación de la activación de los pulsadores de mute y cambio de instrumento:
Figura 12 Diagrama de flujo main.c
Desarrollo práctico
49
• Comprobación del pulsador cambiar instrumento: En este bucle se comprueba
si se ha pulsado el botón de cambio de instrumento, conectado al puerto PTF3
del microcontrolador, activo a nivel bajo. Cuando se detecte que se ha pulsado el
botón, se activará la bandera estado_instrumento. Se realiza la comprobación
pulsar/soltar dos veces para eliminar posibles activaciones erróneas por rebotes
indeseados de la señal. Utilizamos la variable CAMBIA_INST_PULSADA
como un mecanismo de redundancia respecto a la lectura del puerto PTF3.
• Comprobación del pulsador cambiar volumen: Igual que el anterior, con entrada al
puerto PTF2 del microcontrolador. En este caso, cuando se pulsa el botón, se entra en
un bucle if-else que comprueba si ya estaba silenciado. En caso negativo (hay volumen),
se guarda el valor de la variable volumen en la variable volumen_old, se cambia el
valor de volumen a cero y se activa la bandera mute, que se utilizará más adelante en la
interrupción de cambio de volumen. En caso contrario, será el valor de volumen_old
guardado cuando se silenció el que pasará a la variable volumen y se desactivará la
bandera mute. Utilizamos la variable MUTE_PULSADA como un mecanismo de
redundancia respecto a la lectura del puerto PTF2.
Figura 13 Diagrama de estados del pulsador cambio de instrumento
Desarrollo práctico
50
4.4.2 Funciones_2.c
En este apartado se enumerarán y explicarán las funciones creadas para este
proyecto. Primero trataremos las funciones básicas del programa que interactúan con la
pantalla y la tarjeta MIDI.
• void mandachar (char kk): Espera a que el bus no esté transmitiendo nada y,
entonces, envía el carácter recibido como argumento.
• void mandacadena (char * cadena): Envía la cadena de caracteres recibida
como argumento apoyándose en la función mandachar que acabamos de ver,
hasta encontrar un “$”. Tras enviar la cadena, envía un avance de línea y un
retorno de carro.
• void espera (int ms): Crea un tiempo de espera en milisegundos del valor que
recibe como argumento.
• void mandachar_LCD (char kk): Se emplea para mandar datos que se
dibujarán en la pantalla. Para ello, ponemos RS y E a 1, esperamos a que el bus
Figura 14 Diagrama de estados del pulsador MUTE
Desarrollo práctico
51
esté vacío antes de mandar los datos y, tras esto, ponemos los datos a enviar en
el bus. Esperamos a que dichos datos sean recibidos por la pantalla, vaciamos el
bus y ponemos E=0 para finalizar el envío de datos.
• void mandacom (char kk): Es una función idéntica a la anterior con la
diferencia de que RS=0, lo que significa que estamos mandando datos de
configuración en lugar de datos que se escribirán en la pantalla.
• void mandacadena_LCD (char * cadena): Envía la cadena de caracteres
recibida como argumento apoyándose en la función mandachar_LCD vista,
hasta encontrar un “$”.
A continuación detallaremos las funciones que nos servirán para inicializar la pantalla,
movernos a través de ella y enviar datos
• void posición (int fil, int col): Esta función se emplea para colocarnos en la
posición de la pantalla en la que queremos escribir. Las posiciones de la pantalla
se almacenan a partir de la posición de memoria 0x80 del microcontrolador de la
pantalla, llamada memoria DDRAM.
La peculiaridad de esto radica en que para escribir en cada posición, no basta
con escribir en orden ascendente a partir de la posición de memoria 0x80. Así
para los 20 primeros caracteres de la primera fila, hay que sumar de 0x00 a 0x13
a la posición 0x80. Para la segunda hay un salto y hay que sumar de 0x40 a
0x53. Para la tercera volvemos a donde termina la primera, es decir, sumando de
0x14 a 0x27. Y para la cuarta, volvemos a donde acaba la segunda, es decir,
sumando de 0x54 a 0x67. Esto se ha tenido en cuenta, por lo que, empleando
mandacom situamos la dirección DDRAM tal y como indica el manual, lo que
equivale a mandar 0x80 más el comienzo de la línea en hexadecimal (0x00,
0x40, 0x14, 0x54), más la columna a la que quieras desplazarte empezando por
el cero.
• void inicializa_pantalla (void): Usaremos los comandos explicados en un
apartado anterior apoyándonos en la función mandacom.
Desarrollo práctico
52
• void inicializa_datos_pantalla (void): Inicializamos los datos de la pantalla.
Se escribe el título “PFC Eduardo Gonzalez”, el valor del mute, el del volumen,
la inclinación y el instrumento.
• void escribevolumen (int volumen): Envía por pantalla un valor entre 0 y 7
dependiendo del valor de la variable recibida como argumento.
• void escribemute (void): Envía por pantalla un SI o un NO en función de si
está activada o no la función mute.
• void escribeinclinacion (void): Envía por pantalla una barra más o menos
rellena en función de la inclinación de la caja.
• void escribeinstrumento (int inst): Envía por pantalla el instrumento que está
activo, de acuerdo al valor de la variable inst que se le pasa como argumento.
Para terminar, describiremos las funciones utilizadas dentro del bucle principal,
y que hacen uso del protocolo MIDI
• void N_OFF (char a): Envía el comando NOTE OFF para apagar la nota
recibida como argumento.
• void N_ON (char a): Envía el comando NOTE ON para encender la nota
recibida como argumento.
• void setpiano (void): Envía el comando PROGRAM CHANGE para, a
continuación, enviar el valor 0 que corresponde a cambiar el instrumento a
piano.
• void setviolin (void): Envía el comando PROGRAM CHANGE para, a
continuación, enviar el valor 40 que corresponde a cambiar el instrumento a
violín.
• void setflute (void): Envía el comando PROGRAM CHANGE para, a
continuación, enviar el valor 73 que corresponde a cambiar el instrumento a
flute.
Desarrollo práctico
53
4.4.3 Interrupciones (MCUinit.c)
En este apartado se ha programado una única interrupción, la del reloj en tiempo
real RTC. En ella, que se activa cada 10 ms, hemos implementado la lectura de los ejes
x,y del acelerómetro incluido en el microcontrolador, y el potenciómetro
correspondiente a la rueda que controla el volumen. Hay que recordar que, nada más
entrar a la interrupción, hay que poner RTCSC_RTIF=1 para hacer un acknowledge y
permitir que la interrupción pueda volver a saltar.
• Lectura del eje x del acelerómetro: Se produce la lectura del eje x si la bandera
estado_nota está desactivada, para evitar que el valor de la nota a
encender/apagar en proceso cambie. Primero, ponemos el valor de ADCSC1 a
0x01, que hace que se lea el valor del puerto PTA1, correspondiente al eje x del
acelerómetro, y lo convierta a un valor digital de 12 bits, almacenado en la
variable ADCR. Como la escala de notas va de 0 a 127, y nosotros solo
utilizaremos 32 valores intermedios recogidos en el vector vector_notas,
dividimos el valor entre 128 para tener una variabilidad de 5 bits, y se lo
asignamos a la variable índice_nota, con la que posteriormente iremos
recorriendo el vector. A continuación, si la nota es distinta a la que sonó
anteriormente, se asigna a la variable nota, y el valor anterior de nota, a
nota_old para poder apagar la nota posteriormente. Finalmente, se activa la
bandera estado_nota para entrar en el estado “Cambio de nota” del bucle
principal, definido anteriormente.
• Lectura del eje y del acelerómetro: Primero, ponemos el valor de ADCSC1 a
0x08, que hace que se lea el valor del puerto PTA6, correspondiente al eje y del
acelerómetro, y lo convierta a un valor digital de 12 bits, almacenado en la
variable ADCR. Al igual que antes, utilizaremos valores intermedios entre 20 y
35, por lo que como necesitamos una variabilidad de 4 bits, dividimos entre 256.
Este valor se asigna a la variable modulación. Finalmente, se activa la bandera
estado_modulacion para entrar en el estado “Cambio de modulación” del bucle
principal, definido anteriormente.
Desarrollo práctico
54
• Lectura del potenciómetro correspondiente al volumen: Primero, ponemos el
valor de ADCSC1 a 0x13, que hace que se lea el valor del puerto PTG3 al que
está conectado el potenciómetro con el que manejaremos el volumen, y lo
convierta a un valor digital de 12 bits, almacenado en la variable ADCR. Como,
de acuerdo al estándar MIDI, necesitaremos un valor del volumen de 14 bits,
multiplicamos el valor de ADCR por 4 y lo asignamos a la variable volumen si
hay una diferencia significativa respecto al valor anterior y no estamos en
situación de mute. Finalmente, se activa la bandera estado_volumen para entrar
en el estado “Actualización del volumen” del bucle principal, definido
anteriormente.
Figura 15 Diagrama de flujo de la interrupción
Resultados experimentales
55
5. Resultados experimentales
5.1 Montaje en la placa de pruebas
Una vez que ya hemos visto como conectar los componentes, realizaremos el
montaje en la placa de pruebas para, posteriormente, comprobar el funcionamiento del
programa. Para ello, usaremos una placa de pruebas estándar y un lote de cables de
colores para realizar las conexiones.
Figura 16 Protoboard (Placa de pruebas)
Figura 17 Cables de colores arduino
Resultados experimentales
56
Para la alimentación del circuito se planteaba un problema, y es que no existía
disponibilidad de un módulo de alimentación en donde se estaba realizando el proyecto.
Para evitar desplazamientos innecesarios al laboratorio, aprovechamos la circunstancia
de que el circuito necesita una alimentación estándar de 5 voltios, proporcionada por
cualquier cargador de teléfono móvil. Así pues, nos hacemos con un cargador de móvil
Motorola antiguo y se pelan los cables para conectarlo a la placa de pruebas.
Puesto que el ordenador portátil en el que se ejecutará el programa y se realizará
la captura de señales MIDI no tiene ningún puerto MIDI, contaremos con una tarjeta de
sonido que incluya estos puertos que sirva como puente entre el PC y el
microcontrolador.
En nuestro caso, utilizaremos una tarjeta de sonido M-Audio Fast Track Pro:
Figura 18 Transformador de corriente
Resultados experimentales
57
Realizamos las conexiones entre todos los componentes (microcontrolador,
pantalla LCD, integrados…) y el resultado es el siguiente:
Figura 19: Tarjeta de sonido M-Audio Fast Track Pro
Figura 20 Montaje en placa de pruebas
Resultados experimentales
58
Más en detalle:
Figura 21 Montaje detallado en placa de pruebas
Resultados experimentales
59
5.2 Visualización de resultados en el PC
En este apartado veremos los programas utilizados para comprobar el correcto
funcionamiento del programa. Todos serán usados bajo un sistema operativo Windows
7 x86.
- Midi-ox
Programa de propósito general, todo relacionado al MIDI. Será usado para
monitorizar en pantalla todos los eventos MIDI recibidos a través de la tarjeta de
sonido. Así se podrá comprobar si por ejemplo una nota activada en un instante es
desactivada antes de activar la siguiente, si se cambia correctamente el volumen, etc.
Para ello, a la hora de configurarlo, hay que especificarle al programa qué es lo que va a
“escuchar”, por lo que en nuestro caso se selecciona el puerto MIDI IN de la tarjeta de
sonido Fast Track Pro.
Se puede descargar desde la propia página del programa, midiox.com, de forma
gratuita (aunque los desarrolladores incorporan la opción de realizar donaciones
voluntarias).
Figura 22 MIDI-OX monitorizando las señales
Resultados experimentales
60
- Sintetizador
El sintetizador es un programa necesario para que el PC pueda interpretar
correctamente las señales MIDI recibidas y, así, poder monitorizarlas. En este caso se ha
decidido por usar el RGC audio por su sencillez. Para ello, es necesario cargar el
archivo de configuración sfz+.dll, así como una fuente de sonidos, que será ct4mgm.sf2.
El archivo de configuración también se puede conseguir gratuitamente desde hace algún
tiempo, cuando Cakewalk adquirió RGC audio y liberó su código.
Figura 23 Sintetizador
Resultados experimentales
61
5.3 Comprobación de las señales eléctricas
En este apartado nos serviremos de un osciloscopio para comprobar que lo que
se envía por el puerto midi son, efectivamente, datos MIDI. Para ello, colocamos la
sonda del osciloscopio en el pin del cable MIDI correspondiente a la transmisión de
datos, visto anteriormente.
Teniendo en cuenta que la frecuencia de una señal MIDI es de 31.250 baudios,
establecemos los cursores del osciloscopio separados dicha frecuencia, para poner
observar la trama entera de los datos MIDI.
Establecemos un breakpoint en el programa en el bucle que envía la señal digital
correspondiente al volumen. Como se ha visto en apartados anteriores, el primer byte
(byte de estado) que se debe enviar para cambiar el volumen del canal 1 es un comando
control change, que quedaría tal que así
10110000 = 1 (bit que indica status byte) + 011 (control change) + 0000 (canal 1)
El segundo byte, de acuerdo con el estándar MIDI, debe comenzar por 0 para
indicar byte de datos, seguido del valor correspondiente al parámetro que queremos
cambiar. En caso de que en el tercer byte enviaremos los 7 bits más significativos del
valor del volumen, por lo que el segundo byte debe enviar un 7. Así pues, el segundo
byte quedaría:
00000111 = 0 (bit que indica byte de datos) + 0000111 (MSB del Volumen)
Puesto que se empiezan a enviar primero los bits menos significativos, en la
señal capturada en el osciloscopio veremos los datos digitales colocados de forma
inversa, por lo que hay que leerlos de derecha a izquierda. Quedaría tal que así:
Figura 24 Señal visualizada en el osciloscopio
Resultados experimentales
62
donde el nivel alto corresponde a 5 voltios, y el tiempo transcurrido entre el inicio y el
bit de un bit es de 32 microsegundos.
Una vez finalizado y cargado el programa, y comprobado su correcto funcionamiento,
ya sólo nos queda realizar el diseño de la carcasa y el montaje físico. Esto lo veremos en
el siguiente capítulo.
Montaje físico
63
6. Montaje fí sico
6.1 Revelado del PCB
Una vez que tenemos el montaje funcionando en la placa de pruebas, llega el
momento de trasladar ese montaje a una placa de pruebas, cuyo diseño se vio en el
apartado 4.3.2. Para ello nos hemos acercado a la sala de impresión de circuitos en el
laboratorio de ingeniería electrónica de la escuela. Los pasos que hemos seguido para
obtener el PCB son:
• Impresión de ambas caras del rutado en papel de cebolla.
• Insolado de la placa fotosensible durante 2 minutos 30 segundos.
• Exposición de la placa al líquido revelador.
• Baño en mezcla de 2 partes de agua, 1 parte de peróxido de hidrógeno y 1 de
ácido clorhídrico para eliminar el cobre innecesario en la placa.
• Limpieza con acetona para eliminar impurezas.
• Taladrado de los diferentes agujeros.
• Soldadura de los componentes electrónicos
• Otros elementos adicionales (cables, pantalla, micro…)
Figura 25 Corte de la placa
Montaje físico
64
6.2 Realización del montaje
6.2.1 Componentes utilizados
Los componentes utilizados en el montaje físico han sido adquiridos en su
mayoría a la tienda Metro Electrónica S.L., situada en Barcelona. Se pasa a detallar cada
uno de los componentes a continuación
• Caja RETEX Serie 103 (190x115x72 mm.): Es la carcasa del conjunto,
fabricada en ABS con tapa en aluminio anodizado. Precio: 16,98€
• Potenciómetro tipo 21 de 2K2 ohmios para el control de volumen. Precio:
1,60€
• Botón de mando 214/0201: Para darle al potenciómentro de control de
volumen un aspecto estético. Precio: 1,42€
• Conector alimentación macho + base chasis: Usado para adaptar el conector de
alimentación del microcontrolador a la carcasa. Precio: 2,27€
Figura 26 Eliminación del cobre
Montaje físico
65
6.2.2 Montaje paso a paso
Paso 1: Lo primero que hay que hacer es imaginar una vista panorámica del
conjunto. Teniendo en cuenta que la tarjeta DEMOQE irá en el fondo de la caja, y la
pantalla LCD estará adherida a la cara de la superficie, para poder abrir y manipular la
caja será necesario que uno de los dos no esté físicamente unido al PCB en el montaje
final. Puesto que el número de puertos de la pantalla LCD es significativamente menor,
se ha optado por esta última como componente unido a la placa. En uno de los laterales
de la caja irá el puerto de alimentación y la salida MIDI OUT.
Paso 2: Una vez que ya se tiene la idea del diseño, el siguiente paso será realizar
en la caja los orificios correspondientes para los puertos de salida, la pantalla y la
fijación de los elementos hardware a la caja. Se realizan 4 orificios para atornillar la
tarjeta DEMOQE, 2 orificios para el integrado MIDI, un orificio para colocar el puerto
de alimentación, un agujero para el puerto MIDI, 3 orificios en la parte frontal para los
controles de mute, instrumento y volumen, así como un espacio para colocar la pantalla
LCD.
Los orificios de un tamaño considerable se han realizado marcando sobre la caja
el tamaño que deben tener para, a continuación, realizar pequeños agujeros con un
taladro a lo largo del perímetro. Esto se ve más claro en la siguiente figura:
Figura 27 Realización agujero pantalla
Montaje físico
66
A continuación, una vez que ya tenemos los agujeros realizados, nos ayudamos
de una lima para tratar de darle un acabado uniforme
Figura 28 Realización agujero Puerto MIDI
Figura 29 Limado agujero Puerto MIDI
Montaje físico
67
Paso 3: Una vez que ya se han realizado todas las perforaciones y se ha
comprobado que los componentes encajan a la perfección, es la hora de realizar la parte
más crítica del montaje: las soldaduras. Se realizarán derritiendo estaño sobre las
uniones del PCB utilizando un soldador JBC, ayudados de una pequeña esponja
empapada para limpiar el soldador y así evitar que se formen acumulaciones de estaño
que podrían incluso producir un incorrecto funcionamiento del sistema.
Figura 30 Soldador JBC
Figura 31 Realización de soldaduras
Montaje físico
68
Paso 4: Ensamblado de las piezas. Ya realizadas las soldaduras, lo único que queda es
adherir los distintos componentes a la caja, aprovechando los orificios realizados en el
paso 1.
Figura 32 Ensamblado de las piezas
Montaje físico
69
Finalmente se coloca la cubierta en la caja y se atornilla, dando por finalizado el
montaje. En el siguiente apartado se analizará el aspecto final y, más adelante, se
comprobará el funcionamiento del dispositivo.
6.3 Aspecto final y funcionamiento del dispositivo
Tras ajustar la cubierta, fijar los tornillos y las bisagras, el aspecto final que
presenta el dispositivo, visto frontalmente, es el siguiente:
Mientras que, lateralmente, se ve de la siguiente forma:
Figura 33 Aspecto final: vista frontal
Montaje físico
70
Tan solo queda realizar las conexiones del instrumento con los elementos externos. Así
pues, se realizan las conexiones del dispositivo a alimentación y a la tarjeta de sonido
externa y ésta, a su vez, al ordenador, quedando el montaje final de la siguiente forma:
Figura 34 Aspecto final: vista lateral
Montaje físico
71
Se realiza la inicialización de los programas explicados en apartados anteriores y se
comprueba como todo funciona correctamente: pulsadores, rueda de volumen,
sensibilidad del movimiento, etc.
Figura 35 Instrumento conectado y funcionando
Conclusiones
73
7. Conclusiones
Tras el desarrollo realizado, la primera conclusión a obtener es la adecuada
consecución del objetivo marcado: el diseño y la realización de un instrumento musical
MIDI basado en control de inclinación.
A continuación trataremos los objetivos cumplidos y las posibles mejoras a
realizar:
Se ha diseñado un instrumento musical MIDI innovador, debido a que para
cambiar de nota lo que debemos hacer simplemente es inclinar el aparato.
Además, gracias a que le hemos incluido controles de mute, instrumento y
volumen, podemos personalizar en gran medida el tipo de sonido que queremos
emitir
El diseño final del PCB ha quedado de un tamaño menor al que hubiésemos
pensado en un principio, lo que ha redundado en la elección de una caja externa
más pequeña.
El diseño final del instrumento ha resultado compacto y cómodo en el manejo. A
pesar de que esto obviamente es una ventaja, lleva aparejado un inconveniente
que explicaremos más adelante, cuando veamos las posibles mejoras a realizar
en el proyecto.
En un futuro, se podrían realizar otras modificaciones para mejorar el instrumento
MIDI como, por ejemplo:
Conclusiones
74
En el mundo actual se valora mucho la movilidad de los dispositivos, esto es,
no estar sujeto a conexiones cableadas. Así pues, una interesante mejora
sería eliminar el cable MIDI que conecta el instrumento con un ordenador, y
realizar esta conexión inalámbricamente utilizando, por ejemplo, bluetooth.
El instrumento, al ser bastante pequeño, hace que un pequeño movimiento
conlleve una gran variabilidad del ángulo. Por lo tanto, una mejora
interesante sería aumentar su longitud, y así podríamos usar un mayor
número de notas al ser menos sensible al cambio de ángulo
Se ha usado un solo canal MIDI de los 16 disponibles. Se podrían usar otros
canales para otros menesteres como, por ejemplo, usar otro tipo de notas
distintas (más graves o más agudas) que hagan sonar el instrumento, en vez
de las notas intermedias con las que se ha implementado.
Bibliografía
75
8. Bibliografí a
Páginas web
Wikipedia. Página Web, URL: http://es.wikipedia.org/wiki/Microcontrolador
Guía Audio digital y MIDI, de Sergi Jordà. Página Web, URL:
http://www.ccapitalia.net/reso/articulos/audiodigital/
Manual MIDI, Roland.
Datasheets
Freescale MCF51QE128
74HC14
74HC595
ST7066U
PFC y otros trabajos
Cristóbal Cordobés Berraquero: Diseño y realización de un controlador MIDI a
través de una interfaz USB
María del Mar Morales y Julio Díaz-Pezcuezo: Tres en Raya electrónico
Anexos
77
9. Anexos
9.1 Código fuente del controlador MIDI
- Main.c
#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
#ifdef __cplusplus
extern "C"
#endif
void MCU_init(void); /* Device initialization function declaration */
void mandachar (char );
void mandacom(char ); // Manda un comando a la pantalla por SPI
void espera(int ); // Espera varios milisegundos void mandacadena(char *);
void mandacadena_LCD(char *);
void mandachar_LCD(char ); // Manda un dato a la pantalla por SPI
void manda_midi(char *);
void posicion (int ,int );
void inicializa_pantalla (void);
void inicializa_datos_pantalla (void);
void escribevolumen (int );
void escribemute ();
void escribeinclinacion (void);
void escribeinstrumento (int );
void N_OFF(char );
void N_ON(char );
void setviolin(void);
void setpiano(void);
void setflute(void);
#define mi1 40
#define fa1 41
#define sol1 43
#define la1 45
#define si1 47
#define do2 48
#define re2 50
#define mi2 52
#define fa2 53
#define sol2 55
#define la2 57
Anexos
78
#define si2 59
#define do3 60
#define re3 62
#define mi3 64
#define fa3 65
#define sol3 67
#define la3 69
#define si3 71
#define do4 72
#define re4 74
#define mi4 76
#define fa4 77
#define sol4 79
#define la4 81
#define si4 83
#define do5 84
#define re5 86
#define mi5 88
#define fa5 89
#define sol5 91
#define la5 93
int vector_notas[]={mi1, fa1, sol1, la1, si1, do2, re2, mi2, fa2, sol2, la2,
si2, do3, re3, mi3, fa3, sol3, la3, si3, do4, re4, mi4, fa4, sol4, la4, si4,
do5, re5, mi5, fa5, sol5, la5};
#define NOTE_OFF 0x80
#define NOTE_ON 0x90
#define CC 0xB0
char cadena[3];
short VOL;
short puntero;
short estado_nota, estado_volumen, estado_mute, estado_instrumento,
estado_modulacion;
int volumen, vol_nue, volumen_old, nota_nueva, nota, nota_old, modulacion,
indice_nota;
int instrumento=0, mute=0;
short int CAMBIA_INST_PULSADA=0, MUTE_PULSADA=0; // estas variables indican si
se pulsaron los botones de cambiar instrumento o mute
void main(void) {
MCU_init(); /* call Device Initialization */
Anexos
79
int v;
int modulacionLSB=0x0;
VOL=100;
puntero=0;
estado_nota=estado_volumen=estado_mute=estado_instrumento=estado_modulac
ion=0;
volumen=0x3FFF;
inicializa_pantalla ();
espera(20); // Esperamos 20 milisegundos a que la pantalla esté lista
inicializa_datos_pantalla ();
espera(50);
PTFD=0b11101111; // Inicializamos las salidas del puerto F
PTGD=0b11101111; // Inicializamos las salidas del puerto G
escribeinstrumento(instrumento);
escribevolumen(volumen);
mandachar(CC);
mandachar(33); //Inicializo el LSB del modulación a cero
mandachar(modulacionLSB);
setpiano();
for(;;) {
if(estado_nota==1) {
N_OFF(nota_old);
N_ON(nota);
escribeinclinacion();
estado_nota=0;
}
if(estado_volumen==1) {
escribevolumen(volumen);
mandachar(CC);
mandachar(7);
mandachar((volumen>>7));
mandachar(39);
mandachar((volumen & 0x007f));
estado_volumen=0;
}
if(estado_mute==1) {
mandachar(CC);
mandachar(7);
mandachar((volumen>>7));
mandachar(39);
mandachar((volumen & 0x007f));
escribemute();
Anexos
80
estado_mute=0;
}
if(estado_instrumento==1) {
switch(instrumento) {
case 0:
setviolin();
break;
case 40:
setflute();
break;
case 73:
setpiano();
break;
}
escribeinstrumento(instrumento);
estado_instrumento=0;
}
if(estado_modulacion==1) {
mandachar(CC);
mandachar(1);
mandachar((modulacion));
estado_modulacion=0;
}
/* Comprobación de los pulsadores mute y cambiar instrumento */
if(!PTFD_PTFD3 && CAMBIA_INST_PULSADA==0) //pulsamos cambiar
instrumento
{
espera(50); //debounce en tecla PTFD3
if(!PTFD_PTFD3){
estado_instrumento=1;
CAMBIA_INST_PULSADA=1;
} //cambiar instrmento ha sido pulsada
}
if(PTFD_PTFD3 && CAMBIA_INST_PULSADA==1) //soltamos cambiar
instrumento
{
espera(50); //debounce en tecla PTFD3
if(PTFD_PTFD3)
CAMBIA_INST_PULSADA=0; //soltar instrumento ha sido
soltada
}
Anexos
81
if(!PTFD_PTFD2 && MUTE_PULSADA==0) //pulsamos mute
{
espera(50);
if(!PTFD_PTFD2){
if(volumen!=0)
{
volumen_old=volumen;
volumen=0;
mute=1;
}
else
{
volumen=volumen_old;
mute=0;
}
estado_mute=1;
espera(50); //debounce en tecla PTFD2
MUTE_PULSADA=1;
}//mute ha sido pulsada
}
if(PTFD_PTFD2 && MUTE_PULSADA==1) { //soltamos mute
espera(50);
if(PTFD_PTFD2)
MUTE_PULSADA=0; //mute ha sido soltada
}
}
}
- Funciones_2.c
/*Funciones auxiliares de uso común*/
/*Mandacadena: manda la cadena apuntada, hasta que encuentra un carácter $, y
a continuación manda un CR+LF.
Puerto Serie SCI sin interrupciones*/
#include "derivative.h" /* include peripheral declarations */
Anexos
82
void mandacadena(char *);
void mandacadena_LCD(char *);
void mandachar(char );
void mandachar_LCD(char );
void espera(int );
void manda_midi(char *);
void mandacom(char );
void posicion (int ,int );
void inicializa_pantalla (void);
void inicializa_datos_pantalla (void);
void escribevolumen (int );
void escribemute ();
void escribeinclinacion (void );
void escribeinstrumento (int );
void N_OFF(char );
void N_ON(char );
void setviolin(void);
void setpiano(void);
void setflute(void);
extern int instrumento, mute, indice_nota;
void mandacadena (char * cadena) {
int i=0;
do{
mandachar(cadena[i]);
i++;
}while(cadena[i]!='$');
mandachar(10);
mandachar(13);
}
/*mandachar: usada en mandacadena, manda un solo caracter*/
void mandachar(char kk) {
while(!SCI1S1_TDRE){}
SCI1D=kk;
}
Anexos
83
/*espera(ms): espera un tiempo, usando el TPM1, por polling.*/
void espera(int ms) {
TPM1SC=0;
TPM1MOD=16*ms;
TPM1CNT=0;
TPM1SC=0x10;
TPM1SC_TOF=0;
while(!TPM1SC_TOF){}
TPM1SC_TOF=0;
}
void manda_midi (char * cadena) {
int i=0;
do{
mandachar(cadena[i]);
i++;
}while(cadena[i]!='$');
}
void mandacadena_LCD (char * cadena) {
int i=0;
do{
mandachar_LCD(cadena[i]);
i++;
}while(cadena[i]!='$');
}
void mandachar_LCD(char kk) {
PTHD_PTHD0=1; // Ponemos la RS a 0 para mandar datos
PTHD_PTHD1=1; // Ponemos E a 1 para empezar el envío de datos
while(!SPI2S_SPTEF){}// Esperamos a que el bus esté vacío
SPI2D=kk; // Copiamos los datos en el bus
Anexos
84
espera(1);
while(!SPI2S_SPRF){}// Esperamos a que se reciba todo
kk=SPI2D; // Vaciamos el bus de datos
PTHD_PTHD1=0; // Ponemos E a 0 para finalizar el envío de datos
}
void mandacom(char kk) {
PTHD_PTHD0=0; // Ponemos la RS a 1 para mandar datos
PTHD_PTHD1=1; // Se repite el proceso de mandachar
while(!SPI2S_SPTEF){}
SPI2D=kk;
espera(1);
while(!SPI2S_SPRF){}
kk=SPI2D;
PTHD_PTHD1=0;
}
void posicion (int fil,int col) {
int num; // Posición de memoria en la DDRAM (A partir de 0x80)
if (fil==1) {
num=0x80+col; // La primera línea es de 0-13 (hexadecimal)
}
if (fil==2) {
num=0x80+0x40+col; // La segunda línea es de 40-53 (hexadecimal)
}
if (fil==3) {
num=0x80+0x14+col; // La tercera línea es de 14-27 (hexadecimal)
}
if (fil==4) {
num=0x80+0x54+col; // La cuarta línea es de 54-67 (hexadecimal)
}
mandacom(num); // Nos situamos en la posición indicada
}
void inicializa_pantalla (void) {
mandacom(0b00111000); // Function Set
espera(20); // Espera 20 milisegundos
mandacom(0b00000001); // Clear Display
Anexos
85
espera(20); // Espera 20 milisegundos
mandacom(0b00111000); // Function Set
espera(1); // Espera 1 milisegundo
mandacom(0b00001100); // Display On/Off Control
espera(1); // Espera 1 milisegundo
mandacom(0b00000110); // Entry Mode Set
espera(20); // Espera 20 milisegundos
}
void inicializa_datos_pantalla (void) {
char cadena[25]; // Dibujamos la pantalla
cadena[0]='P';
cadena[1]='F';
cadena[2]='C';
cadena[3]=' ';
cadena[4]='E';
cadena[5]='d';
cadena[6]='u';
cadena[7]='a';
cadena[8]='r';
cadena[9]='d';
cadena[10]='o';
cadena[11]=' ';
cadena[12]='G';
cadena[13]='o';
cadena[14]='n';
cadena[15]='z';
cadena[16]='a';
cadena[17]='l';
cadena[18]='e';
cadena[19]='z';
cadena[20]='$';
posicion(1,0);
mandacadena_LCD(cadena);
cadena[0]='M';
cadena[1]='u';
cadena[2]='t';
Anexos
86
cadena[3]='e';
cadena[4]=':';
cadena[5]='N';
cadena[6]='O';
cadena[7]=' ';
cadena[8]=0b01111100; //columna
cadena[9]=' ';
cadena[10]='V';
cadena[11]='o';
cadena[12]='l';
cadena[13]='u';
cadena[14]='m';
cadena[15]='e';
cadena[16]='n';
cadena[17]=':';
cadena[18]=' ';
cadena[19]=' ';
cadena[20]='$';
posicion(2,0);
mandacadena_LCD(cadena);
cadena[0]='I';
cadena[1]='n';
cadena[2]='c';
cadena[3]='l';
cadena[4]='i';
cadena[5]='n';
cadena[6]='a';
cadena[7]='c';
cadena[8]='i';
cadena[9]='o';
cadena[10]='n';
cadena[11]=':';
cadena[12]=' ';
cadena[13]=' ';
cadena[14]=' ';
cadena[15]=' ';
cadena[16]=' ';
cadena[17]=' ';
cadena[18]=' ';
cadena[19]=' ';
cadena[20]='$';
posicion(3,0);
mandacadena_LCD(cadena);
Anexos
87
cadena[0]='I';
cadena[1]='n';
cadena[2]='s';
cadena[3]='t';
cadena[4]='r';
cadena[5]='u';
cadena[6]='m';
cadena[7]='e';
cadena[8]='n';
cadena[9]='t';
cadena[10]='o';
cadena[11]=':';
cadena[12]='P';
cadena[13]='I';
cadena[14]='A';
cadena[15]='N';
cadena[16]='O';
cadena[17]=' ';
cadena[18]=' ';
cadena[19]=' ';
cadena[20]='$';
posicion(4,0);
mandacadena_LCD(cadena);
}
void escribevolumen (int volumen) {
if ((volumen>=0)&&(volumen<=2048)){
posicion(2,18);
mandachar_LCD('0');
}else{
if ((volumen>2048)&&(volumen<=4096)){
posicion(2,18);
mandachar_LCD('1');
}else{
if ((volumen>4096)&&(volumen<=6144)){
posicion(2,18);
mandachar_LCD('2');
}else{
if ((volumen>6144)&&(volumen<=8192)){
posicion(2,18);
Anexos
88
mandachar_LCD('3');
}else{
if ((volumen>8192)&&(volumen<=10240)){
posicion(2,18);
mandachar_LCD('4');
}else{
if ((volumen>10240)&&(volumen<=12288)){
posicion(2,18);
mandachar_LCD('5');
}else{
if ((volumen>12288)&&(volumen<=14336)){
posicion(2,18);
mandachar_LCD('6');
}else{
posicion(2,18);
mandachar_LCD('7');
}
}
}
}
}
}
}
}
void escribemute () {
if(mute==0){
posicion(2,5);
mandachar_LCD('N');
posicion(2,6);
mandachar_LCD('O');
}else{
posicion(2,5);
mandachar_LCD('S');
posicion(2,6);
mandachar_LCD('I');
}
}
void escribeinclinacion () {
Anexos
89
if ((indice_nota>=0)&&(indice_nota<=6)){
posicion(3,12);
mandachar_LCD(0b11111111);
posicion(3,13);
mandachar_LCD(' ');
posicion(3,14);
mandachar_LCD(' ');
posicion(3,15);
mandachar_LCD(' ');
posicion(3,16);
mandachar_LCD(' ');
posicion(3,17);
mandachar_LCD(' ');
posicion(3,18);
mandachar_LCD(' ');
posicion(3,19);
mandachar_LCD(' ');
}else{
if ((indice_nota>6)&&(indice_nota<=9)){
posicion(3,12);
mandachar_LCD(0b11111111);
posicion(3,13);
mandachar_LCD(0b11111111);
posicion(3,14);
mandachar_LCD(' ');
posicion(3,15);
mandachar_LCD(' ');
posicion(3,16);
mandachar_LCD(' ');
posicion(3,17);
mandachar_LCD(' ');
posicion(3,18);
mandachar_LCD(' ');
posicion(3,19);
mandachar_LCD(' ');
}else{
if ((indice_nota>9)&&(indice_nota<=12)){
posicion(3,12);
mandachar_LCD(0b11111111);
posicion(3,13);
mandachar_LCD(0b11111111);
posicion(3,14);
mandachar_LCD(0b11111111);
posicion(3,15);
mandachar_LCD(' ');
Anexos
90
posicion(3,16);
mandachar_LCD(' ');
posicion(3,17);
mandachar_LCD(' ');
posicion(3,18);
mandachar_LCD(' ');
posicion(3,19);
mandachar_LCD(' ');
}else{
if ((indice_nota>12)&&(indice_nota<=15)){
posicion(3,12);
mandachar_LCD(0b11111111);
posicion(3,13);
mandachar_LCD(0b11111111);
posicion(3,14);
mandachar_LCD(0b11111111);
posicion(3,15);
mandachar_LCD(0b11111111);
posicion(3,16);
mandachar_LCD(' ');
posicion(3,17);
mandachar_LCD(' ');
posicion(3,18);
mandachar_LCD(' ');
posicion(3,19);
mandachar_LCD(' ');
}else{
if ((indice_nota>15)&&(indice_nota<=18)){
posicion(3,12);
mandachar_LCD(0b11111111);
posicion(3,13);
mandachar_LCD(0b11111111);
posicion(3,14);
mandachar_LCD(0b11111111);
posicion(3,15);
mandachar_LCD(0b11111111);
posicion(3,16);
mandachar_LCD(0b11111111);
posicion(3,17);
mandachar_LCD(' ');
posicion(3,18);
mandachar_LCD(' ');
posicion(3,19);
mandachar_LCD(' ');
}else{
Anexos
91
if ((indice_nota>18)&&(indice_nota<=21)){
posicion(3,12);
mandachar_LCD(0b11111111);
posicion(3,13);
mandachar_LCD(0b11111111);
posicion(3,14);
mandachar_LCD(0b11111111);
posicion(3,15);
mandachar_LCD(0b11111111);
posicion(3,16);
mandachar_LCD(0b11111111);
posicion(3,17);
mandachar_LCD(0b11111111);
posicion(3,18);
mandachar_LCD(' ');
posicion(3,19);
mandachar_LCD(' ');
}else{
if ((indice_nota>21)&&(indice_nota<=24)){
posicion(3,12);
mandachar_LCD(0b11111111);
posicion(3,13);
mandachar_LCD(0b11111111);
posicion(3,14);
mandachar_LCD(0b11111111);
posicion(3,15);
mandachar_LCD(0b11111111);
posicion(3,16);
mandachar_LCD(0b11111111);
posicion(3,17);
mandachar_LCD(0b11111111);
posicion(3,18);
mandachar_LCD(0b11111111);
posicion(3,19);
mandachar_LCD(' '); }
else{
posicion(3,12);
mandachar_LCD(0b11111111);
posicion(3,13);
mandachar_LCD(0b11111111);
posicion(3,14);
mandachar_LCD(0b11111111);
posicion(3,15);
mandachar_LCD(0b11111111);
posicion(3,16);
Anexos
92
mandachar_LCD(0b11111111);
posicion(3,17);
mandachar_LCD(0b11111111);
posicion(3,18);
mandachar_LCD(0b11111111);
posicion(3,19);
mandachar_LCD(0b11111111);
}
}
}
}
}
}
}
}
void escribeinstrumento (int inst) {
if(inst==0){
posicion(4,12);
mandachar_LCD('P');
posicion(4,13);
mandachar_LCD('I');
posicion(4,14);
mandachar_LCD('A');
posicion(4,15);
mandachar_LCD('N');
posicion(4,16);
mandachar_LCD('O');
posicion(4,17);
mandachar_LCD(' ');
}else{
if(inst==40){
posicion(4,12);
mandachar_LCD('V');
posicion(4,13);
mandachar_LCD('I');
posicion(4,14);
mandachar_LCD('O');
posicion(4,15);
mandachar_LCD('L');
posicion(4,16);
mandachar_LCD('I');
Anexos
93
posicion(4,17);
mandachar_LCD('N');
}else{
if(inst==73){
posicion(4,12);
mandachar_LCD('F');
posicion(4,13);
mandachar_LCD('L');
posicion(4,14);
mandachar_LCD('A');
posicion(4,15);
mandachar_LCD('U');
posicion(4,16);
mandachar_LCD('T');
posicion(4,17);
mandachar_LCD('A');
}
}
}
}
void N_OFF(char a) {
mandachar(0x80);
mandachar(a);
mandachar(100);
}
void N_ON(char a) {
mandachar(0x90);
mandachar(a);
mandachar(100);
}
void setpiano(void) {
instrumento=0;
mandachar(0xc0);
mandachar(instrumento);
}
Anexos
94
void setviolin(void) {
instrumento=40;
mandachar(0xc0);
mandachar(instrumento);
}
void setflute(void) {
instrumento=73;
mandachar(0xc0);
mandachar(instrumento);
}
- MCUinit.c
/*
** ###################################################################
** This code is generated by the Device Initialization Tool.
** It is overwritten during code generation.
** USER MODIFICATION ARE PRESERVED ONLY INSIDE INTERRUPT SERVICE ROUTINES
** OR EXPLICITLY MARKED SECTIONS
**
** Project : midi1
** Processor : MCF51QE128CLH
** Version : Component 01.008, Driver 01.07, CPU db: 3.00.071
** Datasheet : MCF51QE128RM, Rev. 3, 9/2007
** Date/Time : 03/04/2013, 12:59
** Abstract :
** This module contains device initialization code
** for selected on-chip peripherals.
** Contents :
** Function "MCU_init" initializes selected peripherals
**
** Copyright : 1997 - 2009 Freescale Semiconductor, Inc. All Rights Reserved.
**
** http : www.freescale.com
Anexos
95
** mail : [email protected]
** ###################################################################
*/
/* MODULE MCUinit */
#include <MCF51QE128.h> /* I/O map for MCF51QE128CLH */
#include "MCUinit.h"
/* pragma to disable "possibly unassigned ISR handler" message generated by
compiler on definition of ISR without vector number */
#pragma warn_absolute off
/* User declarations and definitions */
#define mi1 40
#define fa1 41
#define sol1 43
#define la1 45
#define si1 47
#define do2 48
#define re2 50
#define mi2 52
#define fa2 53
#define sol2 55
#define la2 57
#define si2 59
#define do3 60
#define re3 62
#define mi3 64
#define fa3 65
#define sol3 67
#define la3 69
#define si3 71
#define do4 72
#define re4 74
#define mi4 76
#define fa4 77
#define sol4 79
#define la4 81
#define si4 83
#define do5 84
Anexos
96
#define re5 86
#define mi5 88
#define fa5 89
#define sol5 91
#define la5 93
#define NOTE_OFF 0x80
#define NOTE_ON 0x90
extern int vector_notas[];
int dif_vol=0;
extern char cadena[3];
extern short VOL;
extern short puntero;
extern short estado_nota, estado_volumen, estado_mute, estado_instrumento,
estado_modulacion;
extern int volumen, vol_nue, volumen_old, modulacion, mute;
extern int nota_old, nota, nota_nueva, indice_nota;
void manda_midi(char *cadena);
/* Code, declarations and definitions here will be preserved during code
generation */
/* End of user declarations and definitions */
/*
** ===================================================================
** Method : __initialize_hardware (component MCF51QE128_64)
**
** Description :
** Initialization code for CPU core and a clock source.
** ===================================================================
*/
void __initialize_hardware(void)
{
/* ### MCF51QE128_64 "Cpu" init code ... */
/* PE initialization code after reset */
/* Common initialization of the write once registers */
/* SOPT1: COPE=0,COPT=1,STOPE=0,WAITE=1,RSTOPE=0,BKGDPE=1,RSTPE=0 */
SOPT1 = 82;
/* SPMSC1: LVDF=0,LVDACK=0,LVDIE=0,LVDRE=1,LVDSE=1,LVDE=1,BGBE=0 */
SPMSC1 = 28;
Anexos
97
/* SPMSC2: LPR=0,LPRS=0,LPWUI=0,PPDF=0,PPDACK=0,PPDE=1,PPDC=0 */
SPMSC2 = 2;
/* SPMSC3: LVDV=0,LVWV=0,LVWIE=0 */
SPMSC3 &= (unsigned char)~56;
/* Initialization of CPU registers */
asm {
/* VBR: ADDRESS=0 */
clr.l d0
movec d0,VBR
/* CPUCR: ARD=0,IRD=0,IAE=0,IME=0,BWD=0,FSD=0 */
clr.l d0
movec d0,CPUCR
}
/* System clock initialization */
if (*(unsigned char*far)1023 != 255) { /* Test if the device trim value
is stored on the ¬ specified address */
ICSTRM = *(unsigned char*far)1023; /* Initialize ICSTRM register
from a non volatile memory * /
ICSSC = (unsigned char)((*(unsigned char*far)1022) & (unsigned
char)1); /* Initialize ICSSC ¬ register from a non volatile memory */
}
/* ICSC1: CLKS=0,RDIV=0,IREFS=1,IRCLKEN=1,IREFSTEN=0 */
ICSC1 = 6; /* Initialization of the ICS control register 1 */
/* ICSC2: BDIV=0,RANGE=0,HGO=0,LP=0,EREFS=0,ERCLKEN=0,EREFSTEN=0 */
ICSC2 = 0;
/* Initialization of the ICS control register 2 */
while(!ICSSC_IREFST) { /* Wait until the source of reference clock is
internal clock */
}
/* ICSSC: DRST_DRS=2,DMX32=0 */
ICSSC = (unsigned char)((ICSSC & (unsigned char)~96) | (unsigned
char)128); /* Initialization of the ICS status and control */
while((ICSSC & 192) != 128) { /* Wait until the FLL switches to High
range DCO mode */
}
/* INTC_WCR: ENB=0,MASK=0 */
INTC_WCR = 0;
}
/*
** ===================================================================
** Method : MCU_init (component MCF51QE128_64)
**
Anexos
98
** Description :
** Device initialization code for selected peripherals.
** ===================================================================
*/
void MCU_init(void)
{
/* SCGC1: TPM3=1,TPM2=1,TPM1=1,ADC=1,IIC2=1,IIC1=1,SCI2=1,SCI1=1 */
SCGC1 = 255;
/* SCGC2: FLS=1,IRQ=1,KBI=0,ACMP=1,RTC=1,SPI2=1,SPI1=1 */
SCGC2 = 239;
/* Common initialization of the CPU registers */
/* PTASE: PTASE7=0,PTASE6=0,PTASE4=0,PTASE3=0,PTASE2=0,PTASE1=0,PTASE0=0
*/
PTASE &= (unsigned char)~223;
/* PTBSE:
PTBSE7=0,PTBSE6=0,PTBSE5=0,PTBSE4=0,PTBSE3=0,PTBSE2=0,PTBSE1=0,PTBSE0=0 */
PTBSE = 0;
/* PTCSE:
PTCSE7=0,PTCSE6=0,PTCSE5=0,PTCSE4=0,PTCSE3=0,PTCSE2=0,PTCSE1=0,PTCSE0=0 */
PTCSE = 0;
/* PTDSE:
PTDSE7=0,PTDSE6=0,PTDSE5=0,PTDSE4=0,PTDSE3=0,PTDSE2=0,PTDSE1=0,PTDSE0=0 */
PTDSE = 0;
/* PTESE:
PTESE7=0,PTESE6=0,PTESE5=0,PTESE4=0,PTESE3=0,PTESE2=0,PTESE1=0,PTESE0=0 */
PTESE = 0;
/* PTFSE:
PTFSE7=0,PTFSE6=0,PTFSE5=0,PTFSE4=0,PTFSE3=0,PTFSE2=0,PTFSE1=0,PTFSE0=0 */
PTFSE = 0;
/* PTGSE: PTGSE3=0,PTGSE2=0,PTGSE1=0,PTGSE0=0 */
PTGSE &= (unsigned char)~15;
/* PTHSE: PTHSE7=0,PTHSE6=0,PTHSE1=0,PTHSE0=0 */
PTHSE &= (unsigned char)~195;
/* PTADS:
PTADS7=0,PTADS6=0,PTADS5=0,PTADS4=0,PTADS3=0,PTADS2=0,PTADS1=0,PTADS0=0
*/
PTADS = 0;
/* PTBDS:
PTBDS7=0,PTBDS6=0,PTBDS5=0,PTBDS4=0,PTBDS3=0,PTBDS2=0,PTBDS1=0,PTBDS0=0
*/
PTBDS = 0;
/* PTCDS:
PTCDS7=0,PTCDS6=0,PTCDS5=0,PTCDS4=0,PTCDS3=0,PTCDS2=0,PTCDS1=0,PTCDS0=0
Anexos
99
*/
PTCDS = 0;
/* PTDDS:
PTDDS7=0,PTDDS6=0,PTDDS5=0,PTDDS4=0,PTDDS3=0,PTDDS2=0,PTDDS1=0,PTDDS0=0
*/
PTDDS = 0;
/* PTEDS:
PTEDS7=0,PTEDS6=0,PTEDS5=0,PTEDS4=0,PTEDS3=0,PTEDS2=0,PTEDS1=0,PTEDS0=0
*/
PTEDS = 0;
/* PTFDS:
PTFDS7=0,PTFDS6=0,PTFDS5=0,PTFDS4=0,PTFDS3=0,PTFDS2=0,PTFDS1=0,PTFDS0=0
*/
PTFDS = 0;
/* PTGDS:
PTGDS7=0,PTGDS6=0,PTGDS5=0,PTGDS4=0,PTGDS3=0,PTGDS2=0,PTGDS1=0,PTGDS0=0
*/
PTGDS = 0;
/* PTHDS:
PTHDS7=0,PTHDS6=0,PTHDS5=0,PTHDS4=0,PTHDS3=0,PTHDS2=0,PTHDS1=0,PTHDS0=0
*/
PTHDS = 0;
/* ### Init_SCI init code */
/* SCI1C2: TIE=0,TCIE=0,RIE=0,ILIE=0,TE=0,RE=0,RWU=0,SBK=0 */
SCI1C2 = 0; /* Disable the SCI1 module */
(void)(SCI1S1 == 0); /* Dummy read of the SCI1S1 register to clear flags
*/
(void)(SCI1D == 0); /* Dummy read of the SCI1D register to clear flags
*/
/* SCI1S2: LBKDIF=1,RXEDGIF=1,RXINV=0,RWUID=0,BRK13=0,LBKDE=0,RAF=0 */
SCI1S2 = 192;
/* SCI1BDH: LBKDIE=0,RXEDGIE=0,SBR12=0,SBR11=0,SBR10=0,SBR9=0,SBR8=0 */
SCI1BDH = 0;
/* SCI1BDL: SBR7=0,SBR6=0,SBR5=1,SBR4=1,SBR3=0,SBR2=0,SBR1=1,SBR0=0 */
SCI1BDL = 50;
/* SCI1C1: LOOPS=0,SCISWAI=0,RSRC=0,M=0,WAKE=0,ILT=0,PE=0,PT=0 */
SCI1C1 = 0;
/* SCI1C3: R8=0,T8=0,TXDIR=1,TXINV=0,ORIE=0,NEIE=0,FEIE=0,PEIE=0 */
SCI1C3 = 32;
/* SCI1C2: TIE=0,TCIE=0,RIE=0,ILIE=0,TE=1,RE=0,RWU=0,SBK=0 */ SCI1C2 =
8; /*
### Init_RTC init code */
/* RTCMOD: RTCMOD=49 */
Anexos
100
RTCMOD = 49;
/* Set modulo register */
/* RTCSC: RTIF=1,RTCLKS=0,RTIE=1,RTCPS=11 */
RTCSC = 155;
/* Configure RTC */
/* ### Init_TPM init code */
/* TPM1SC: TOF=0,TOIE=0,CPWMS=0,CLKSB=0,CLKSA=0,PS2=0,PS1=0,PS0=0 */
TPM1SC = 0; /* Stop and reset counter */
TPM1MOD = 4U; /* Period value setting */
(void)(TPM1SC == 0); /* Overflow int. flag clearing (first part) */
/* TPM1SC: TOF=0,TOIE=0,CPWMS=0,CLKSB=1,CLKSA=0,PS2=0,PS1=1,PS0=0 */
TPM1SC = 18; /* Int. flag clearing (2nd part) and timer control register
setting */
/* ### Init_ADC init code */
/* APCTL2:
ADPC15=0,ADPC14=0,ADPC13=0,ADPC12=0,ADPC11=0,ADPC10=0,ADPC9=0,ADPC8=1 */
APCTL2 = 1;
/* APCTL1:
ADPC7=0,ADPC6=0,ADPC5=0,ADPC4=0,ADPC3=0,ADPC2=0,ADPC1=0,ADPC0=0 */
APCTL1 = 0;
/* APCTL3:
ADPC23=0,ADPC22=0,ADPC21=0,ADPC20=0,ADPC19=0,ADPC18=0,ADPC17=0,ADPC16=0
*/
APCTL3 = 0;
/* ADCCFG:
ADLPC=0,ADIV1=1,ADIV0=0,ADLSMP=0,MODE1=0,MODE0=1,ADICLK1=0,ADICLK0=0 */
ADCCFG = 68;
/* ADCCV:
ADCV11=0,ADCV10=0,ADCV9=0,ADCV8=0,ADCV7=0,ADCV6=0,ADCV5=0,ADCV4=0,ADCV3=
0,ADCV2=0, ADCV1=0,ADCV0=0 */
ADCCV = 0U;
/* ADCSC2: ADACT=0,ADTRG=0,ACFE=0,ACFGT=0 */
ADCSC2 = 0;
/* ADCSC1: COCO=0,AIEN=0,ADCO=0,ADCH4=1,ADCH3=1,ADCH2=1,ADCH1=1,ADCH0=1
*/
ADCSC1 = 31;
/* ### Init_SPI init code */
/* SPI2C1: SPIE=0,SPE=0,SPTIE=0,MSTR=0,CPOL=0,CPHA=0,SSOE=0,LSBFE=0 */
SPI2C1 = 0;
/* The SPRF interrupt flag is cleared when the SPI2 module is disabled.
*/
/* SPI2C2: MODFEN=1,BIDIROE=1,SPISWAI=0,SPC0=1 */
SPI2C2 = 25;
/* SPI2BR: SPPR2=1,SPPR1=1,SPPR0=1,SPR2=1,SPR1=1,SPR0=1 */
Anexos
101
SPI2BR = 119;
(void)(SPI2S == 0);
/* Dummy read of the SPI2S registr to clear the MODF flag ¬ */
/* SPI2C1: SPIE=0,SPE=1,SPTIE=0,MSTR=1,CPOL=0,CPHA=0,SSOE=1,LSBFE=0 */
SPI2C1 = 82;
/* ### Init_GPIO init code */
/* PTHDD: PTHDD1=1,PTHDD0=1 */
PTHDD |= (unsigned char)3;
/* ### */
asm { /* Set Interrupt level 0 */
move.w SR,D0;
andi.l #0xF8FF,D0;
move.w D0,SR;
}
} /*MCU_init*/
/*
** ===================================================================
** Interrupt handler : isr_default
**
** Description :
** User interrupt service routine.
** Parameters : None
** Returns : Nothing
** ===================================================================
*/
__interrupt void isr_default(void)
{
/* Write your interrupt code here ... */
}
/* end of isr_default */
/*
** ===================================================================
** Interrupt handler : isrVlvd
**
** Description :
** User interrupt service routine.
** Parameters : None
** Returns : Nothing
Anexos
102
** ===================================================================
*/
__interrupt void isrVlvd(void)
{
/* Write your interrupt code here ... */
}
/* end of isrVlvd */
/*
** ===================================================================
** Interrupt handler : isrVtpm1ovf
**
** Description :
** User interrupt service routine.
** Parameters : None
** Returns : Nothing
** ===================================================================
*/
__interrupt void isrVtpm1ovf(void)
{
/* Write your interrupt code here ... */
}
/* end of isrVtpm1ovf */
/*
** ===================================================================
** Interrupt handler : isrVspi2
**
** Description :
** User interrupt service routine.
** Parameters : None
** Returns : Nothing
** ===================================================================
*/
Anexos
103
__interrupt void isrVspi2(void)
{
/* Write your interrupt code here ... */
}
/* end of isrVspi2 */
/*
** ===================================================================
** Interrupt handler : isrVsci1err
**
** Description :
** User interrupt service routine.
** Parameters : None
** Returns : Nothing
** ===================================================================
*/
__interrupt void isrVsci1err(void)
{
/* Write your interrupt code here ... */
}
/* end of isrVsci1err */
/*
** ===================================================================
** Interrupt handler : isrVsci1rx
**
** Description :
** User interrupt service routine.
** Parameters : None
** Returns : Nothing
** ===================================================================
*/
__interrupt void isrVsci1rx(void)
{
/* Write your interrupt code here ... */
Anexos
104
}
/* end of isrVsci1rx */
/*
** ===================================================================
** Interrupt handler : isrVsci1tx
**
** Description :
** User interrupt service routine.
** Parameters : None
** Returns : Nothing
** ===================================================================
*/
__interrupt void isrVsci1tx(void)
{
/* Write your interrupt code here ... */
}
/* end of isrVsci1tx */
/*
** ===================================================================
** Interrupt handler : isrVadc
**
** Description :
** User interrupt service routine.
** Parameters : None
** Returns : Nothing
** ===================================================================
*/
__interrupt void isrVadc(void)
{
/* Write your interrupt code here ... */
}
/* end of isrVadc */
Anexos
105
/*
** ===================================================================
** Interrupt handler : isrVrtc
**
** Description :
** User interrupt service routine.
** Parameters : None
** Returns : Nothing
** ===================================================================
*/
__interrupt void isrVrtc(void)
{
/* Write your interrupt code here ... */
// Lectura acelerómetro eje x
if(estado_nota!=1){
RTCSC_RTIF=1;
ADCSC1=0x01; // Select ADC1 (PTA1) channel
while (!(ADCSC1_COCO)){} // Waits until ADC conversion is completed
indice_nota=ADCR/128; // Va desde 0 a 31
nota_nueva=vector_notas[indice_nota];
if(nota_nueva!=nota) {
estado_nota=1;
nota_old=nota;
nota=nota_nueva;
}
}
// Lectura acelerómetro eje y
RTCSC_RTIF=1;
ADCSC1=0x08; // Select ADC8 (PTA6) channel
while (!(ADCSC1_COCO)){} // Waits until ADC conversion is completed
Anexos
106
if(modulacion!=(20+ADCR/256)){
modulacion=20 + ADCR/256;
estado_modulacion=1;
}
// Lectura potenciómetro
RTCSC_RTIF=1;
ADCSC1=0x13; // Select ADC19 (PTG3) channel
while(!ADCSC1_COCO);
vol_nue=ADCR*4; // Multiplico por 4 porque luego hay que mandar 14 bit en el
bucle principal, y el ADCR da 12 bit
if(mute==0){
if(vol_nue>volumen){
dif_vol=vol_nue-volumen;
}else
dif_vol=volumen-vol_nue;
if((dif_vol>10)&&(mute==0)) {
estado_volumen=1;
}
volumen=vol_nue;
}
} /* end of isrVrtc */
/* Initialization of the CPU registers in FLASH */
/* NVPROT: FPS6=1,FPS5=1,FPS4=1,FPS3=1,FPS2=1,FPS1=1,FPS0=1,FPOPEN=1 */
unsigned char NVPROT_INIT @0x0000040D = 255;
/* NVOPT: KEYEN1=0,KEYEN0=1,SEC1=1,SEC0=1 */
unsigned char NVOPT_INIT @0x0000040F = 127;
#ifdef __cplusplus
extern "C" {
#endif
Anexos
107
extern void _startup(void);
extern unsigned long far _SP_INIT[];
#ifdef __cplusplus
}
#endif
/* Interrupt vector table */
#ifndef UNASSIGNED_ISR
#define UNASSIGNED_ISR isr_default /* unassigned interrupt service
routine */
#endif
/*Address Lvl Pri */
void (*const vector_0)(void) @INITSP = (void(*const )(void))_SP_INIT;
/*0x00000000 - - */
void (*const vector_1)(void) @INITPC = _startup; /*0x00000004 - - */
void (*const vector_2)(void) @Vaccerr = UNASSIGNED_ISR; /*0x00000008 - - */
void (*const vector_3)(void) @Vadderr = UNASSIGNED_ISR; /*0x0000000C - - */
void (*const vector_4)(void) @Viinstr = UNASSIGNED_ISR; /*0x00000010 - - */
void (*const vector_5)(void) @VReserved5 = UNASSIGNED_ISR; /*0x00000014 - - */
void (*const vector_6)(void) @VReserved6 = UNASSIGNED_ISR; /*0x00000018 - - */
void (*const vector_7)(void) @VReserved7 = UNASSIGNED_ISR; /*0x0000001C - - */
void (*const vector_8)(void) @Vprviol = UNASSIGNED_ISR; /*0x00000020 - - */
void (*const vector_9)(void) @Vtrace = UNASSIGNED_ISR; /*0x00000024 - - */
void (*const vector_10)(void) @Vunilaop = UNASSIGNED_ISR; /*0x00000028 - - */
void (*const vector_11)(void) @Vunilfop = UNASSIGNED_ISR; /*0x0000002C - - */
void (*const vector_12)(void) @Vdbgi = UNASSIGNED_ISR; /*0x00000030 - - */
void (*const vector_13)(void) @VReserved13 = UNASSIGNED_ISR; /*0x00000034 - -
*/
void (*const vector_14)(void) @Vferror = UNASSIGNED_ISR; /*0x00000038 - - */
void (*const vector_15)(void) @VReserved15 = UNASSIGNED_ISR; /*0x0000003C - -
*/
void (*const vector_16)(void) @VReserved16 = UNASSIGNED_ISR; /*0x00000040 - -
*/
void (*const vector_17)(void) @VReserved17 = UNASSIGNED_ISR; /*0x00000044 - -
*/
void (*const vector_18)(void) @VReserved18 = UNASSIGNED_ISR; /*0x00000048 - -
*/
void (*const vector_19)(void) @VReserved19 = UNASSIGNED_ISR; /*0x0000004C - -
*/
void (*const vector_20)(void) @VReserved20 = UNASSIGNED_ISR; /*0x00000050 - -
*/
Anexos
108
void (*const vector_21)(void) @VReserved21 = UNASSIGNED_ISR; /*0x00000054 - -
*/
void (*const vector_22)(void) @VReserved22 = UNASSIGNED_ISR; /*0x00000058 - -
*/
void (*const vector_23)(void) @VReserved23 = UNASSIGNED_ISR; /*0x0000005C - -
*/
void (*const vector_24)(void) @Vspuri = UNASSIGNED_ISR; /*0x00000060 - - */
void (*const vector_25)(void) @VReserved25 = UNASSIGNED_ISR; /*0x00000064 - -
*/
void (*const vector_26)(void) @VReserved26 = UNASSIGNED_ISR; /*0x00000068 - -
*/
void (*const vector_27)(void) @VReserved27 = UNASSIGNED_ISR; /*0x0000006C - -
*/
void (*const vector_28)(void) @VReserved28 = UNASSIGNED_ISR; /*0x00000070 - -
*/
void (*const vector_29)(void) @VReserved29 = UNASSIGNED_ISR; /*0x00000074 - -
*/
void (*const vector_30)(void) @VReserved30 = UNASSIGNED_ISR; /*0x00000078 - -
*/
void (*const vector_31)(void) @VReserved31 = UNASSIGNED_ISR; /*0x0000007C - -
*/
void (*const vector_32)(void) @Vtrap0 = UNASSIGNED_ISR; /*0x00000080 - - */
void (*const vector_33)(void) @Vtrap1 = UNASSIGNED_ISR; /*0x00000084 - - */
void (*const vector_34)(void) @Vtrap2 = UNASSIGNED_ISR; /*0x00000088 - - */
void (*const vector_35)(void) @Vtrap3 = UNASSIGNED_ISR; /*0x0000008C - - */
void (*const vector_36)(void) @Vtrap4 = UNASSIGNED_ISR; /*0x00000090 - - */
void (*const vector_37)(void) @Vtrap5 = UNASSIGNED_ISR; /*0x00000094 - - */
void (*const vector_38)(void) @Vtrap6 = UNASSIGNED_ISR; /*0x00000098 - - */
void (*const vector_39)(void) @Vtrap7 = UNASSIGNED_ISR; /*0x0000009C - - */
void (*const vector_40)(void) @Vtrap8 = UNASSIGNED_ISR; /*0x000000A0 - - */
void (*const vector_41)(void) @Vtrap9 = UNASSIGNED_ISR; /*0x000000A4 - - */
void (*const vector_42)(void) @Vtrap10 = UNASSIGNED_ISR; /*0x000000A8 - - */
void (*const vector_43)(void) @Vtrap11 = UNASSIGNED_ISR; /*0x000000AC - - */
void (*const vector_44)(void) @Vtrap12 = UNASSIGNED_ISR; /*0x000000B0 - - */
void (*const vector_45)(void) @Vtrap13 = UNASSIGNED_ISR; /*0x000000B4 - - */
void (*const vector_46)(void) @Vtrap14 = UNASSIGNED_ISR; /*0x000000B8 - - */
void (*const vector_47)(void) @Vtrap15 = UNASSIGNED_ISR; /*0x000000BC - - */
void (*const vector_48)(void) @VReserved48 = UNASSIGNED_ISR; /*0x000000C0 - -
*/
void (*const vector_49)(void) @VReserved49 = UNASSIGNED_ISR; /*0x000000C4 - -
*/
void (*const vector_50)(void) @VReserved50 = UNASSIGNED_ISR; /*0x000000C8 - -
*/
void (*const vector_51)(void) @VReserved51 = UNASSIGNED_ISR; /*0x000000CC - -
*/
Anexos
109
void (*const vector_52)(void) @VReserved52 = UNASSIGNED_ISR; /*0x000000D0 - -
*/
void (*const vector_53)(void) @VReserved53 = UNASSIGNED_ISR; /*0x000000D4 - -
*/
void (*const vector_54)(void) @VReserved54 = UNASSIGNED_ISR; /*0x000000D8 - -
*/
void (*const vector_55)(void) @VReserved55 = UNASSIGNED_ISR; /*0x000000DC - -
*/
void (*const vector_56)(void) @VReserved56 = UNASSIGNED_ISR; /*0x000000E0 - -
*/
void (*const vector_57)(void) @VReserved57 = UNASSIGNED_ISR; /*0x000000E4 - -
*/
void (*const vector_58)(void) @VReserved58 = UNASSIGNED_ISR; /*0x000000E8 - -
*/
void (*const vector_59)(void) @VReserved59 = UNASSIGNED_ISR; /*0x000000EC - -
*/
void (*const vector_60)(void) @VReserved60 = UNASSIGNED_ISR; /*0x000000F0 - -
*/
void (*const vector_61)(void) @Vunsinstr = UNASSIGNED_ISR; /*0x000000F4 - - */
void (*const vector_62)(void) @VReserved62 = UNASSIGNED_ISR; /*0x000000F8 - -
*/
void (*const vector_63)(void) @VReserved63 = UNASSIGNED_ISR; /*0x000000FC - -
*/
void (*const vector_64)(void) @Virq = UNASSIGNED_ISR; /*0x00000100 - - */
void (*const vector_65)(void) @Vlvd = isrVlvd; /*0x00000104 7 3 */
void (*const vector_66)(void) @Vtpm1ch0 = UNASSIGNED_ISR; /*0x00000108 - - */
void (*const vector_67)(void) @Vtpm1ch1 = UNASSIGNED_ISR; /*0x0000010C - - */
void (*const vector_68)(void) @Vtpm1ch2 = UNASSIGNED_ISR; /*0x00000110 - - */
void (*const vector_69)(void) @Vtpm1ovf = isrVtpm1ovf; /*0x00000114 6 1 */
void (*const vector_70)(void) @Vtpm2ch0 = UNASSIGNED_ISR; /*0x00000118 - - */
void (*const vector_71)(void) @Vtpm2ch1 = UNASSIGNED_ISR; /*0x0000011C - - */
void (*const vector_72)(void) @Vtpm2ch2 = UNASSIGNED_ISR; /*0x00000120 - - */
void (*const vector_73)(void) @Vtpm2ovf = UNASSIGNED_ISR; /*0x00000124 - - */
void (*const vector_74)(void) @Vspi2 = isrVspi2; /*0x00000128 4 7 */
void (*const vector_75)(void) @Vspi1 = UNASSIGNED_ISR; /*0x0000012C - - */
void (*const vector_76)(void) @Vsci1err = isrVsci1err; /*0x00000130 4 5 */
void (*const vector_77)(void) @Vsci1rx = isrVsci1rx; /*0x00000134 4 4 */
void (*const vector_78)(void) @Vsci1tx = isrVsci1tx; /*0x00000138 4 3 */
void (*const vector_79)(void) @Viicx = UNASSIGNED_ISR; /*0x0000013C - - */
void (*const vector_80)(void) @Vkeyboard = UNASSIGNED_ISR; /*0x00000140 - - */
void (*const vector_81)(void) @Vadc = isrVadc; /*0x00000144 3 5 */
void (*const vector_82)(void) @Vacmpx = UNASSIGNED_ISR; /*0x00000148 - - */
void (*const vector_83)(void) @Vsci2err = UNASSIGNED_ISR; /*0x0000014C - - */
void (*const vector_84)(void) @Vsci2rx = UNASSIGNED_ISR; /*0x00000150 - - */
void (*const vector_85)(void) @Vsci2tx = UNASSIGNED_ISR; /*0x00000154 - - */
Anexos
110
void (*const vector_86)(void) @Vrtc = isrVrtc; /*0x00000158 2 2 */
void (*const vector_87)(void) @Vtpm3ch0 = UNASSIGNED_ISR; /*0x0000015C - - */
void (*const vector_88)(void) @Vtpm3ch1 = UNASSIGNED_ISR; /*0x00000160 - - */
void (*const vector_89)(void) @Vtpm3ch2 = UNASSIGNED_ISR; /*0x00000164 - - */
void (*const vector_90)(void) @Vtpm3ch3 = UNASSIGNED_ISR; /*0x00000168 - - */
void (*const vector_91)(void) @Vtpm3ch4 = UNASSIGNED_ISR; /*0x0000016C - - */
void (*const vector_92)(void) @Vtpm3ch5 = UNASSIGNED_ISR; /*0x00000170 - - */
void (*const vector_93)(void) @Vtpm3ovf = UNASSIGNED_ISR; /*0x00000174 - - */
void (*const vector_94)(void) @VReserved94 = UNASSIGNED_ISR; /*0x00000178 - -
*/
void (*const vector_95)(void) @VReserved95 = UNASSIGNED_ISR; /*0x0000017C - -
*/
void (*const vector_96)(void) @VL7swi = UNASSIGNED_ISR; /*0x00000180 - - */
void (*const vector_97)(void) @VL6swi = UNASSIGNED_ISR; /*0x00000184 - - */
void (*const vector_98)(void) @VL5swi = UNASSIGNED_ISR; /*0x00000188 - - */
void (*const vector_99)(void) @VL4swi = UNASSIGNED_ISR; /*0x0000018C - - */
void (*const vector_100)(void) @VL3swi = UNASSIGNED_ISR; /*0x00000190 - - */
void (*const vector_101)(void) @VL2swi = UNASSIGNED_ISR; /*0x00000194 - - */
void (*const vector_102)(void) @VL1swi = UNASSIGNED_ISR; /*0x00000198 - - */
/*
** ===================================================================
** Interrupt handler : isrVkeyboard
**
** Description :
** User interrupt service routine.
** Parameters : None
** Returns : Nothing
** ===================================================================
*/
__interrupt void isrVkeyboard(void)
{
/* Write your interrupt code here ... */
/* KBI1SC_KBIE = 0; // Disable KBI1 interrupts
KBI2SC_KBIE = 0; // Disable KBI2 interrupts
KBI1SC_KBACK = 1; // Clear KBACK
KBI2SC_KBACK = 1; // Clear KBACK
*/
/*
Anexos
111
KBI1SC_KBACK=1 ;
KBI2SC_KBACK=1 ;
KBI1SC_KBIE = 1; // enable KBI1 interrupts
KBI2SC_KBIE = 1; // enable KBI2 interrupts
*/
}
/* end of isrVkeyboard */
/* END MCUinit */
/*
** ###################################################################
Anexos
112
9.2 Esquemas
5
5
4
4
3
3
2
2
1
1
D D
C C
B B
A A
VDDVO
VSS
W/RS
EDB0DB1DB2DB3DB4DB5DB6DB7
+5VCC
+5VCC
+5VCC
+5VCC
+3VCC
+3VCC
Title
Size Document Number Rev
Date: Sheet of
MIDI 00
MIDI
A3
2 2Friday, May 31, 2013
Title
Size Document Number Rev
Date: Sheet of
MIDI 00
MIDI
A3
2 2Friday, May 31, 2013
Title
Size Document Number Rev
Date: Sheet of
MIDI 00
MIDI
A3
2 2Friday, May 31, 2013
GN
D8
SDO9
CLR 10G 13
SDI 14
VC
C16
SRCLK 11RCLK 12QA15QB1QC2QD3QE4QF5QG6QH7
U2
NPX _74HC595
U2
NPX _74HC595
12
U1A
NPX_74HC14
U1A
NPX_74HC14
135791113151719212325272931333537394143454749515355
2468
101214161820222426283032343638404244464850525456
J4POSTE 2.54 X2.54J4POSTE 2.54 X2.54
98
U1D
NPX_74HC14
U1D
NPX_74HC14C5100nFCONVENCIONAL
C5100nFCONVENCIONAL
12
J63.96_2J63.96_2
D21N4004
CONVENCIONAL
D21N4004
CONVENCIONAL
56
U1C
NPX_74HC14
U1C
NPX_74HC14
SW1ELECTRO DH_11.522/4SW1ELECTRO DH_11.522/4
C4100nF
CONVENCIONAL
C4100nF
CONVENCIONAL
C1100nFCONVENCIONAL
C1100nFCONVENCIONAL
CONTRASTE12K2PT10 HORIZ. MONT.
CONTRASTE12K2PT10 HORIZ. MONT. R1
1K1/4W
R11K1/4W
C6100nFCONVENCIONAL
C6100nFCONVENCIONAL
1234
J52.54 X 2.54J52.54 X 2.54
SW2ELECTRO DH_11.522/4SW2ELECTRO DH_11.522/4
12345678910111213141516
Pantalla LCDPantalla LCD
R21K1/4W
R21K1/4W
VOLUMEN2K2
PT15 VERT MONT
VOLUMEN2K2
PT15 VERT MONT
34
U1B
NPX_74HC14
U1B
NPX_74HC14
C310nFCONVENCIONAL
C310nFCONVENCIONAL
DEMOQE
MIDI OUT
MUTECAMBIO
INST
74HC14 74HC595
Pantalla LCD
VOLUME
1 3 5 7 43 41 55 50 52 25 29 31
6 4 7 8 9 10 11 12 13 14
2 4 1 8 5 6 15 1 2 3 4 5 6 7
14 11 129 3
DC
10 nF
100 nF100 nF
DC
15 16
DC16
8
Enchufe de alimentación
Esquema de cableadoProyecto MIDI
Eduardo González Blanco
Tarjeta de sonidoM-Audio
Ordenador
Sintetizador, monitorización
Instrumento musical
Enchufe de alimentación
Cable MIDI
Montaje final con elementos externosProyecto MIDI
Eduardo González Blanco
Conexión de los elementos
1 7 8 14
8 7 6 5 4 3 2 1
9 10 11 12 13 14 15 16
74HC5957 6 5 4 3 2 1
8 9 10 11 12 13 1474HC11 1
2
3
4
55 29 27 1
56 30 28 2
1 2
3 4
1 2
3 4
1 2 3
1
2
3
1 2
3
Placa de circuito impreso
Potenciómetro volúmen
Botones mute e instrumento
Pantalla LCD, Placa DEMOQE e integrado MIDI en capítulo 3.
U1 74HC595
U2 74HC14
U3, pin 1 Placa DEMOQE, pin 1
U3, pin 3 Placa DEMOQE, pin 3
U3, pin 5 Placa DEMOQE, pin 5
U3, pin 7 Placa DEMOQE, pin 7
U3, pin 25 Placa DEMOQE, pin 25
U3, pin 29 Placa DEMOQE, pin 29
U3, pin 31 Placa DEMOQE, pin 31
U3, pin 41 Placa DEMOQE, pin 41
U3, pin 43 Placa DEMOQE, pin 43
U3, pin 50 Placa DEMOQE, pin 50
U3, pin 52 Placa DEMOQE, pin 52
U3, pin 55 Placa DEMOQE, pin 55
U4 Integrado MIDI, pines coincidentes
U5 Pantalla LCD, pines coincidentes
U6 Potenciómetro interno, integrado
U7 Botón mute, pines coincidentes
U8 Botón instrumento, pines coincidentes
U9, pin 1 Potenciómetro volumen, pin 1 (cable blanco)
U9, pin 2 Potenciómetro volumen, pin 2 (cable negro)
U9, pin 3 Potenciómetro volumen, pin 3 (cable marrón)
JP1, pin 1 Fuente de alimentación, polo negativo
JP1, pin 2 Fuente de alimentación, polo positivo