【Raspberry Pi】I2C、SPI、UARTを扱うためのC++ライブラリ

1. 説明

        Raspberry Pi は、現在 4 つのリビジョンとミニマルな Zero バリアントが提供されているシングルボード コンピューターです。サイズが小さく、消費電力が高く、処理速度が速く、完全な Linux ベースのコンピューターであるため、さまざまなプロジェクトで人気の選択肢です。

        複数のシングルボード コンピュータやマイクロコントローラを接続する方法の 1 つは、直接配線です。このために最も一般的に使用されるプロトコルは、I2C、SPI、および UART です。ブログ シリーズの以前の投稿では、これらのプロトコルの原理を説明し、Arduino 固有の C ライブラリを紹介しました。この記事では、Raspberry Pi でこれらのプロトコルを使用できるようにする C++ ライブラリについて説明します。各プロトコルについて、利用可能なライブラリを調査し、簡単な説明とコード例を示します。これらの例は私が開発したものではなく、ライブラリのドキュメントからのものであり、具体的な動作例の基礎として役立つはずであるとは言わないでください。

この記事はもともと私のブログ admantium.comに掲載されたものです。

二、I2C

        I2C は、I2C バスの特定のバリアントとして説明される SMBus プロトコル経由でサポートされます。このプロトコルは、 Linux カーネル モジュールとして利用できます これを使用するには、Raspberry Pi を設定する必要があります。ターミナルで、実行し、選択し、 を選択します。raspi-config3 Interfacing OptionsP5 I2C

kernel.org のコード例        に従って 、接続された I2C デバイスを表すデバイス ファイルを開き、デバイス レジスタに書き込んで SMBus コマンドを送信する必要があります。

// SOURCE: https://www.kernel.org/doc/Documentation/i2c/dev-interface */
#include <linux/i2c-dev.h>
#include <i2c/smbus.h>int file;
int adapter_nr = 2;
char filename[20];snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);
file = open(filename, O_RDWR);
if (file < 0) {
  exit(1);
}  int addr = 0x40;if (ioctl(file, I2C_SLAVE, addr) < 0) {
  exit(1);
}__u8 reg = 0x10;
__s32 res;
char buf[10];res = i2c_smbus_read_word_data(file, reg);
if (res < 0) {
  /* ERROR HANDLING: i2c transaction failed */
} else {
  /* res contains the read word */
}buf[0] = reg;
buf[1] = 0x43;
buf[2] = 0x65;
if (write(file, buf, 3) != 3) {
  /* ERROR HANDLING: i2c transaction failed */
} 

3.SPI

SPI を使用するには、特定のカーネル モジュールSpidev        を追加する必要もありますRaspberry Pi はこのモジュールをサポートしています。呼び出して構成し、[and] を選択する必要があります。raspi-config3 Interfacing OptionsP4 SPI

        C/C++ を使用して SPI 関数にアクセスするには、  spidev ラッパー ライブラリを使用できます。サンプル コードに従って、SPI 接続を構成し、接続するデバイスを開いて、ライブラリ メソッドを使用してデータの読み取りと書き込みを行う必要があります。

//SOURCE: https://raw.githubusercontent.com/milekium/spidev-lib/master/sample/spidev-testcpp.cc
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <spidev_lib++.h>spi_config_t spi_config;
uint8_t tx_buffer[32];
uint8_t rx_buffer[32];int  main( void)
{  SPI *mySPI = NULL;  spi_config.mode=0;
  spi_config.speed=1000000;
  spi_config.delay=0;
  spi_config.bits_per_word=8;  mySPI=new SPI("/dev/spidev1.0",&spi_config);  if (mySPI->begin())
  {
    memset(tx_buffer,0,32);
    memset(rx_buffer,0,32);
    sprintf((char*)tx_buffer,"hello world");
    printf("sending %s, to spidev2.0 in full duplex \n ",(char*)tx_buffer);
    mySPI->xfer(tx_buffer,strlen((char*)tx_buffer),rx_buffer,strlen((char*)tx_buffer));
    printf("rx_buffer=%s\n",(char *)rx_buffer);
    //mySPI->end();
    delete mySPI;
  }
 return 1;
} 

4.UART

        共通Cライブラリを使用してUART接続が可能です。この記事の非常に詳細な手順に従って、デバイスを開いて、TTY デバイスを定義するさまざまなプロパティを使用して、シリアル ポートへの書き込みとシリアル ポートからの読み取りを行う必要があります。termios struct

// SOURCE: https://blog.mbedded.ninja/programming/operating-systems/linux/linux-serial-ports-using-c-cpp/
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>int main() {
  int serial_port = open("/dev/ttyUSB0", O_RDWR);  struct termios tty;  if(tcgetattr(serial_port, &tty) != 0) {
      printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
      return 1;
  }  tty.c_cflag &= ~PARENB;
  tty.c_cflag &= ~CSTOPB;
  tty.c_cflag &= ~CSIZE;
  tty.c_cflag |= CS8;
  tty.c_cflag &= ~CRTSCTS;
  tty.c_cflag |= CREAD | CLOCAL;  tty.c_lflag &= ~ICANON;
  tty.c_lflag &= ~ECHO;
  tty.c_lflag &= ~ECHOE;
  tty.c_lflag &= ~ECHONL;
  tty.c_lflag &= ~ISIG;
  tty.c_iflag &= ~(IXON | IXOFF | IXANY);
  tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL);  tty.c_oflag &= ~OPOST;
  tty.c_oflag &= ~ONLCR;  tty.c_cc[VTIME] = 10;
  tty.c_cc[VMIN] = 0;  cfsetispeed(&tty, B9600);
  cfsetospeed(&tty, B9600);  if (tcsetattr(serial_port, TCSANOW, &tty) != 0) {
      printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
      return 1;
  }  unsigned char msg[] = { 'H', 'e', 'l', 'l', 'o', '\r' };
  write(serial_port, "Hello, world!", sizeof(msg));  char read_buf [256];  memset(&read_buf, '\0', sizeof(read_buf);  int num_bytes = read(serial_port, &read_buf, sizeof(read_buf));  if (num_bytes < 0) {
      printf("Error reading: %s", strerror(errno));
      return 1;
  }  printf("Read %i bytes. Received message: %s", num_bytes, read_buf);  close(serial_port)
  return 0; 

5. 一般的な GPIO アクセス

ライブラリ libgpiod は、 Linux を実行しているデバイスの GPIO への汎用アクセスを提供します。使用可能な GPIO を検出し、データの読み取りと書き込みが可能で、トリガー イベントを待機します。これにより、接続されたデバイスと UART を通信するためのコードを作成できます。

        インストールするには、次のコマンドを実行します。

apt-get install autoconf autoconf-archive libtool libkmod-dev pkg-config
git clone https://github.com/brgl/libgpiod.gitcd libgpiod
./autogen.sh --enable-tools=yes --prefix=/usr/local/bin
make
sudo make install 

        コンパイルとインストールが成功すると、GPIO の参照に使用できるバイナリがサブフォルダー内に見つかります。以下の例を参照してください。./toolsgpiodetectgpioinfo

 ./tools/gpiodetect
gpiochip0 [pinctrl-bcm2711] (58 lines)
gpiochip1 [raspberrypi-exp-gpio] (8 lines)./tools/gpioinfo
gpiochip0 - 58 lines:
 line   0:     "ID_SDA"       unused   input  active-high
 line   1:     "ID_SCL"       unused   input  active-high
 line   2:       "SDA1"       unused   input  active-high
 line   3:       "SCL1"       unused   input  active-high
 line   4:  "GPIO_GCLK"       unused   input  active-high
 line   5:      "GPIO5"       unused   input  active-high
... 

        ライブラリを使用する場合は、この記事の詳細な手順をお読みください。

6. 結論

        Raspberry Pi で I2C、SPI、UART を使用するには、Python だけでなく C++ ライブラリも使用できます。具体的には、対応するカーネル モジュールをローカルにロードする I2C および SPI 機能をアクティブにする必要があります。次に、クライアント ライブラリとその他の必要な C++ ヘッダーを選択します。ライブラリの使用も同じ原則に従います。つまり、接続用のデバイス ファイルを決定し、接続オブジェクトを構成し、デバイス ファイルを開き、デバイス ファイルの読み取り/書き込みを行います。最後に、便利なライブラリ libgpiod を使用すると、すべての GPIO ピンに直接アクセスでき、デバッグに役立ちます。raspi-config

 

おすすめ

転載: blog.csdn.net/gongdiwudu/article/details/131913868