【Raspberry Pi】C++ library for handling I2C, SPI and UART

1. Description

        The Raspberry Pi is a single board computer that now comes in 4 revisions and a minimalistic Zero variant. It is a popular choice for different projects because of its small size, high power consumption, fast processing speed, and being a complete Linux-based computer.

        One way to connect multiple single-board computers and/or microcontrollers is by direct wiring. For this, the most commonly used protocols are I2C, SPI and UART. Previous posts in the blog series explained the principles of these protocols and introduced Arduino-specific C libraries. In this article, I'll explain the C++ libraries that enable the use of these protocols on the Raspberry Pi. For each protocol, I research the available libraries and give a short explanation and code example. Please don't say that these examples were not developed by me, but are from the library documentation and should serve as the basis for concrete working examples.

This article originally appeared on my blog admantium.com .

Two, I2C

        I2C is supported via the SMBus protocol, which is described as a specific variant of the I2C bus. This protocol is available as  a Linux kernel module . To use it, you need to configure your Raspberry Pi. In Terminal, run, select and .raspi-config3 Interfacing OptionsP5 I2C

        Following  the code example at kernel.org , you need to open the device file representing the attached I2C device, then send the SMBus command by writing to the device registers.

// 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

        To use SPI, you also need to add a specific kernel module: Spidev . Raspberry Pi supports this module, you need to configure it by calling, and then select and.raspi-config3 Interfacing OptionsP4 SPI

        To access SPI functions using C/C++,  the spidev wrapper library can be used . Following the example code , you need to configure the SPI connection, then open the device to connect to, and use the library methods to read and write data.

//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

        A UART connection can be made with the common C library. Following the very detailed instructions in this article , you will need to open the device, then use the various properties that define the TTY device, then write to and read from the serial port.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. General GPIO access

The library libgpiod provides generic access to the GPIOs of any device running Linux. It detects available GPIOs, can read and write data, and waits for trigger events. With this, you can write ow code to communicate the UART with any connected device.

        To install it, run the following command:

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 

        If the compilation and installation were successful, you will find binaries in a subfolder that can be used to browse the GPIO. See the examples below../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
... 

        If you want to use the library, read this article for detailed instructions.

6. Conclusion

        In order to use I2C, SPI and UART on Raspberry Pi, not only Python but also C++ libraries can be used. Specifically, you need to activate the I2C and SPI functions, which will load the corresponding kernel modules locally. Then select the client library and other necessary C++ headers. Using the library follows the same principles: determine the device file for the connection, configure the connection object, open the device file, and read/write to it. Finally, the handy library libgpiod gives you direct access to all GPIO pins, which is helpful for debugging.raspi-config

 

Guess you like

Origin blog.csdn.net/gongdiwudu/article/details/131913868