Android Question CH341 USB to SPI/I2C/UART/GPIO/Parallel - CH341PAR.jar - Library

rtek1000

Active Member
Licensed User
Longtime User
Note: Library added in post #7.

Hello, I have found a possible alternative to the FT311D chip, which may be able to operate with the SPI port to be a alternative to the USB Serial converter (CH341 seems to be cheaper).

The CH341 is a USB bus adapter that provides asynchronous UART, parallel port, and common 2-wire and 4-wire synchronous serial interfaces via the USB bus. In the parallel port mode, an EPP/MEM 8-bit parallel interface is provided, and the commonly used synchronous serial interface mainly includes a 2-wire IIC, a 4-wire SPI, and the like.
This document mainly introduces the Java Driver Library of CH341USB to EPP, MEM, IIC, SPI mode (hereinafter referred to as CH341PAR), and how to use the APK to operate CH341PAR for data communication under Android. The driver is based on the Android USB Host protocol, and the user can call the provided interface API to communicate with the Android USB Host.

This CH341 has an interface JAR file, and the functions are described in a pdf file.
  • int CH341SystemInit()
  • int[][] CH341getPIDVID()
  • boolean CH341GetInput(int[] iStatus)
  • boolean CH341SetOutput(long iEnable, long iSetDirOut, long iSetDataOut)
  • boolean CH341Set_D5_D0(long iSetDirOut, long iSetDataOut)
  • boolean CH341SetTimeOut(int WriteTimeOut, int ReadTimeOut)
  • boolean CH341StreamSPI4(char chipSelect, long iLength, byte[] ioBuffer)

In addition the source code of a sample app is provided.

(P.S. Source file citation removed on 10/27/2019)

How can I declare these functions?

(Unfortunately when creating a USB device, it is necessary to buy a VID / PID address, and for a small project it becomes unviable, so the need to find a faster interface alternative than the serial port with USB adapter)

Thank you.

Ref: Accesing third party Jar with #Additionaljar and JavaObject - Picasso
 
Last edited:

rtek1000

Active Member
Licensed User
Longtime User
Interesting how hardware is linked with software:

multiport = new MultiPortManager(
(UsbManager) getSystemService(Context.USB_SERVICE), this,
ACTION_USB_PERMISSION);

(P.S. Source file citation removed on 10/27/2019)
 

Attachments

  • device_filter.zip
    278 bytes · Views: 438
  • multiport.zip
    11.6 KB · Views: 459
Last edited:
Upvote 0

rtek1000

Active Member
Licensed User
Longtime User
ch341a-devboard3.jpg
 
Upvote 0

rtek1000

Active Member
Licensed User
Longtime User
thanks, but maybe if everyone needs to know how to program in Java, then it makes no sense to use B4X ¯\_(ツ)_/¯
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
Not true.
Writing a app completely in java is more complicated.
B4A makes it MUCH easier.
In most cases NO java knowledge is needed at all!

But in some cases it is really helpful to know some java and to be able to use a thirdparty jar. Like in this case.

If you are not able then you can:
- Create a thread in the Wishforum
- Hire someone who do the job for you (JobOffer forum).
- Wait and hope someone is boring and do the Job because of this.
 
Last edited:
Upvote 0

rtek1000

Active Member
Licensed User
Longtime User
I was able to generate a library. I was also able to compile on Eclipse and Android Studio.

But I didn't get the result I expected. It seems that Android takes too long to communicate with the CH341. The CH341 library seems unable to transfer a very large amount of data either. (I use CH341 to program EEPROM on Windows, and it seems to have better speed performance).

The code of library (CH341MultiPort.java) was based on the examples available in the repository. It has interesting functions in the repository sample code, such as AVR (Atmega) / S51 chip programmer function.

The CH341PAR_B4A.jar/xml was compiled with: Simple Library Compiler - Build libraries

These logs below are from the android app I made for basic tests (Note the time variation):
str2 length: 96
Time to send: 38ms
54 - SPI write done
str2 length: 96
Time to send: 21ms
55 - SPI write done
str2 length: 96
Time to send: 23ms
56 - SPI write done
str2 length: 96
Time to send: 55ms
57 - SPI write done
str2 length: 96
Time to send: 33ms
58 - SPI write done
str2 length: 96
Time to send: 11ms
59 - SPI write done
str2 length: 124
Time to send: 18ms
0 - SPI write done
str2 length: 124
Time to send: 20ms
1 - SPI write done

CH341 repository:
https://github.com/boseji/CH341-Store
(There are several examples, for Windows/Linux/MAC/Android, many of the comments are in chinese, but you can understand almost everything using the Google translator.)

The library for B4A was based on the functions available in the CH341PAR.jar Android library file, so if in doubt you can decompile and see how the Java file (MultiPortManager.java) was written. (P.S. Commands look better explained in AVR programmer (CH341DP) example for Windows, I didn't see all the examples)
 

Attachments

  • CH341_SPI.zip
    9.2 KB · Views: 423
  • CH341PAR_B4A.jar
    3.6 KB · Views: 355
  • CH341PAR_B4A.xml
    17.7 KB · Views: 344
  • MultiPortManager.java
    52 KB · Views: 340
  • CH341MultiPort.java
    15.2 KB · Views: 630
Last edited:
Upvote 0

rtek1000

Active Member
Licensed User
Longtime User
Test Code with Arduino UNO / Nano / Pro Mini (Atmega328):

Master (CH341) / Slave (Arduino)
SCK ---------------> SCK
MISO <-------------- MISO
MOSI --------------> MOSI
SS ---------------> SS
GND <-------------> GND

B4X:
#include "pins_arduino.h"

char buf [128];
volatile byte pos;
volatile boolean process_it;

void setup (void)
{
  Serial.begin (115200);   // debugging

  Serial.println("SPI Test");

  // turn on SPI in slave mode
  SPCR |= _BV(SPE);

  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);
  pinMode(MOSI, INPUT);
  pinMode(SCK, INPUT);
  pinMode(SS, INPUT);

  // turn on interrupts
  SPCR |= _BV(SPIE);

  pos = 0;
  process_it = false;
}  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
{
  byte c = SPDR; // Receive register

  SPDR = c; // Send register

  // add to buffer if room
  if (pos < sizeof buf)
  {
    buf [pos++] = c;

    // example: newline means time to process buffer
    if (c == '\n')
      process_it = true;

  }  // end of room available
}

// main loop - wait for flag set in interrupt routine
void loop (void)
{
  if (process_it)
  {
    buf [pos] = 0;
    Serial.println (buf);
    pos = 0;
    process_it = false;
  }  // end of flag set

}  // end of loop

Source: https://forum.arduino.cc/index.php?topic=52111.0
 
Upvote 0
Top