最近需要操作24C02,封裝了一下函數方便以后操作。
參考鏈接:
https://my.oschina.net/handawei/blog/68526
http://blog.csdn.net/onetwothreef/article/details/49488443
源碼:
#include <stdio.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#define I2C_DEFAULT_TIMEOUT 1
#define I2C_DEFAULT_RETRY 3
/*
* fd : 文件描述符
* timeout : 發送超時時間
* retry : 重復發送次數
*/
//重復發送次數可以設多一點,在調試的時候,只設置了一次,導致有時候發送會失敗。
int i2c_set(int fd, unsigned int timeout, unsigned int retry)
{
if (fd == 0 )
return -1;
if (ioctl(fd, I2C_TIMEOUT, timeout ? timeout : I2C_DEFAULT_TIMEOUT) < 0)
return -1;
if (ioctl(fd, I2C_RETRIES, retry ? retry : I2C_DEFAULT_RETRY) < 0)
return -1;
return 0;
}
/*
* fd : 文件描述符
* addr : i2c的設備地址
* reg : 寄存器地址
* val : 要寫的數據
* 描述 :從指定地址寫數據
*/
int i2c_byte_write(int fd, unsigned char addr, unsigned char reg, unsigned char val)
{
int ret = 0;
unsigned char outbuf[2];
struct i2c_rdwr_ioctl_data packets;
struct i2c_msg messages;
packets.nmsgs = 1;
packets.msgs = &messages;
//發送要讀取的寄存器地址
messages.addr = addr;
messages.flags = 0;
messages.len = 2; //寄存器地址加數據,共發送2個字節
messages.buf = outbuf;
outbuf[0] = reg;
outbuf[1] = val;
ret = ioctl(fd, I2C_RDWR, (unsigned long)&packets); //讀出來
if (ret < 0)
ret = -1;
return ret;
}
/*
* fd : 文件描述符
* addr : i2c的設備地址
* reg : 寄存器地址
* val : 要寫的數據
* len : 數據長度
* 描述 :從指定地址寫數據
* 24c02以8字節為1個page,如果在一個page里面寫,寫的字節長度超過這個page的末尾,
* 就會從page的開頭寫,覆蓋開頭的內容
*/
int i2c_nbytes_write(int fd, unsigned char addr, unsigned char reg, unsigned char *val, int len)
{
int ret = 0;
struct i2c_rdwr_ioctl_data packets;
struct i2c_msg messages;
int i;
packets.nmsgs = 1;
packets.msgs = &messages;
//發送要讀取的寄存器地址
messages.addr = addr;
messages.flags = 0; //write
messages.len = len + 1; //數據長度
//發送數據
messages.buf = (unsigned char *)malloc(len+1);
if (NULL == messages.buf)
{
ret = -1;
goto err;
}
messages.buf[0] = reg;
for (i = 0; i < len; i++)
{
messages.buf[1+i] = val[i];
}
ret = ioctl(fd, I2C_RDWR, (unsigned long)&packets);//讀出來
if (ret < 0){
printf("write error!\n");
return -1;
}
err:
free(messages.buf);
return ret;
}
/*
* fd : 文件描述符
* addr : i2c的設備地址
* val : 保存讀取數據
* 描述 :從當前地址讀取一個字節數據
*/
int i2c_byte_read(int fd, unsigned char addr, unsigned char *val)
{
int ret = 0;
struct i2c_rdwr_ioctl_data packets;
struct i2c_msg messages;
packets.nmsgs = 1; //數據幀類型只有一種,讀操作,只需要發送一個起始信號,因此是1
packets.msgs = &messages;
//發送要讀取的寄存器地址
messages.addr = addr; //i2c設備地址
messages.flags = I2C_M_RD; //讀操作
messages.len = 1; //數據長度
messages.buf = val; //讀取的數據保存在val
ret = ioctl (fd, I2C_RDWR, (unsigned long)&packets); //發送數據幀
if (ret < 0)
ret = -1;
return ret;
}
/*
* fd : 文件描述符
* addr : i2c的設備地址
* reg : 寄存器地址
* val : 保存讀取的數據
* len : 讀取數據的長度
* 描述 :讀取達到eeprom的末尾時,會讀取最開頭的字節
*/
int i2c_nbytes_read(int fd, unsigned char addr, unsigned char reg, unsigned char *val, int len)
{
int ret = 0;
unsigned char outbuf;
struct i2c_rdwr_ioctl_data packets;
struct i2c_msg messages[2];
/* 數據幀類型有2種
* 寫要發送起始信號,進行寫寄存器操作,再發送起始信號,進行讀操作,
* 有2個起始信號,因此需要分開來操作。
*/
packets.nmsgs = 2;
//發送要讀取的寄存器地址
messages[0].addr = addr;
messages[0].flags = 0; //write
messages[0].len = 1; //數據長度
messages[0].buf = &outbuf; //發送寄存器地址
outbuf = reg;
//讀取數據
messages[1].len = len; //讀取數據長度
messages[1].addr = addr; //設備地址
messages[1].flags = I2C_M_RD; //read
messages[1].buf = val;
packets.msgs = messages;
ret = ioctl(fd, I2C_RDWR, (unsigned long)&packets); //發送i2c,進行讀取操作
if (ret < 0)
ret = -1;
return ret;
}
Tony Liu
2016-9-23, Shenzhen