- El Pensadero de Canek - https://aztlan.fciencias.unam.mx/~canek/pensadero -

CP2102 UART Bridge

(Esta entrada es la tercera parte de una serie que cubre un proyecto personal que realicé en el verano de 2014; pueden ver todas las partes aquí [1]).

La familia de adaptadores USB ↔ serial cp210x es bastante común para la gente que quiere comunicarse con hardware de forma serial. Hace unos años (tal vez habría que decir décadas) no era necesario utilizar este tipo de adaptadores: todas las computadoras tenían al menos un conector de este estilo incluido, llamado (imaginativamente) el puerto serial (serial port); en el mundo de DOS se le conocía como COM1 (y si había más eran COM2, etc.), y yo todavía llegué a conectar algún módem de esta manera a una computadora.

Como decía en la entrada anterior de esta serie [2], el estándar USB ha reemplazado a casi todos los conectores de la antigüedad; los conectores PS1, paralelo, y serial incluidos. Por lo tanto, si alguien quiere (como yo quería) comunicarse de forma serial usando una computadora moderna, uno necesita un adaptador USB ↔ serial.

Leyendo en Internet, rápidamente me decidí por un CP2102 UART Bridge, que encontré a precio de ganga en Amazon [3]; el que ligo cuesta casi 7 dólares, pero el que de hecho compré me salió en menos de 3, con envío incluido. Lamentablemente, no sé dónde conseguir este tipo de cosas en México, así que lo pedí por Amazon y lo envié a la dirección de Omar en Boston (Amazon generalmente no envía electrónicos fuera del gabacho), donde lo recogí cuando pasé a verlo a finales de mayo.

CP2102 [4]

CP2102

(Siendo 100% honesto, sí lo encontré en MercadoLibre [5]; pero el precio era más del doble).

Me decidí por el CP2102 básicamente porque es muy barato, y porque está muy bien soportado en Linux (niguna de esas razones me sorprende; no hace nada terriblemente interesante). En Gentoo, sencillamente tuve que habilitar el módulo del kernel cp210x (funciona para el CP2101 y el CP2103 también), con la opción USB_SERIAL_CP210X, y después sencillamente lo conecté a mi computadora. Inmediatamente el adaptador queda registrado con el dispositivo /dev/ttyUSB0, y uno puede comenzar a usarlo sin problemas.

Bueno, casi; el dispositivo por omisión tiene permisos de escritura únicamente para root, así que usando la siguiente regla de udev:

SUBSYSTEMS=="usb", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE:="0666"
KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE:="0666"

puedo darle permisos a todo mundo de forma automática, lo que me permite que mis aplicaciones corran para cualquier usuario.

Como sea; el CP2102 es bastante sencillo de usar (si es que acaso el hardware está bien conectado), uno únicamente abre el dispositivo, y puede empezar a escribir y leer información de él sin muchos problemas:

#include <termios.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#define TTY_BAUDRATE   B38400

int
main(int argc, char* argv[])
{
        struct termios options;
        int fd;

        if ((fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0) {
                return -1;
        } else {
                tcgetattr(fd, &options);
                cfsetispeed(&options, TTY_BAUDRATE);
                cfsetospeed(&options, TTY_BAUDRATE);
                cfmakeraw(&options);
                if (tcsetattr(fd, TCSANOW, &options) < 0) {
                        close(fd);
                        return -1;
                }
                tcflush(fd, TCIFLUSH);
        }

        uint8_t byte = 0xff;

        /* Envía byte. */
        int r = write(fd, &byte, 1);
        tcflush(fd, TCIFLUSH);

        /* Recibe byte. */
        fd_set readfds;

        struct timeval timeout = {
                .tv_sec = 1,
                .tv_usec = 0
        };

        FD_ZERO(&readfds);
        FD_SET(fd, &readfds);

        int status = select(fd+1, &readfds, NULL, NULL, &timeout);
        if (!status)
                return -1;
        
        if (FD_ISSET(fd, &readfds)) {
                r = read(fd, &byte, 1);
        } else if(status == EINTR) {
                return -1;
        }

        return (int)byte;
}

Obviamente se pueden transmitir secuencias de bytes más largas que 1, pero para lo que quería hacer 1 bastaba… o al menos no he necesitado más.

Por supuesto, el chiste de todo esto es, ¿a dónde van esos bytes que estoy enviando? El adaptador CP2120 únicamente me permite comunicarme de forma serial vía USB; es sólo una pieza más del rompecabezas que estuve armando para mi proyecto. Y, en retrospectiva, de hecho fue la pieza más sencilla; casi no tuve que hacer nada para que funcionara.

Del resto de las piezas escribiré más adelante.

2 Comments (Open | Close)

2 Comments To "CP2102 UART Bridge"

#1 Comment By Carlos Alegría On julio 26, 2014 @ 7:12 PM

¿tons cuál era el proyecto?

#2 Comment By Canek On julio 26, 2014 @ 8:14 PM

No pues todavía no lo digo; primero estoy describiendo cada una de las piezas del rompecabezas, antes de especificar cómo las junté todas.