element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Single-Board Computers
  • Products
  • Dev Tools
  • Single-Board Computers
  • More
  • Cancel
Single-Board Computers
Forum BBB - I2C notes
  • Blog
  • Forum
  • Documents
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Single-Board Computers to participate - click to join for free!
Actions
  • Share
  • More
  • Cancel
Forum Thread Details
  • Replies 33 replies
  • Subscribers 60 subscribers
  • Views 6693 views
  • Users 0 members are here
  • beaglebone_black
  • beagle_black
  • bb_black
  • beagle_bone_black
Related

BBB - I2C notes

shabaz
shabaz over 12 years ago

Note: 15th August 2019: The I2C library described here has been wrapped up into a single general-purpose I/O library which includes I2C and SPI. See here:

BeagleBone Black (BBB) and PocketBeagle I/O (GPIO), SPI and I2C Library for C – 2019 Edition

 

I2C turns out to be fairly easy and straightforward on the BBB.

There are three I2C busses (I2C0, I2C1, I2C2), of which I2C2 is easily usable (Expansion port P9, see table 11 in the SRM).

 

I2C0: used for some on-board components (HDMI, EEPROM, power mgmt). Not brought out to any connector/header

I2C1: entirely free to use, but doesn't seem to be enabled

I2C2: entirely free to use, and works

 

NOTE: In software, the busses are numbered differently; I2C2 is identified as 1. I2C0 is identified as 0.

 

The C code in the zip file attached worked for me on I2C2 bus (it's just a tidied version of various other peoples code, with some wrapper

functions to make life easier).

 

 

// bus=1 for interface I2C2 on BBB

// returns handle to be used in remainder functions

// addr is a 7-bit value (so, for example the BMP085-0330SBO008BMP085-0330SBO008 datasheet specifies

// 0xEE, so we need to right-shift by 1 and use 0x77 for this function)

int i2c_open(unsigned char bus, unsigned char addr);

// These functions return -1 on error, otherwise return the number of bytes read/written:

int i2c_write(int handle, unsigned char* buf, unsigned char length);

int i2c_read(int handle, unsigned char* buf, unsigned char length);

int i2c_write_read(int handle,

                   unsigned char addr_w, unsigned char *buf_w, unsigned int len_w,

                   unsigned char addr_r, unsigned char *buf_r, unsigned int len_r);

int i2c_write_ignore_nack(int handle,

                          unsigned char addr_w, unsigned char* buf, unsigned int length);

int i2c_read_no_ack(int handle,

                    unsigned char addr_r, unsigned char* buf, unsigned int length);

int i2c_write_byte(int handle, unsigned char val);

int i2c_read_byte(int handle, unsigned char* val);

// These functions return -1 on error, otherwise return 0 on success

int i2c_close(int handle);

// Provides an inaccurate delay (may be useful for waiting for ADC etc).

// The maximum delay is 999msec

int delay_ms(unsigned int msec);

 

 

By default the bus appears to run at 100kbps approx.

I created a test program using the nearest I2C device at hand (which happened to be a BMP085 temperature and pressure sensor),

it is part of the zip contents.

 

 

root@beaglebone:~# ./a.out

Temperature is 23.6 degrees C

Pressure is 101.027 kPa

 

 

I noticed it is not possible to control the power mgmt ic using the code, since presumably it is a protected resource.

 

I2C2 on Expansion header P9:

pin 19: SCL

pin 20: SDA

pin 1: 0V

pin 3: 3.3V

 

 

image

 

Message was edited by: Shabaz  - added more recent v3 which adds a couple more functions, and added a precompiled library (put it in /usr/lib and put the header in /usr/include)

Attachments:
i2c_code_v3.zip
precompiledv3.zip
  • Sign in to reply
  • Cancel

Top Replies

  • Former Member
    Former Member over 12 years ago +1
    shabaz wrote: NOTE: In software, the busses are numbered differently; I2C 2 is identified as 1 . I2C0 is identified as 0. That will be due to the order of registration with the kernels i2c subsystem. I…
  • shabaz
    shabaz over 12 years ago in reply to Former Member +1
    That's good to know! So we'll be able to enumerate at the start of code. Hopefully a build will appear with the full 400kHz speed too. I had to update the code a little bit (attached) with a new function…
  • shabaz
    shabaz over 12 years ago +1
    The code is updated to v3 (I've left the older version there for now, I'll delete it in a few days), to add a couple more functions for I2C-like devices that don't actually ack at all (which is technically…
  • Former Member
    Former Member over 12 years ago

    shabaz wrote:

     

    NOTE: In software, the busses are numbered differently; I2C2 is identified as 1. I2C0 is identified as 0.

    That will be due to the order of registration with the kernels i2c subsystem. I expect that when the hardware's I2C1 is enabled then it will get /dev/i2c-1 and I2C2 will move to /dev/i2c-2

     

    You'll be able to work out which one is which by looking at the targets of the symlinks in /sys/bus/i2c/devices

     

    root@beaglebone:/sys/bus/i2c/devices# ls -l i2c*

    lrwxrwxrwx 1 root root 0 Jan  2 04:52 i2c-0 -> ../../../devices/ocp.2/44e0b000.i2c/i2c-0/

    lrwxrwxrwx 1 root root 0 Jan  2 04:52 i2c-1 -> ../../../devices/ocp.2/4819c000.i2c/i2c-1/

     


    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • shabaz
    shabaz over 12 years ago in reply to Former Member

    That's good to know! So we'll be able to enumerate at the start of code.

    Hopefully a build will appear with the full 400kHz speed too.

     

    I had to update the code a little bit (attached) with a new function (repeated start capability - needed for some I2C devices).

     

    // To perform a 'repeated start' use the i2c_write_read function which can write some

    // data and then immediately read data without a stop bit in between.

    int i2c_write_read(int handle,

                       unsigned char addr_w, unsigned char *buf_w, unsigned int len_w,

                       unsigned char addr_r, unsigned char *buf_r, unsigned int len_r);

    Attachments:
    i2c_code_v2.zip
    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • Former Member
    Former Member over 12 years ago in reply to shabaz

    shabaz wrote:

     

    Hopefully a build will appear with the full 400kHz speed too.

    fairly sure you could do that yourself if you wanted to

     

    i2c@4819c000 {

                            compatible = "ti,omap4-i2c";

                            #address-cells = <0x1>;

                            #size-cells = <0x0>;

                            ti,hwmods = "i2c3";

                            reg = <0x4819c000 0x1000>;

                            interrupts = <0x1e>;

                            status = "okay";

                            pinctrl-names = "default";

                            pinctrl-0 = <0x4>;

                            clock-frequency = <0x186a0>;

                            linux,phandle = <0x24>;

     

    haven't tried it, but 0x186a0 is 100kHz, so seems it would work. You'd need to check that anything else on the bus will be happy at a higher frequency too - you probably don't want to annoy the PMIC for example..

     

    The reg = <0x4819c000 line in there is also your key to the data in /sys so you can see how it all ties together.

     

    Devicetree seems like a bit of a pain, especially if it's going to be the only interface to setting up pinmux, but on the other hand there's lots of other stuff in there for you to tweak and it doesn't require a full kernel recompile the way platform data in previous kernels did.


    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • shabaz
    shabaz over 12 years ago

    The code is updated to v3 (I've left the older version there for now, I'll delete it in a few days), to add a couple more functions for I2C-like devices that don't actually ack at all (which is technically against the I2C spec).

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • jrychter
    jrychter over 11 years ago

    Hi — for those who find this post and might be looking for a way to send longer I2C that include restarts, I've written a tiny Linux library that allows you to send arbitrary sequences with restarts and reads, using the Bus Pirate convention/notation. See Lsquaredc (L²C) for details.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • shabaz
    shabaz over 11 years ago in reply to jrychter

    Hi Jan,

     

    The code above supports restarts too, I've been using this code for close to a year. Not sure what bus pirate convention is, but the code above (in my opinion) follows closely what the I2C bus is doing, in it's naming of functions and parameters, i.e. how chip manufacturers may specify behavior.

     

    Anyway, choice is good.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • jrychter
    jrychter over 11 years ago in reply to shabaz

    I'm sorry, I should have been clearer in my description. Your code is OK and works fine, as long as all you need is a single restart in a transaction.


    The main difference is that lsquaredc has a *single* API call to perform any kind of I2C sequence, including multiple writes, reads and restarts. Sequences are specified like this:


    {0x38, 0x16, I2C_RESTART, 0x39, I2C_READ, I2C_READ, I2C_READ};

     

    you then call i2c_send_sequence() providing a buffer that can store 3 bytes, and you get your data back. The sequence may include many restarts (up to 42).

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • Former Member
    Former Member over 11 years ago in reply to jrychter

    Any kind of I2C sequence?  Ok, I need to have a sequence length of 1, how do I do that with your code ?

     

    This is on real hardware where an I2C transaction needs to be exactly one byte on the wire.

     

    Ten bit addressing? PEC?  You seem to fall quite a way short of your 'any' claim.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • jrychter
    jrychter over 11 years ago in reply to Former Member

    Guys, chill down. I am not here to compete, and my code has a proud price tag of 0. If you like it, use it. If you don't, don't use it. I just thought it would be useful to people.

     

    I have better things to do than pursue arguments of this kind.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • Former Member
    Former Member over 11 years ago in reply to jrychter

    Nobody is arguing.  The choice you made of how to answer what should have been a straightforward question is perhaps more interesting than any real answer.

     

    FWIW, I'm unlikely to ever use either piece of code, neither meet my needs.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube