Difference between revisions of "Beaglebone black i2c"
From Teknologisk videncenter
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: | + | [[Category:Beagleboard Black]][[Category:I2C]][[Category:Linux]] |
Latest revision as of 15: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
- Implementing I2C device drivers in userspace (From kernel.org)
- i2c dev-interface (Must read i2c or SM-bus)
- Implementing I2C device drivers