Kommunizieren Sie mit I2C-Geräten unter Linux C.

Einführung

Wenn Sie ein I2C-Gerät mit Raspberry Pi oder Jetson nano verwenden möchten, verfügt RasPi über Bibliotheken wie pigpio und WiringPi, Jetson jedoch nur über Jetson.GPIO. Dies kann ein Problem sein, wenn Sie in C / C ++ schreiben möchten. (Bist Du in Schwierigkeiten ??)

Zu dieser Zeit schrieb ich einen Artikel über die Kommunikation mit I2C-Geräten mithilfe des universellen I2C-Treibers von Linux.

Bestätigungsumgebung

Quellcode

Es scheint verschiedene Möglichkeiten zu geben, mit I2C-Geräten zu kommunizieren, aber dieser Code verwendet ioctl I2C_RDWR.

i2c_example.c


#include <stdint.h>
// ...
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>

static const char* dev_name = "/dev/i2c-1";

/*!Lesen Sie Daten vom I2C-Slave-Gerät.
 * @param[in] dev_Adr-Geräteadresse.
 * @param[in] reg_Adresse des Adr-Registers.
 * @param[out]Daten Ein Zeiger auf den Speicherort der zu lesenden Daten.
 * @param[in]Länge Länge der zu lesenden Daten.
 */
int8_t i2c_read(
    uint8_t dev_addr, uint8_t reg_addr, uint8_t* data, uint16_t length) {
  /*Öffnen Sie das I2C-Gerät. */
  int32_t fd = open(dev_name, O_RDWR);
  if (fd == -1) {
    fprintf(stderr, "i2c_read: failed to open: %s\n", strerror(errno));
    return -1;
  }

  /* I2C-Erstellen Sie eine Lesemeldung. */
  struct i2c_msg messages[] = {
      { dev_addr, 0, 1, &reg_addr },         /*Registeradresse einstellen. */
      { dev_addr, I2C_M_RD, length, data },  /*Längenbytes in Daten einlesen. */
  };
  struct i2c_rdwr_ioctl_data ioctl_data = { messages, 2 };

  /* I2C-Lesen. */
  if (ioctl(fd, I2C_RDWR, &ioctl_data) != 2) {
    fprintf(stderr, "i2c_read: failed to ioctl: %s\n", strerror(errno));
    close(fd);
    return -1;
  }

  close(fd);
  return 0;
}

/*!Schreiben Sie Daten auf das I2C-Slave-Gerät.
 * @param[in] dev_Adr-Geräteadresse.
 * @param[in] reg_Adresse des Adressregisters.
 * @param[in]Daten Ein Zeiger auf den Speicherort der zu schreibenden Daten.
 * @param[in]Länge Länge der zu schreibenden Daten.
 */
int8_t i2c_write(
    uint8_t dev_addr, uint8_t reg_addr, const uint8_t* data, uint16_t length) {
  /*Öffnen Sie das I2C-Gerät. */
  int32_t fd = open(dev_name, O_RDWR);
  if (fd == -1) {
    fprintf(stderr, "i2c_write: failed to open: %s\n", strerror(errno));
    return -1;
  }

  /* I2C-Bereiten Sie einen Puffer für Write vor. */
  uint8_t* buffer = (uint8_t*)malloc(length + 1);
  if (buffer == NULL) {
    fprintf(stderr, "i2c_write: failed to memory allocate\n");
    close(fd);
    return -1;
  }
  buffer[0] = reg_addr;              /*Stellen Sie die Registeradresse im ersten Byte ein. */
  memcpy(&buffer[1], data, length);  /*Daten nach dem zweiten Byte einstellen. */

  /* I2C-Schreiben Nachricht schreiben. */
  struct i2c_msg message = { dev_addr, 0, length + 1, buffer };
  struct i2c_rdwr_ioctl_data ioctl_data = { &message, 1 };

  /* I2C-Schreiben. */
  if (ioctl(fd, I2C_RDWR, &ioctl_data) != 1) {
    fprintf(stderr, "i2c_write: failed to ioctl: %s\n", strerror(errno));
    free(buffer);
    close(fd);
    return -1;
  }

  free(buffer);
  close(fd);
  return 0;
}

Kommentar

Zunächst die Aufnahme des Headers und die Definition des Gerätenamens.

python


#include <linux/i2c-dev.h>
#include <linux/i2c.h>

static const char* dev_name = "/dev/i2c-1";

Die Pinbelegung für den I2C-Bus1 von RasPi und Jetson nano ist identisch, und der Gerätename ist für / dev / i2c-1 identisch.

Lesevorgang

python


  /* I2C-Erstellen Sie eine Lesemeldung. */
  struct i2c_msg messages[] = {
      { dev_addr, 0, 1, &reg_addr },         /*Registeradresse einstellen. */
      { dev_addr, I2C_M_RD, length, data },  /*Längenbytes in Daten einlesen. */
  };
  struct i2c_rdwr_ioctl_data ioctl_data = { messages, 2 };

  /* I2C-Lesen. */
  if (ioctl(fd, I2C_RDWR, &ioctl_data) != 2) {

Zum Lesen sind zwei i2c_msg-Strukturen erforderlich. Stellen Sie zuerst die Registeradresse ein, Die zweite zu lesende Größe und der Speicherort der Daten werden angegeben.

Schreibvorgang

python


  /* I2C-Bereiten Sie einen Puffer für Write vor. */
  uint8_t* buffer = (uint8_t*)malloc(length + 1);
  buffer[0] = reg_addr;              /*Stellen Sie die Registeradresse im ersten Byte ein. */
  memcpy(&buffer[1], data, length);  /*Daten nach dem zweiten Byte einstellen. */

  /* I2C-Schreiben Nachricht schreiben. */
  struct i2c_msg message = { dev_addr, 0, length + 1, buffer };
  struct i2c_rdwr_ioctl_data ioctl_data = { &message, 1 };

  /* I2C-Schreiben. */
  if (ioctl(fd, I2C_RDWR, &ioctl_data) != 1) {

Zum Zeitpunkt des Schreibens ist ein Puffer mit "Länge der zu schreibenden Daten + 1" erforderlich. Stellen Sie die Registeradresse im 1. Byte ein, Stellen Sie die Daten nach dem zweiten Byte ein.

Die i2c_msg-Struktur wird eins sein.

abschließend

Ich konnte mit diesem Code sowohl auf RasPi als auch auf Jetson Nano mit I2C-Geräten kommunizieren. Beachten Sie jedoch, dass der Code und der Inhalt möglicherweise falsch sind.

Recommended Posts

Kommunizieren Sie mit I2C-Geräten unter Linux C.
Segfo mit 16 Zeichen in C-Sprache
X86 Assembler unter Linux (Verknüpfung mit C)
[C] [Python] Lesen mit AquesTalk unter Linux
Erstellen Sie Amazon Linux mit AWS EC2 und melden Sie sich an
Versuchen Sie, Python mit pybind11 in ein C ++ - Programm einzubetten
Bibliothek zum Messen der Ausführungszeit in Linux C-Anwendungen
Verarbeiten Sie Signale in C-Sprache
Behälterartig hergestellt mit C # 1
Linux-Berechtigungen für Java
C / C ++ - Debugging mit gdb
Linux (Lubuntu) mit OneMix3S
Greifen Sie auf MongoDB in C zu
Seurat unter Linux (Installation)
C-API in Python 3
Erstellen Sie Azure-Pipelies mit Azure DevOps in einer selbst gehosteten Linux-Umgebung
Greifen Sie auf das Feld C-Struktur mit dem in Go reservierten Namen zu.