Beaglebone black i2c

From Teknologisk videncenter
Jump to: navigation, search


Detect i2c devices

Use with a little care - read the i2cdetect man page

root@beaglebone:/home/debian/bin# i2cdetect -y -r 2
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- 18 -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- 3c -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- UU UU UU UU -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
  • --" Means no answer on probe
  • "UU" Means probing was skipped, because a device driver uses the address
  • "Number" - A n i2c device was found

I2C Low level

See: /usr/include/linux/i2c.h for i2c_msg structure and flags and i2c_rdwr_ioctl_data

 * Module...: seeed_dip6.c
 * Version..: 0.1 (Beta - unfinished)
 * Author...: Henrik Thomsen/Mercantec <heth@mercantec.dk
 * Date.....: 10. nov 2023
 *
 * Abstract.: Implementation of Seeed Grove Sensor "I2C High
 *            Accuracy Temperature sensor" based on MCP-9808
 *            Implementet in user space using libi2c
 * Mod. log.: 01-06-2021: Could not compile. Got i2c_smbus_read_word_data undefined.
                              Include <i2c/smbus.h> should be include. (Worked in 2020)

 * License..: Free open software but WITHOUT ANY WARRANTY.
 * Terms....: see http://www.gnu.org/licenses
 *
 * Documentation - see https://mars.merhot.dk/w/index.php/Grove_I2C_High_Accuracy_Temerature_Sensor_-_Seeed
 *
 * REMEMBER: Install the libi2c-dev package to compile this file
 * Compile this example with: gcc seeed_dip6.c  -o seeed_dip6  -li2c 
 */
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

//Device specific information. (Perhaps better as command options or config file)
#define I2C_BUS "/dev/i2c-2"
#define I2C_ADDR 0x03 // Grove DIP-switch 6 slave address default

int main(void) {
  int file;
  int nmsgs_sent;
  unsigned int len;
  int i;
  char buf[2][20];
  struct i2c_msg msgs[I2C_RDRW_IOCTL_MAX_MSGS]; // I2C_RDRW_IOCTL_MAX_MSGS defined in linx/i2c-dev.h
  struct i2c_rdwr_ioctl_data rdwr;

  // init msgs's
  for (i = 0; i < I2C_RDRW_IOCTL_MAX_MSGS; i++)
    msgs[i].buf = NULL;

  // Maybe errer just assumes bus number
  file = open(I2C_BUS, O_RDWR);
  if (file < 0) { // If error
    fprintf(stderr, "ERROR: opening %s - %s\n", I2C_BUS, strerror(errno));
    exit(1);
  }

  if (file < 0)
    fprintf(stderr, "ERROR: open_i2c_dev failed: %s", strerror(errno));

  // Build IOCTL operation message structure. (What you want to do)

  //msgs[0] Write one byte - Command in buf[0] - flags 0 = write
  msgs[0].addr = I2C_ADDR;
  msgs[0].flags = 0;
  msgs[0].len = 1;
  msgs[0].buf = buf[0];
  buf[0][0] = 0x01;

  //msgs[1] read 10 bytes to buf
  msgs[1].addr = I2C_ADDR;
  msgs[1].flags = 1;
  msgs[1].len = 10;
  msgs[1].buf = buf[1];

  rdwr.msgs = msgs;
  rdwr.nmsgs = 2;
  nmsgs_sent = ioctl(file, I2C_RDWR, & rdwr);
  if (nmsgs_sent != 2) {
    fprintf(stderr, "ERRORi in line %d: Wrong number of messages: %d\n", __LINE__, nmsgs_sent);
    exit(0);
  }
  for (i = 0; i < 10; i++)
    printf("Read 0x2d: %x\n", buf[1][i]);
  return (0);
}

I2C device drivers