Congratulations to our 2022 Qt Champions!

QtSerialPort with /dev/spidev

  • Did anybody make QSerialPort(Info) work on /dev/spidev* kernel driver?

    I have running (visible, configured, operable via spidev_test.c) /dev/spidev0.0, however QSerialPortInfo::availablePorts returns list with just one member, for /dev/ttyAMA0. I guess I can not (simply) use QSerialPort constructor with "/dev/spidev0.0" parameter before "somehow" getting /dev/spidev0.0 accepted by QSerialPortInfo. Am I wrong? What to do to make /dev/spidev0.0 appear in the list?

    Any clues and advices heartily welcome. (I am able to workaround based on QFile of course, however I would love to do things Qt way ;) .)

  • QSerialPort and QSerialPortInfo were written to work with serial ports aka (UART, RS232, e.t.c), not with SPI interfaces.

  • Thanks for explanation.

    SPI has same basic characteristics like serial port (baud rate, parity...) and even (kind of) asynchronous in/out driven by kernel device so this is why I expected same object could manage them both.

    Now I intend to develop some object for accessing RS-485 UART on RaspComm board (which is itself driven via SPI). Is there something in Qt (ready or WIP) about this (not to re-invent wheel) or is there some design skeleton/advice allowing eventually later extend QtSerialPort by this "device"? (I am willing to contribute, should my development be evaluated as worth it.)

  • AFAIK there isn't any implementation for SPI interface in Qt. So probably you must write your own implementation. As i assumed you use raspberry for your project so you can try bcm2835 library for this.

  • Getting back to document conclusions of my research on best practice of using RaspiComm RS-485 under Qt for anybody, who finds this thread useful (I expect many of it is valid for RS-232 on same board as well, did not test myself):

    1. Do not try to implement communication with MAX3140 UART chip yourself (maybe except of asm based implementation, what is however most probably unnecessary exertion). I succeeded to implement it based on kernel /dev/spidev0.0 only to find out that even this partially system driver supported solution is too slow for even 19 200 Bd speed (loosing about 5 characters on one received).
      I myself feared about RaspiComm RS-485 driver /dev/ttyRPC0 based on some forums complaints and not clear versioning, however found out, that the forum thread was heavy outdated. These official installation instructions worked like a charm and the resulting driver worked out-of-box for my latest Raspbian Wheezy (4.1.7+ #817). So I strongly recommend to take this approach.

    2. QSerialPort class has constructor with signature QSerialPort(const QString &, QObject *), where QString may contain even device which is not included in the QList that QSerialPortInfo::availablePorts() returns. This works with no surprise. If one does not set anything than (eventually) baud speed, one gets standard 8 bit, 1 stop bit, no parity without any character translations, good old plain raw binary. So QSerialPort may be used with /dev/ttyRPC0 directly and easily.

      QSerialPort rpc0("/dev/ttyRPC0");
      rpc0.write("Binary request\0even\xffcontaining weird\x03characters", length_of_binary);
      if(rpc0.waitForReadyRead(100)) // Enough long time in miliseconds
      QByteArray data = rpc0.readAll(); // You may have to wait/read repetitively in loop
      // and merge data on higher link speeds

    3. Hardware of RaspiComm uses RTS pin to select in/out direction of data. CTS is kept active permanently by wiring, so using default use RTS/CTS mode works properly with no inappropriate blocking.

    That's all you should need, so enjoy your communication.