PMBus

PMBus 是I2C通用协议之一,可用于测量和控制设备,如电源、风扇等。

本文针对PMBus 在传输数据时,使用的两种线性数据格式,即:Linear-11 和 Linear-16,数据格式如何转换进行介绍。

LINEAR11 Format

通过官方文档解释,线性11格式的数据格式主要用于非输出电压,值 N 和 Y 形成一个 16 位值,通过总线发送

具体组成如下:

N代表2的多少次幂,一般为负数

Y则是传输数据的值乘以2的N次幂

注意点: N和Y都是补码

真实值X计算的公式是:

X = Y * 2^N

这里补充下原码、反码、补码的概念:
原码:原码是带符号位的,第1位为符号位,1表示负数,0表示正数
反码:正数的反码是其本身,负数的反码是在其原码基础上符号位不变其余个位数取反
补码:正数的补码是其本身,负数的补码是在其原码基础上符号位不变,其余个位数取反,再加1(反码+1)

举例:假如现在用N=-3,表示数据,传输电压数据为 X=12V,那么:
N的取值计算,(5位二进制数表示):
原码 -3 = 10011
反码 -3 = 11100
补码 -3 = 11101
那报文中高位为:01101,即0x1d。

Y 的取值计算:
Y=12(X) * 2^3=48
原码:48 = 00110000
反码:48 = 00110000
补码:48 = 00110000

转成16进制,故前面八位为:0xe8,后面四位为:0x30。

N 代表的用处:
这里的N代表数据的精度,比如N=0,表示数据精确到1,N=-1,表示数据精确到0.5,以此类推。

LINEAR16 Format

LINEAR16 格式用于输出电压,和linear11 类似,但是N 是来自 VOUT_MODE 参数的有符号5 位2的补码整数。

具体组成如下:

VOUT_MODE 命令组成

通过长城文档可以看出,VOUT_MODE 命令的格式为:mode +N。我们使用的linear模式,则5-7为都为0.

我研究驱动代码,在linux 中发现pmbus_core.c 中有如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
static int pmbus_identify_common(struct i2c_client *client,
struct pmbus_data *data, int page)
{
int vout_mode = -1;

if (pmbus_check_byte_register(client, page, PMBUS_VOUT_MODE))
vout_mode = _pmbus_read_byte_data(client, page,
PMBUS_VOUT_MODE);
if (vout_mode >= 0 && vout_mode != 0xff) {
/*
* Not all chips support the VOUT_MODE command,
* so a failure to read it is not an error.
*/
switch (vout_mode >> 5) {
case 0: /* linear mode */
if (data->info->format[PSC_VOLTAGE_OUT] != linear)
return -ENODEV;

data->exponent[page] = ((s8)(vout_mode << 3)) >> 3;
break;
case 1: /* VID mode */
if (data->info->format[PSC_VOLTAGE_OUT] != vid)
return -ENODEV;
break;
case 2: /* direct mode */
if (data->info->format[PSC_VOLTAGE_OUT] != direct)
return -ENODEV;
break;
default:
return -ENODEV;
}
}

pmbus_clear_fault_page(client, page);
return 0;
}

可以分析到pmbus在传输数据时,有三种mode,分别是linear,direct,vid,这里我们这里主要分析linear模式。

传输举例:假如现在用N=-4,表示数据,传输电压数据为 X=12V,那么:
N的取值计算,(5位二进制数表示):
原码 -4 = 10100
反码 -4 = 11011
补码 -4 = 11100

那vout_mod = 0001 1100 = 0x1c

Y 的取值计算:
Y=12(X) * 2^4=96
原码:96 = 1100000
反码:96 = 1100000
补码:96 = 1100000

转成16进制,故前面八位为:0x00,后面八位为:0x60。