Páginas

martes, 28 de enero de 2014

Del MCP23008 al MCP23017 (de 8 bits a 16 bits mediante el interfaz i2c)

En la entrada anterior expusimos el modo de utilizar el MCP23008 para ampliar las salidas digitales del Raspberry Pi, en 8 bits por circuito integrado. En esta nueva entrada expondremos el modo de utilizar el MCP23017 para extender aún más las entradas/salidas digitales, hasta un total de 16 bits, por MCP23017 utilizado.
No voy a partir de cero, por lo que recomiendo leerse con anterioridad la entrada de este mismo blog: Expandiendo las Entradas y Salidas Digitales de Raspberry Pi con el MCP23008.
En el montaje virtual que hemos realizado con el programa Fritzing, podemos observar dos bloques de 8 LEDs cada uno, los rojos están conectados al puerto A del circuito integrado MCP23017, y los verdes al puerto B del mismo chip. Como en la entrada del MCP23008, cada LED está serializado con una resistencia de 330 ohmios, Así evitamos un excesivo consumo de corriente, evitando que las salidas de la RaspPi no lleguen a dañarse, por un lado, y por el otro, que la propia RaspPi sea capaz de proporcionar el consumo necesario para encender a todos los LEDs simultáneamente.

Lista de materiales

EL material requerido para este montaje es el siguiente:

  • 1 MCP23017 (empaquetado en DIL28)
  • 16 resistencias de 330 ohmios
  • 8 LEDs rojos
  • 8 LEDs verdes
  • conector de expansión (desarrollado por mi) para conexión de la protoboard al RaspPi. Ver entrada anterior en este blog (Conectando la Raspberry Pi a una protoboard).

Evidentemente, para realizar las pruebas que queremos hacer, no se requieren que los LEDs sean del color indicado, ni que compremos tantos LEDs. Con poner algunos en ambos puertos, podremos comprobar que el montaje funciona.
En el montaje virtual he utilizado el mismo código de colores que en el montaje realizado para el MCP23008, por lo que no voy a extenderme en ello.

Características del MCP23017

Este chip, al igual que el MCP23008, tiene un espacio de direcciones que van desde 0x200x27, en función de los valores que vayan tomando los 3 bits de direccionamiento, A2, A1 y A0. En nuestro caso, estos tres bits están puestos a CERO.
Desde un punto de vista de programación, este chip dispone de 11 pares de registros, de 8 bits cada uno, con los que gestionamos su funcionalidad, leyendo/escribiendo en ellos a través del interfaz I2C. Uno de los registros (IOCONA/B) está compartido por ambos bancos. Esto significa que lo que hagamos en uno de ellos se reflejará en el otro. Este registro común nos permite configurar el modo de operar y de organizar los 22 registros.
Para este ejemplo, vamos a configurar los 11 pares de registros en dos bloques diferenciados, uno para el puerto A, direccionables por el interfaz i2c en el rango 0x00-0x0A, y el otro para el puerto B, en el rango 0x10-0x1A. La estructura de los registros una vez configurados convenientemente es la que mostrada en la siguiente imagen.
Pero esta disposición de registro no es la que tenemos nada más alimentarlo. Al darle tensión, todos los registros se inicializan a 0x00, excepto los IODIRA/B que lo hacen a 0xff, pasando a estar todos los bits de E/S en modo entrada. Tendremos que actuar, por tanto, sobre algunos bits del doble registro IOCONA/B para configurarlo tal como queremos:
  • IOCON.BANK = 1, registros agrupados por Banco A o B.
  • IOCON.SEQOP = 1, lectura/escritura de un byte (no secuencial).
  • IODIRA/B = 0x00, todos los bits de ambos puertos en modo salida.
Debemos tener en cuenta que, al arranque, la disposición de los registros es distinta (IOCON.BANK = 0) y el modo de operar es secuencial (IOCON.SEQOP = 0). Por tanto, al arranque, tendremos que considerar al doble registro IOCONA/B ubicado en la dirección como 0x0A/0x0B, direcciones que utilizaremos al dirigirnos a ellos por el protocolo i2c.
Los bits BANK y SEQOP corresponden a los bits B7 y B5 del registro IOCON. Por lo que para poner ambos bits a '1' escribiremos en el registro IOCON el valor 0xA0 (b10100000). Este registro se puede direccionar indistintamente tanto por el puerto A, en 0x0A, como por el puerto B, en 0x0B. Debemos tener muy en cuenta que, una vez configurado el circuito integrado del modo en el que lo hemos hecho, las direcciones de acceso al registro IOCON pasan a ser indistitamente 0x05 (IOCONA) o 0x15 (IOCONB).

El programa ejemplo mcp23017

Antes de proceder con el nuevo programa podemos hacer una prueba con los otros dos programas ejemplo que desarrollamos para el MCP23008, y comprobar que también se ejecutan. Eso sí, solo parpadeadarán los LEDs rojos, los del puerto A.
Si ejecutamos el programa mcp23017 con la opción de ayuda (-h, o también --help) se muestra la funcionalidad que se ha implementado. 
El programa permite gestionar el circuito integrado. Por ejemplo, la opción --show muestra la distribución de los registros internos, y sus valores:
Vemos claramente, con el bit IOCON.BANK activo, la distribución de los registros en dos bloques idénticos, equivalentes al bloque existente en el MCP23008, 11 pares de registros, un par direccionable entre 00h y 0Ah y el otro par entre 10h y 1Ah.  En cambio, si desactivamos el bit IOCON.BANK, el programa muestra otra distribución de registros:
En esta configuración los registros de cada bloque se van alternando, dentro de un rango de direcciones entre 00h y 15h. Podemos observar que tanto IOCONA (0Ah) como IOCONB (0Bh) contienen el mismo valor (0x28), distinto de lo que hemos grabado en él (0x29), porque el bit menos significativo, al leerlo, devuelve el valor '0'.
En la imagen anterior vemos el modo de alterar un registro que es indicando el registro (mediante la etiqueta correspondiente) al que queremos acceder y el valor a escribir.
La opción --mode nos muestra el valor del registro IOCON (A=B) o podemos alterarlo escribiendo en él un valor entre 0x00 y 0xFF (0 y 255).
FInalmente, podemos activar tres demos de activación de los LEDs con distintos patrones: random, counter y flash. En la demo random, en un bucle sin fin, escribimos dos valores aleatorios y distintos simultáneamente a ambos puertos (GPIOA y GPIOB), esperamos 'n' milisegundos, e iniciamos de nuevo el bucle. Si pulsamos <CTRL-C> abortamos el programa. La demo counter, los bits del puerto A muestran de forma binaria el valor de un contador que se incrementa cada 'n' milisegundos. El puerto B muestra de forma binaria a un contador decrementándose con la misma cadencia. Y por último, la demo flash va alternando cada 'n' milisegundos el encendido completo de cada puerto.
En Enlaces está la dirección del fichero mcp23017.rar, que una vez descomprimido se puede generar el ejecutable invocando desde un terminal de comandos make all.
Y eso es todo. En una próxima entrada hablaré de la gestión de las entradas y de las interrupciones.

Enlaces

- MCP23017/MCP23S17 datasheet
- I2C access examples
- Source Package: i2c-tools (3.1.0-2)
i2c - dev-interface
- Using I2C from userspace in Linux
- Raspberry pi and i2c gpios
- Expandiendo las Entradas y Salidas Digitales de Raspberry Pi con el MCP23008
- Fritzing
- MCP23017.fzz
- mcp23017.rar

No hay comentarios:

Publicar un comentario