Difference between revisions of "Beaglebone black i2c"

From Teknologisk videncenter
Jump to: navigation, search
m (I2C device drivers)
m
 
(9 intermediate revisions by the same user not shown)
Line 19: Line 19:
 
*"UU" Means probing was skipped, because a device driver uses the address
 
*"UU" Means probing was skipped, because a device driver uses the address
 
*"Number" - A n i2c device was found
 
*"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'''
 +
 +
<source lang=c>
 +
* 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);
 +
}
 +
</source>
  
 
=I2C device drivers=
 
=I2C device drivers=
 +
*[https://www.kernel.org/doc/html/next/i2c/dev-interface.html Implementing I2C device drivers in userspace] (From kernel.org)
 
*[https://www.kernel.org/doc/Documentation/i2c/dev-interface i2c dev-interface] (Must read i2c or SM-bus)
 
*[https://www.kernel.org/doc/Documentation/i2c/dev-interface i2c dev-interface] (Must read i2c or SM-bus)
 
*[https://www.kernel.org/doc/html/latest/i2c/writing-clients.html Implementing I2C device drivers]
 
*[https://www.kernel.org/doc/html/latest/i2c/writing-clients.html Implementing I2C device drivers]
  
[[Category:Beagleboard Black]][[Category:i2c]][[Category:Linux]]
+
[[Category:Beagleboard Black]][[Category:I2C]][[Category:Linux]]

Latest revision as of 16:49, 29 November 2023


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