i2c协议和SMBus协议

i2c协议

i2c协议操作时需要起始信号,在scl时钟线为高电平的时候SDA数据线上的数据有效,最后停止发送需要停止信号,如上图所示。

SMBus协议

SMBus 为系统和电源管理这样的任务提供了一条控制总线,使用 SMBus 的系统,设备之间发送和接收消息都是通过 SMBus,而不是使用单独的控制线,这样可以节省设备的管脚数。

i2c协议和SMBus的区别

SMBus 是基于I2C协议的,SMBus要求更严格,SMBus是I2C协议的子集。对于I2C协议,它只定义了怎么传输数据,但是并没有定义数据的格式,这完全由设备来定义。

SMBus协议定义的几种数据格式

在面对不同的情况使用不同的协议可以事半功倍,在平时运用也可以多加考虑

首先介绍一个底层的 I2C SMBus 访问函数,用于执行各种 SMBus 操作。如果操作成功,返回读取到的字节数据;如果失败,返回负数错误码

__s32 i2c_smbus_access(int file, char read_write, __u8 command,
		       int size, union i2c_smbus_data *data)
{
	struct i2c_smbus_ioctl_data args;
	__s32 err;

	args.read_write = read_write;
	args.command = command;
	args.size = size;
	args.data = data;

	err = ioctl(file, I2C_SMBUS, &args);
	if (err == -1)
		err = -errno;
	return err;
}

用来发送一位数据

R/W#本意是用来表示读或写,但是在 SMBus 里可 以用来表示其他含义。比如某些开关设备,可以根据这一位来决定是打开还是关闭

读取一个字节

__s32 i2c_smbus_read_byte(int file)
{
	union i2c_smbus_data data;
	int err;

	err = i2c_smbus_access(file, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data);
	if (err < 0)
		return err;

	return 0x0FF & data.byte;
}

发送一个字节

__s32 i2c_smbus_write_byte(int file, __u8 value)
{
	return i2c_smbus_access(file, I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
}

向 I2C 设备发送一个命令,然后读取一个字节的数据

先发出 Command Code(它一般表示芯片内部的寄存器地址),再读取一个字节的数据。

__s32 i2c_smbus_read_byte_data(int file, __u8 command)
{
	union i2c_smbus_data data;
	int err;

	err = i2c_smbus_access(file, I2C_SMBUS_READ, command, I2C_SMBUS_BYTE_DATA, &data);
	if (err < 0)
		return err;

	return 0x0FF & data.byte;
}

向 I2C 设备发送一个命令,然后读取两个字节的数据

先发出Command Code(它一般表示芯片内部的寄存器地址),再读取2个字节的数据。

__s32 i2c_smbus_read_word_data(int file, __u8 command)
{
	union i2c_smbus_data data;
	int err;

	err = i2c_smbus_access(file, I2C_SMBUS_READ, command, I2C_SMBUS_WORD_DATA, &data);
	if (err < 0)
		return err;

	return 0x0FFFF & data.word;
}

向 I2C 设备发送一个命令,然后发送一个字节的数据

先发出Command Code(它一般表示芯片内部的寄存器地址),再发出1个字节的数据。

__s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value)
{
	union i2c_smbus_data data;
	data.byte = value;
	return i2c_smbus_access(file, I2C_SMBUS_WRITE, command, I2C_SMBUS_BYTE_DATA, &data);
}

向 I2C 设备发送一个命令,然后发送两个字节的数据

先发出Command Code(它一般表示芯片内部的寄存器地址),再发出2个字节的数据。

__s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value)
{
	union i2c_smbus_data data;
	data.word = value;
	return i2c_smbus_access(file, I2C_SMBUS_WRITE, command, I2C_SMBUS_WORD_DATA, &data);
}

向 I2C 设备发送一个命令,然后发起读操作

在读之前需要先读取一个字节表示后续要读的字节数

__s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values)
{
	union i2c_smbus_data data;
	int i, err;

	err = i2c_smbus_access(file, I2C_SMBUS_READ, command, I2C_SMBUS_BLOCK_DATA, &data);
	if (err < 0)
		return err;

	for (i = 1; i <= data.block[0]; i++)
		values[i-1] = data.block[i];
	return data.block[0];
}

向 I2C 设备发送一个命令,然后发起写操作

在写之前需要先发送一个字节表示后续要写的字节数

__s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length,
				 const __u8 *values)
{
	union i2c_smbus_data data;
	int i;
	if (length > I2C_SMBUS_BLOCK_MAX)
		length = I2C_SMBUS_BLOCK_MAX;
	for (i = 1; i <= length; i++)
		data.block[i] = values[i-1];
	data.block[0] = length;
	return i2c_smbus_access(file, I2C_SMBUS_WRITE, command, I2C_SMBUS_BLOCK_DATA, &data);
}

向 I2C 设备发送一个命令,然后发起读操作

与上面的区别是直接进行读

__s32 i2c_smbus_read_i2c_block_data(int file, __u8 command, __u8 length,
				    __u8 *values)
{
	union i2c_smbus_data data;
	int i, err;

	if (length > I2C_SMBUS_BLOCK_MAX)
		length = I2C_SMBUS_BLOCK_MAX;
	data.block[0] = length;

	err = i2c_smbus_access(file, I2C_SMBUS_READ, command,
			       length == 32 ? I2C_SMBUS_I2C_BLOCK_BROKEN :
				I2C_SMBUS_I2C_BLOCK_DATA, &data);
	if (err < 0)
		return err;

	for (i = 1; i <= data.block[0]; i++)
		values[i-1] = data.block[i];
	return data.block[0];
}

向 I2C 设备发送一个命令,然后发起写操作

与上面的区别是直接写

__s32 i2c_smbus_write_i2c_block_data(int file, __u8 command, __u8 length,
				     const __u8 *values)
{
	union i2c_smbus_data data;
	int i;
	if (length > I2C_SMBUS_BLOCK_MAX)
		length = I2C_SMBUS_BLOCK_MAX;
	for (i = 1; i <= length; i++)
		data.block[i] = values[i-1];
	data.block[0] = length;
	return i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
				I2C_SMBUS_I2C_BLOCK_BROKEN, &data);
}

先向i2c写一块数据再向i2c读一块数据

__s32 i2c_smbus_block_process_call(int file, __u8 command, __u8 length,
				   __u8 *values)
{
	union i2c_smbus_data data;
	int i, err;

	if (length > I2C_SMBUS_BLOCK_MAX)
		length = I2C_SMBUS_BLOCK_MAX;
	for (i = 1; i <= length; i++)
		data.block[i] = values[i-1];
	data.block[0] = length;

	err = i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
			       I2C_SMBUS_BLOCK_PROC_CALL, &data);
	if (err < 0)
		return err;

	for (i = 1; i <= data.block[0]; i++)
		values[i-1] = data.block[i];
	return data.block[0];
}

以上代码来源于韦东山的教程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值