The magic “CH341A USB to I2C/IIC/SPI/UART/TTL/ISP/GPIO adapter, EPP/MEM parallel port converter!”

4 minute read

A long time ago I saw this in hackaday, after investigation over it on internet, I decided to get one from aliexpress ($9).

image

Front

image

Back

This dongle should provide:

  • SPI/ISP [Front (4)]
  • I²C [Front (6)]
  • UART-TTL [Front (3, 7, 8)]
  • GPIO [Front (3, 4), Back (1)]

The main CI is the CH341A.

image

CH341DS1 Datasheet (I don't know how similar the CIs are)

In [Back (2)] we have a 3.3V regulator.

image

AMS1117 Datasheet

The switch in [Front (1)] will change the USB PID value.

  • For I²C and SPI: idVendor=1a86, idProduct=5512, bcdDevice= 3.04
  • For UART: idVendor=1a86, idProduct=5523, bcdDevice= 3.04 Making the USB driver to select the correct kernel module to deal with it.

It’s also possible to change the output voltage with the voltage selection switches [Front (2, 5)].

I’m pretty happy with the hardware, the selection keys makes everything easy to configure and dealing between all the modes sounds pretty possible. It would be better to have all modes at the same time, but that is not possible and does not sound as a terrible thing right now for me. Besides that, the 3.3V regulator can provide up to 1A, and that sounds pretty good also.

The serial interface mode works without any problem as a normal ch341a serial interface (some Arduinos does use it).

The big question is the other modes, like I²C, GPIO and SPI. But the great and beautiful community has already the modules for all functionalities.

How to compile, load and remove a module

First things first:

  • To load something that you compiled
    • Compile with make
    • Load with sudo insmod module_name.ko
    • Unload with sudo rmmod module_name
  • To load a kernel module
    • Load with sudo modprobe module
    • Unload with sudo rmmod module

That’s what you need to know, for anything else you can use Google.

GPIO and I²C

All GPIOs are provided with sysfs, I would personally prefer something like libiio or providing /dev/* devices (Like in: I²C or SPI).

(The GPIO in both SPI and I²C are D* Pins in [Back (1)] and CS* in [Front (4)]).

Ok, to check the I²C, you need to make sure that your i2c-dev module is loaded, you can search it in /lib/modules with find . | grep i2c-dev and load it with sudo modprobe i2c-dev, this will allow the modules to show the I²C devices under /dev.

The gschorcht/i2c-ch341-usb driver will returns in dmesg:

[314374.047570] usb 1-1.1.1: new full-speed USB device number 109 using xhci_hcd
[314374.138693] usb 1-1.1.1: New USB device found, idVendor=1a86, idProduct=5512, bcdDevice= 3.04
[314374.138702] usb 1-1.1.1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[314374.148039] i2c-ch341-usb 1-1.1.1:1.0: ch341_cfg_probe: output gpio0 gpio=0 irq=0
[314374.148049] i2c-ch341-usb 1-1.1.1:1.0: ch341_cfg_probe: output gpio1 gpio=1 irq=1
[314374.148055] i2c-ch341-usb 1-1.1.1:1.0: ch341_cfg_probe: output gpio2 gpio=2 irq=2
[314374.148061] i2c-ch341-usb 1-1.1.1:1.0: ch341_cfg_probe: output gpio3 gpio=3 irq=3
[314374.148068] i2c-ch341-usb 1-1.1.1:1.0: ch341_cfg_probe: input  gpio4 gpio=4 irq=4 (hwirq)
[314374.148074] i2c-ch341-usb 1-1.1.1:1.0: ch341_cfg_probe: input  gpio5 gpio=5 irq=5
[314374.148080] i2c-ch341-usb 1-1.1.1:1.0: ch341_cfg_probe: input  gpio6 gpio=6 irq=6
[314374.148086] i2c-ch341-usb 1-1.1.1:1.0: ch341_cfg_probe: input  gpio7 gpio=7 irq=7
[314374.148349] i2c-ch341-usb 1-1.1.1:1.0: ch341_i2c_probe: created i2c device /dev/i2c-8
[314374.148354] i2c-ch341-usb 1-1.1.1:1.0: ch341_i2c_set_speed: Change i2c bus speed to 100 kbps
[314374.149365] i2c-ch341-usb 1-1.1.1:1.0: ch341_usb_probe: connected

Showing our 8 pins plus the i2c-8 device running at 100khz.

I was able to do a simple test with i2cdetect 8. (You can get it from i2c-tools).

image

I²C detect running in CH341A and analyzed with saleae.

You can download my i2cdetect test raw .logicdata or a csv.

I did a simple test with while true; do echo 1 > /sys/class/gpio/gpio0/value; echo 0 > /sys/class/gpio/gpio0/value; done, and the example gpio_output.c file, both were able to toggle the GPIO at average 10khz.

image

image

You can download my gpio test raw .logicdata or a csv.

SPI

For the spi device, you need also to load the device module called spidev, sudo modprove spidev. Now with the driver loaded, you should just compile and load the spi module.

[315818.960403] usb 1-1.1.1: USB disconnect, device number 117
[315819.771286] usbcore: registered new interface driver spi-ch341-usb
[315824.287292] usb 1-1.1.1: new full-speed USB device number 118 using xhci_hcd
[315824.381352] usb 1-1.1.1: New USB device found, idVendor=1a86, idProduct=5512, bcdDevice= 3.04
[315824.381358] usb 1-1.1.1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[315824.391008] spi-ch341-usb 1-1.1.1:1.0: ch341_cfg_probe: output cs0 SPI slave with cs=0
[315824.391013] spi-ch341-usb 1-1.1.1:1.0: ch341_cfg_probe: output cs1 SPI slave with cs=1
[315824.391016] spi-ch341-usb 1-1.1.1:1.0: ch341_cfg_probe: output cs2 SPI slave with cs=2
[315824.391020] spi-ch341-usb 1-1.1.1:1.0: ch341_cfg_probe: input  gpio4 gpio=0 irq=0 (hwirq)
[315824.391023] spi-ch341-usb 1-1.1.1:1.0: ch341_cfg_probe: input  gpio5 gpio=1 irq=1
[315824.391028] spi-ch341-usb 1-1.1.1:1.0: ch341_spi_probe: SPI master connected to SPI bus 0
[315824.391307] spi-ch341-usb 1-1.1.1:1.0: ch341_spi_probe: SPI device /dev/spidev0.0 created
[315824.391645] spi-ch341-usb 1-1.1.1:1.0: ch341_spi_probe: SPI device /dev/spidev0.1 created
[315824.391981] spi-ch341-usb 1-1.1.1:1.0: ch341_spi_probe: SPI device /dev/spidev0.2 created
[315824.392423] spi-ch341-usb 1-1.1.1:1.0: ch341_usb_probe: connected

The SPI was running with 1.5MHz, the tests was done with python-spidev.

import spidev
spi = spidev.SpiDev()
spi.open(0, 0)
to_send = []
for i in range(30):
	to_send += [i]
spi.xfer(to_send)

More than 30 bytes will give:

Traceback (most recent call last):
  File "test.py", line 7, in <module>
    spi.xfer(to_send)
TimeoutError: [Errno 110] Connection timed out

I’m not sure why.

image

image

You can download my spi test raw .logicdata or a csv.

Final

Yes, I give a positive vote in this device, everything appears to be working with the correct kernel modules. I don’t have time right now to test with real devices/sensors, but everything shows that will work, I’ll try to update this subject in the future.

References