「Qtの基礎 - SPI通信」の版間の差分

ナビゲーションに移動 検索に移動
68行目: 68行目:
*: 各ワード転送後にCSをトグルするかどうかを指定する。
*: 各ワード転送後にCSをトグルするかどうかを指定する。
*: 通常、CSはトランザクション全体で低いままであるが、一部のデバイスでは各ワード間でCSをトグルする必要がある。
*: 通常、CSはトランザクション全体で低いままであるが、一部のデバイスでは各ワード間でCSをトグルする必要がある。
<br><br>
== SPI通信の共通クラスの定義 ==
SPI通信の設定を以下に示す。<br>
* LSB First
* 3線式SPIモード / 4線式SPIモード
* ループバックモード
* No Chip Select (CS)
* Ready
* CS Change
<br>
<syntaxhighlight lang="c++">
// SpiDevice.hファイル
#include <QObject>
#include <QFile>
#include <QFuture>
#include <QtConcurrent>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include <fcntl.h>
#include <unistd.h>
class SpiDevice : public QObject
{
    Q_OBJECT
protected:
    QString m_devicePath;
public:
    enum class Mode {
      Mode0 = SPI_MODE_0,
      Mode1 = SPI_MODE_1,
      Mode2 = SPI_MODE_2,
      Mode3 = SPI_MODE_3
    };
    struct Config {
      Mode mode          = Mode::Mode0;
      bool lsbFirst      = false;
      bool threeWire      = false;
      bool loopback      = false;
      bool noCs          = false;
      bool ready          = false;
      bool csChange      = false;
      uint8_t bitsPerWord = 8;
      uint32_t speed      = 500000;
    };
    explicit SpiDevice(const QString& devicePath, QObject* parent = nullptr) : QObject(parent), m_devicePath(devicePath)
    {}
    bool configure(const Config& config)
    {
      QFile spiDevice(m_devicePath);
      if (!spiDevice.open(QIODevice::ReadWrite)) {
          emit errorOccurred("SPIデバイスを開けませんでした: " + spiDevice.errorString());
          return false;
      }
      int fd = spiDevice.handle();
      uint8_t mode = static_cast<uint8_t>(config.mode);
      if (config.lsbFirst)  mode |= SPI_LSB_FIRST;
      if (config.threeWire) mode |= SPI_3WIRE;
      if (config.loopback)  mode |= SPI_LOOP;
      if (config.noCs)      mode |= SPI_NO_CS;
      if (config.ready)    mode |= SPI_READY;
      if (config.csChange)  mode |= SPI_CS_HIGH;
      if (ioctl(fd, SPI_IOC_WR_MODE, &mode) < 0 || ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &config.bitsPerWord) < 0 ||
            ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &config.speed) < 0) {
          emit errorOccurred("SPIの設定に失敗しました");
          spiDevice.close();
          return false;
      }
      spiDevice.close();
      return true;
    }
signals:
    void errorOccurred(const QString& error);
};
</syntaxhighlight>
<br><br>
<br><br>


84行目: 169行目:
  #include <fcntl.h>
  #include <fcntl.h>
  #include <unistd.h>
  #include <unistd.h>
#include "SpiDevice.h"
   
   
  class SpiReader : public QObject
  class SpiReader : public SpiDevice
  {
  {
     Q_OBJECT
     Q_OBJECT
   
   
  private:
  private:
    QString          m_devicePath;
     std::atomic<bool> m_stopReading{false};
     std::atomic<bool> m_stopReading{false};
   
   
  public:
  public:
     explicit SpiReader(const QString& devicePath, QObject* parent = nullptr) : QObject(parent), m_devicePath(devicePath)
     using SpiDevice::SpiDevice;
    {}
   
   
     void startReading(int bufferSize = 1024)
     void startReading(int bufferSize = 1024)
107行目: 191行目:
   
   
           int fd = spiDevice.handle();
           int fd = spiDevice.handle();
          uint8_t mode  = SPI_MODE_0;
          uint8_t bits  = 8;
          uint32_t speed = 500000;
          if (ioctl(fd, SPI_IOC_WR_MODE, &mode) < 0 || ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits) < 0 ||
              ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0) {
            emit errorOccurred("SPIの設定に失敗");
            spiDevice.close();
            return;
          }
           QByteArray buffer(bufferSize, 0);
           QByteArray buffer(bufferSize, 0);
           while (!m_stopReading) {
           while (!m_stopReading) {
             ssize_t ret = read(fd, buffer.data(), buffer.size());
             ssize_t ret = read(fd, buffer.data(), buffer.size());
             if (ret < 0) {
             if (ret < 0) {
                 emit errorOccurred("SPIの読み込みに失敗");
                 emit errorOccurred("SPIの読み込みに失敗しました");
                 break;
                 break;
             }
             }
142行目: 215行目:
  signals:
  signals:
     void dataRead(const QByteArray& data);
     void dataRead(const QByteArray& data);
    void errorOccurred(const QString& error);
     void readingFinished();
     void readingFinished();
  };
  };
159行目: 231行目:
   
   
     SpiReader reader("/dev/spidev0.0");
     SpiReader reader("/dev/spidev0.0");
    SpiDevice::Config config;
    config.mode        = SpiDevice::Mode::Mode0;
    config.lsbFirst    = true;
    config.threeWire  = true;
    config.loopback    = false;
    config.noCs        = true;
    config.ready      = false;
    config.csChange    = false;
    config.bitsPerWord = 8;
    config.speed      = 1000000;
    if (!reader.configure(config) || !writer.configure(config)) {
      qDebug() << "SPIデバイスの設定に失敗";
      return -1;
    }
   
   
     QObject::connect(&reader, &SpiReader::dataRead, [](const QByteArray& data) {
     QObject::connect(&reader, &SpiReader::dataRead, [](const QByteArray& data) {

案内メニュー