【嵌入式5】电源相关芯片驱动

news2025/1/11 2:56:46

文章目录

  • 1.读MPS5023芯片:0x03ff即将前6位屏蔽
  • 2.读PXE1410CDM电压和电流:一个数&0x7ff,将这个数前5位全变为0,其余位不变
    • 2.1 1ine11:先看第15和10位,e9b6是上面读出的值
    • 2.2 1ine16:PMBUS协议16bit
      • 0x20读出0x14:0x14取反加1就是-12
      • 0x20读出0x17:0x17取反加1后,十进制和十六进制都为9
  • 3. xdpe12284c读电压:https://elixir.bootlin.com/linux/v5.19/source/drivers/hwmon/pmbus/pmbus_core.c#L699,ratio
  • 4.xdpe132g5c调压:
  • 5.读ADS7830的8个channel电压:P5V0即5.0V
  • 6.读INA220电压和电流:Read_INA220_Voltage_Current.sh


1.读MPS5023芯片:0x03ff即将前6位屏蔽

在这里插入图片描述

# Read_FPGA_Power.sh  
#!/bin/bash
stop_ipmistack()
{
    cnt=0
    while true
    do
        /etc/init.d/ipmistack stop >/dev/null  2>&1
        s1=$(ps aux)
        s2="/usr/local/bin/IPMIMain"
        result=$(echo $s1 | grep "${s2}")
        if [[ "$result" == "" ]]
        then
            break
        fi
        if [ $cnt -eq 5 ]
        then
           echo "Unable to stop ipmistack !"
           exit 1
        fi
        cnt=$(($cnt+1))
        sleep 10
    done
}

delete()
{
    cnt=0
    while true
    do
        echo 0x73 > /sys/bus/i2c/devices/i2c-7/delete_device #将bus7上0x73这设备删除
        if [ $? = 0 ]
        then
            break
        fi
        if [ $cnt -eq 5 ]
        then
          echo "Unable to delete device  !"
          exit 1
        fi
        cnt=$(($cnt+1))
    done
}

access()
{
    cnt=0
    while true
    do
        i2c-test -b 7 -s 0x73 -w -d 0x08 >/dev/null 2>&1
        if [ $? = 0 ]
        then
            break
        fi
        if [ $cnt -eq 5 ]
        then
          echo $cnt
          echo "Unable to access 9545 !"
          exit 1
        fi
        cnt=$(($cnt+1))
        echo $cnt
    done
}

OpenChannel()
{
    cnt=0
    while true
    do
        i2c-test -b 7 -s 0x71 -w -d 0x80 >/dev/null 2>&1   #0x80打开channel8
        if [ $? = 0 ]
        then
            break
        fi
        if [ $cnt -eq 5 ]
        then
          echo "Unable to access 9548 channel8 !"
          exit 1
        fi
        cnt=$(($cnt+1))
    done
}

read_voltage(){
    cnt=0
    while true
    do
        val_v=$(i2c-test -b 7 -s 0x40 -m 1 -rc 2 -d 0x8b)
        if [ $? = 0 ]
        then
        hexval_v_h=${val_v:14:2}
        hexval_v_l=${val_v:17:2}
        hexval_v=${hexval_v_l}${hexval_v_h}
        #echo $hexval_v  #0183

        dec_v=$((0x$hexval_v & 0x3ff))  #&:有0为0,3ff:10个1, hex->dec
        #echo $dec_v  #388
        dec_v_wv=$((dec_v*3125))  #31.25mV/LSB
        dec_v_v=$((dec_v_wv/100000))
        #echo $dec_v_v   #12
              break
        fi
        if [ $cnt -eq 5 ]
        then
          echo "Unable to read voltage !"
          exit 1
        fi
        cnt=$(($cnt+1))
    done
}

read_power(){
    cnt=0
    while true
    do
        val_a=$(i2c-test -b 7 -s 0x40 -m 1 -rc 2 -d 0x8c) #电流
        if [ $? = 0 ]
        then
        hexval_a_h=${val_a:14:2}
        hexval_a_l=${val_a:17:2}
        hexval_a=${hexval_a_l}${hexval_a_h}
        #echo $hexval_a  #0054

        dec_a=$((0x$hexval_a & 0x3ff))
        dec_a_wa=$((dec_a*6250))
        dec_a_a=$((dec_a_wa/100000))
		#echo $dec_a_a
        power=$(($dec_v_v * $dec_a_a))
        echo "FPGA Power : "$power"W"
              break
        fi
        if [ $cnt -eq 5 ]
        then
          echo "Unable to read electricity !"
          exit 1
        fi
        cnt=$(($cnt+1))
    done
}

start_ipmistack()
{
    cnt=0
    while true
    do
        /etc/init.d/ipmistack start >/dev/null 2>&1
        s1=$(ps aux)
        s2="/usr/local/bin/IPMIMain"
        result=$(echo $s1 | grep "${s2}")
        if [[ "$result" != "" ]]
        then
            break
        fi
        if [ $cnt -eq 5 ]
        then
          echo "Unable to start ipmistack !"
          exit 1
        fi
        cnt=$(($cnt+1))
		    sleep 10
    done
}

start_ipmistack
stop_ipmistack
delete
access
OpenChannel
read_voltage
read_power
start_ipmistack

在这里插入图片描述

2.读PXE1410CDM电压和电流:一个数&0x7ff,将这个数前5位全变为0,其余位不变

ipmitool raw 0x3a 0x10 <bus id> <slave addr> <Read count> <Data to write> (00:第一个状态码不显示)
在这里插入图片描述

status , log_psu1 = run_command("sudo bash -c 'a=$(ipmitool raw 0x3a 0x10 14 0xb0 2 0x88) ; b=${a:1:2} ; c=${a:4:5} ; d=${c}${b} ; \
    f=`../utility/diag-tools/pmbus_tool/line11 0x$d` ; echo $f'")  #psu1输入电压; 输出电压0x8b,line16
status , log_psu2 = run_command("sudo bash -c 'a=$(ipmitool raw 0x3a 0x10 15 0xb0 2 0x88) ; b=${a:1:2} ; c=${a:4:5} ; d=${c}${b} ; \
    f=`../utility/diag-tools/pmbus_tool/line11 0x$d` ; echo $f'")  #psu2输入电压; 输出电压0x8b,line16
输入电压(mv):
root@gnr5713bb:/var/log/abak# i2cget -f -y 15 0x60 0x88 w
0xe9b6
root@gnr5713bb:/var/log/abak# i2cget -f -y 15 0x61 0x88 w
0xe9b5
root@gnr5713bb:/var/log/abak# i2cget -f -y 15 0x62 0x88 w
0xe9b6
root@gnr5713bb:/var/log/abak# ./line11_arm 0xe9b6
54750

输出电压(mv):
root@gnr5713bb:/var/log/abak# i2cget -f -y 15 0x60 0x8b w
0xc2ad
root@gnr5713bb:/var/log/abak# i2cget -f -y 15 0x61 0x8b w
0xc395
root@gnr5713bb:/var/log/abak# i2cget -f -y 15 0x62 0x8b w
0xc0f8

【VOUT_MODE】:
root@gnr5713bb:/var/log/abak# i2cget -f -y 15 0x60 0x20
0x14
root@gnr5713bb:/var/log/abak# i2cget -f -y 15 0x61 0x20
0x14
root@gnr5713bb:/var/log/abak# i2cget -f -y 15 0x62 0x20
0x14

【输出电压(mv)】:
root@gnr5713bb:/var/log/abak# ./line16_arm 0xc2ad 0x14
12167
root@gnr5713bb:/var/log/abak# ./line16_arm 0xc395 0x14
12223
root@gnr5713bb:/var/log/abak# ./line16_arm 0xc0f8 0x14
12060

2.1 1ine11:先看第15和10位,e9b6是上面读出的值

在这里插入图片描述
如下计算机以补码形式存放负数,0010+1=0011(十进制3)。
在这里插入图片描述
438乘2的-3次方 = 54.8(V)。
在这里插入图片描述

// arm编译器arm-linux-gcc (不是x86的gcc)编译成linear11
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char ** argv)
{
    short exponent;
    int mantissa;
    int val_x;

    mantissa = ((signed short)((strtoul(argv[1],0,0) & 0x7ff) << 5)) >> 5;
    // printf("%x\n",mantissa);
    exponent = ((signed short)strtoul(argv[1],0,0))>>11;
    // printf("%d\n",exponent);
    val_x = mantissa * 1000L;  //v转为mv

    if (exponent >= 0)
        val_x <<= exponent;  // 左移:* 2的exponent次方
    else
        val_x >>= -exponent; // 右移:/ 2的exponent(正)次方  即 * 2的 - exponent(正)次方
   printf("%d\n",val_x);
   return 0;
}

在这里插入图片描述

2.2 1ine16:PMBUS协议16bit

0x20读出0x14:0x14取反加1就是-12

如下十六进制HEX为c2ad(上面读出的值) ,49837乘2的-12次方 = 12.1(A)。
在这里插入图片描述
在这里插入图片描述

0x20读出0x17:0x17取反加1后,十进制和十六进制都为9

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

// linear16
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char ** argv)
{
    short exponent;
    int mantissa;
    int val_x;

    mantissa = (signed short)strtoul(argv[1],0,0);
    exponent = ((signed short)(0x17 << 11)) >> 11 ;

    val_x = mantissa * 1000L;
    if (exponent >= 0)
        val_x <<= exponent;
    else
        val_x >>= -exponent;
   printf("%d\n",val_x);
   return 0;
}
linear16_convert()
{
    mantissa=$(printf %d "$1") # 有符号,也需像linear11_convert一样判断
    if [ $((($2 >> 4) & 0x1)) == 1 ] ; then
        exponent=$(((((($2 << 11)) >> 11)) & 0xf))
        exponent=$(($exponent ^ 0xf))
        exponent=$((~$exponent))
    else
        exponent=$(printf %d "$2")
    fi
    val_x=$((mantissa * 1000))
    if [ $exponent -ge 0 ]; then
        val_x=$(($val_x<<$exponent))
    else
        val_x=$(($val_x>>$((-$exponent))))
    fi
    echo $val_x
}

在这里插入图片描述
在这里插入图片描述

# Read_PXE1410CDM_0X62_Voltage_Current.sh
#!/bin/bash

write_ch0()
{
    cnt=0
    while true
    do
        i2c-test -b 7 -s 0x60 -w -d 0x0 0x00 >/dev/null 2>&1
        if [ $? = 0 ]
        then
            break
		    fi
        if [ $cnt -eq 5 ]
        then
          echo "Unable to write PXE CH0!"
          exit 1
        fi
        cnt=$(($cnt+1))
    done
}

read_ch0_voltage(){
    cnt=0
    while true
    do
        val_v_0=$(i2c-test -b 7 -s 0x60 -m 1 -rc 2 -d 0x8b)
        if [ $? = 0 ]
        then
        hex_v_h_0=${val_v_0:14:2}
        hex_v_l_0=${val_v_0:17:2}
        hex_v_0=${hex_v_l_0}${hex_v_h_0}
        dec_v_0=$((0x$hex_v_0 & 0xff))
        #echo $dec_v_0
        dec_v_0=$(((500 + (dec_v_0 - 1) * 10)/2))
        echo  "PXE_0x60_0_P0V9_VCCH Voltage : "$dec_v_0"mV"
              break
        fi
        if [ $cnt -eq 5 ]
        then
          echo "Unable to read ch0 voltage !"
          exit 1
        fi
        cnt=$(($cnt+1))
    done
}

read_ch0_current(){
    cnt=0
    while true
    do
        val_a_0=$(i2c-test -b 7 -s 0x60 -m 1 -rc 2 -d 0x8c)
        if [ $? = 0 ]
        then
        hex_a_h_0=${val_a_0:14:2}
        hex_a_l_0=${val_a_0:17:2}
        hex_a_0=${hex_a_l_0}${hex_a_h_0}
        dec_a_0=$(./linear11 0x$hex_a_0)
        echo  "PXE_0x60_0 Current : "$dec_a_0"mA"
              break
        fi
        if [ $cnt -eq 5 ]
        then
          echo "Unable to read ch0 current !"
          exit 1
        fi
        cnt=$(($cnt+1))
    done
}
start_ipmistack
stop_ipmistack
delete
access
OpenChannel
write_ch0
read_ch0_voltage
read_ch0_current
write_ch1
read_ch1_voltage
read_ch1_current
start_ipmistack

在这里插入图片描述

3. xdpe12284c读电压:https://elixir.bootlin.com/linux/v5.19/source/drivers/hwmon/pmbus/pmbus_core.c#L699,ratio

// linux-aspeed/drivers/hwmon/pmbus/xdpe12284.c
static int xdpe122_identify(struct i2c_client *client,
			    struct pmbus_driver_info *info)
{
	u8 vout_params;
	int i, ret;
	for (i = 0; i < XDPE122_PAGE_NUM; i++) {
		/* Read the register with VOUT scaling value.*/
		ret = pmbus_read_byte_data(client, i, PMBUS_VOUT_MODE); // PMBUS_VOUT_MODE=0x20 , ret=0x21(page01) , ret=0x23(page00默认)
		if (ret < 0)
			return ret;
		vout_params = ret & GENMASK(4, 0);  // 0010 0011  &  0001 1111 = 0000 0011 (0x03)
		switch (vout_params) {
		case XDPE122_PROT_VR12_5_10MV:  // 0x02
			info->vrm_version[i] = vr13;
			break;
		case XDPE122_PROT_VR12_5MV:  // 0x01
			info->vrm_version[i] = vr12;
			break;
		case XDPE122_PROT_IMVP9_10MV:  // 0x03 //
			info->vrm_version[i] = imvp9;
			break;
		case XDPE122_AMD_625MV:  // 0x10
			info->vrm_version[i] = amd625mv;
			break;
		default:
			return -EINVAL;
		}
	}
	return 0;
}

在这里插入图片描述

// linux-aspeed/drivers/hwmon/pmbus/pmbus_core.c
static long pmbus_reg2data_vid(struct pmbus_data *data,
			       struct pmbus_sensor *sensor)
{
	long val = sensor->data;
	long rv = 0;

	switch (data->info->vrm_version[sensor->page]) {
	case vr11:
		if (val >= 0x02 && val <= 0xb2)
			rv = DIV_ROUND_CLOSEST(160000 - (val - 2) * 625, 100);
		break;
	case vr12:
		if (val >= 0x01)
			rv = 250 + (val - 1) * 5;
		break;
	case vr13:
		if (val >= 0x01)
			rv = 500 + (val - 1) * 10;
		break;
	case imvp9:
		if (val >= 0x01)
			rv = 200 + (val - 1) * 10;  // val就是0x8b读出的值,10就是10mv步进
		break;
	case amd625mv:
		if (val >= 0x0 && val <= 0xd8)
			rv = DIV_ROUND_CLOSEST(155000 - val * 625, 100);
		break;
	}
	return rv;
}

4.xdpe132g5c调压:

如下在switch芯片手册中,查找到AVS值需要经过intel VR11.1协议进行转换。
在这里插入图片描述
如下在intel VRM11.1协议说明手册中通过Vcc_Max一列看出步长为6.25mv。Hex一列代表switch芯片传入basecpld的初始值,Hex为00的Vcc_Max的值为1.6+0.00625*2=1.6125(V),通过i2cget -f -y 0 0x0d 0x10从basecpld的10寄存器读取switch芯片传入的初始值为0x7a,所以Hex为7a的Vcc_Max值 = 1.6125 -(0.00625*122)= 0.85(V),所以0.85V为最终的XDPE132g芯片的调压显示结果值。
在这里插入图片描述
但是XDPE132g芯片内部有调压逻辑如下,所以不能将0.85直接设置进XDPE132g芯片寄存器中,厂商邮件如下:
在这里插入图片描述
通过i2cget -f -y 29 0x40 0x20命令读出XDPE132g芯片的20寄存器为0x14对应如上0.244mv step,上图第三步1000 (mv) / 1.953 = 512即0x0200(相当于3484),所以850 (mv) / 0.244 = 3484,将3484设置进21寄存器(需要先切换page),再通过8b寄存器读出对比设置进21寄存器的值是否一致。
在这里插入图片描述
关闭dcdc监控后,可以看出XDPE132g芯片的8b和21寄存器的值是一样的。
在这里插入图片描述

// cat /sys/bus/i2c/devices/i2c-29/29-0040/hwmon/hwmon20/in2_input节点后
// linux-aspeed/drivers/hwmon/pmbus/pmbus_core.c
static ssize_t pmbus_show_sensor(struct device *dev,
				 struct device_attribute *devattr, char *buf)
{
	struct pmbus_data *data = pmbus_update_device(dev);
	struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);

	if (sensor->data < 0)
		return sensor->data;
	if (sensor->data == 0xffff)
		return 0;
	printk(KERN_INFO "pmbus_show_sensor, %d, %d\n", sensor->data, pmbus_reg2data(data, sensor)); /// 3282, 801
	return snprintf(buf, PAGE_SIZE, "%ld\n", pmbus_reg2data(data, sensor));
}

static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
{
	long val;
	switch (data->info->format[sensor->class]) {
	case direct:
		val = pmbus_reg2data_direct(data, sensor);
		break;
	case vid:
		val = pmbus_reg2data_vid(data, sensor);
		break;
	case linear:
		printk(KERN_INFO "pmbus_reg2datalinear\n"); // 会打印出
	default:
		printk(KERN_INFO "pmbus_reg2datadefault, %d, %d\n", sensor->page, sensor->reg); // 0 , 139 (8b)
		val = pmbus_reg2data_linear(data, sensor);
		break;
	}
	return val;
}

static long pmbus_reg2data_linear(struct pmbus_data *data,
				  struct pmbus_sensor *sensor)
{
	s16 exponent;
	s32 mantissa;
	long val;
	printk(KERN_INFO "pmbus_reg2datad_data, %d\n", sensor->data);   // 3282
	if (sensor->class == PSC_VOLTAGE_OUT) {	/* LINEAR16 */
		exponent = data->exponent[sensor->page];
		mantissa = (u16) sensor->data;
	} else {				/* LINEAR11 */
		exponent = ((s16)sensor->data) >> 11;
		mantissa = ((s16)((sensor->data & 0x7ff) << 5)) >> 5;
	}

	val = mantissa;

	/* scale result to milli-units for all sensors except fans */
	if (sensor->class != PSC_FAN)
		val = val * 1000L;

	/* scale result to micro-units for power sensors */
	if (sensor->class == PSC_POWER)
		val = val * 1000L;

	if (exponent >= 0)
		val <<= exponent;
	else
		val >>= -exponent;
	printk(KERN_INFO "pmbus_reg2data_val, %d\n", val);   // 801
	return val;
}

5.读ADS7830的8个channel电压:P5V0即5.0V

在这里插入图片描述
如下CH0:1000 1100为六进制0x8c,十进制140。从SD=1往下看,SD=0不用看。CH1中C2 C1 C0为1 0 0即0xcc即204。
在这里插入图片描述
cmd | (((ch >> 1) | (ch & 0x01) << 2) << 4); cmd =0x8c。
在这里插入图片描述
如下CH7竖着多出了一条。
在这里插入图片描述
在这里插入图片描述
i2c-test -b 7 -s 0x48 -rc 1 -d 0x8c #显示0x57即十进制87。如下x=87*9766,divisor=1000。

#define DIV_ROUND_CLOSEST(x, divisor)({   //C文件                                                       
        typeof(x) __x = x;                                
        typeof(divisor) __d = divisor;                       
        (((typeof(x))-1) > 0 ||                               
         ((typeof(divisor))-1) > 0 ||                       
         (((__x) > 0) == ((__d) > 0))) ?                 
                (((__x) + ((__d) / 2)) / (__d)) :         
                (((__x) - ((__d) / 2)) / (__d));         
})
# Read_ADS7830_0x48_Voltage.sh
#!/bin/bash
DIV_ROUND_CLOSEST(){
    __x=$1
    __d=$2
    A=$(((__x) > 0))
    B=$(((__d) > 0))

    C=$(($__d>>1))
    C=$(($__x+$C))
    C=$(($C/$__d))
    
    D=$(($__d>>1))
    D=$(($__x+$D))
    D=$(($D/$__d))

    E=$(($A==$B))
    echo $(($E?$C:$D))
}

OpenChannel()
{
    cnt=0
    while true
    do
        i2c-test -b 7 -s 0x71 -w -d 0x04 >/dev/null 2>&1
        if [ $? = 0 ]
        then
            break
		    fi

        if [ $cnt -eq 5 ]
        then
          echo "Unable to access 9548 channel 3 !"
          exit 1
        fi
        cnt=$(($cnt+1))
    done
}

read_channel0(){
    cnt=0
    while true
    do
        val_0=$(i2c-test -b 7 -s 0x48 -rc 1 -d 0x8c)  # channel1 :不是0x8c,是0xcc(204).....
        if [ $? = 0 ]
        then
        #echo $val_0
        hex_0=${val_0:34:2}
        #echo $hex_0  #57

        dec_0=$((0x$hex_0 & 0xff)) #转为十进制
        #echo $dec_0   #87
        dec_v_0=$((dec_0*9766))
        dec_v_v_0=$(DIV_ROUND_CLOSEST $dec_v_0 1000)
        echo "ADS7830 CH0:PFM8_VCC Voltage : "$dec_v_v_0"mV"
              break
        fi

        if [ $cnt -eq 5 ]
        then
          echo "Unable to read channel0 voltage !"
          exit 1
        fi
        cnt=$(($cnt+1))
    done
}

read_channel7(){
    cnt=0
    while true
    do
        val_7=$(i2c-test -b 7 -s 0x48 -rc 1 -d 0xfc)
        if [ $? = 0 ]
        then
        #echo $val_7
        hex_7=${val_7:34:2}
        #echo $hex_7   #57

        dec_7=$((0x$hex_7 & 0xff))
        #echo $dec_7  #

        dec_v_7=$((dec_7*9766))
        dec_v_v_7=$(($(DIV_ROUND_CLOSEST $dec_v_7 1000)*2))  # 多出一条
        echo "ADS7830 CH7:P3V3_EARLY Voltage : "$dec_v_v_7"mV"
              break
        fi

        if [ $cnt -eq 5 ]
        then
          echo "Unable to read channel7 voltage !"
          exit 1
        fi
        cnt=$(($cnt+1))
    done
}

start_ipmistack
stop_ipmistack
delete
access
OpenChannel
read_channel0
...
read_channel7
start_ipmistack

在这里插入图片描述
在这里插入图片描述

# Read_ADS7830_0X49_Voltage.sh
#!/bin/bash

read_channel0(){
    cnt=0
    while true
    do
        val_0=$(i2c-test -b 7 -s 0x49 -rc 1 -d 0x8c)
        if [ $? = 0 ]
        then
        #echo $val_0

        hex_0=${val_0:34:2}
        #echo $hex_0  #57

        dec_0=$((0x$hex_0 & 0xff))
        #echo $dec_0   #87

        dec_v_0=$((dec_0*9766))
        dec_v_v_0=$(($(DIV_ROUND_CLOSEST $dec_v_0 1000)*2))
        echo "ADS7830 CH0:P2V5_VPP_CH01 Voltage : "$dec_v_v_0"mV"
              break
        fi

        if [ $cnt -eq 5 ]
        then
          echo "Unable to read channel0 voltage !"
          exit 1
        fi
        cnt=$(($cnt+1))
    done
}

read_channel6(){
    cnt=0
    while true
    do
        val_6=$(i2c-test -b 7 -s 0x49 -rc 1 -d 0xbc)
        if [ $? = 0 ]
        then
        #echo 6
        hex_6=${val_6:34:2}
        #echo $hex_6  #57

        dec_6=$((0x$hex_6 & 0xff))
        #echo $dec_6  #

        dec_v_6=$((dec_6*9766))
        dec_v_v_6=$(($(DIV_ROUND_CLOSEST $dec_v_6 1000)*349/100))
        echo "ADS7830 CH6:P5V0 Voltage : "$dec_v_v_6"mV"
              break
        fi

        if [ $cnt -eq 5 ]
        then
          echo "Unable to read channel6 voltage !"
          exit 1
        fi
        cnt=$(($cnt+1))
    done
}

read_channel7(){
    cnt=0
    while true
    do
        val_7=$(i2c-test -b 7 -s 0x49 -rc 1 -d 0xfc)
        if [ $? = 0 ]
        then
        #echo $val_7
        hex_7=${val_7:34:2}
        #echo $hex_7   #57

        dec_7=$((0x$hex_7 & 0xff))
        #echo $dec_7  #

        dec_v_7=$((dec_7*9766))
        dec_v_v_7=$(($(DIV_ROUND_CLOSEST $dec_v_7 1000)*57/10))
        echo "ADS7830 CH7:P12V Voltage : "$dec_v_v_7"mV"
              break
        fi

        if [ $cnt -eq 5 ]
        then
          echo "Unable to read channel7 voltage !"
          exit 1
        fi
        cnt=$(($cnt+1))
    done
}

start_ipmistack
stop_ipmistack
delete
access
OpenChannel
read_channel0
...
read_channel6
read_channel7
start_ipmistack

在这里插入图片描述

6.读INA220电压和电流:Read_INA220_Voltage_Current.sh

在这里插入图片描述

#!/bin/bash

delete()
{
    cnt=0
    while true
    do
        echo 0x73 > /sys/bus/i2c/devices/i2c-3/delete_device
        if [ $? = 0 ]
        then
            break
		    fi
        if [ $cnt -eq 5 ]
        then
          echo "Unable to delete device  !"
          exit 1
        fi
        cnt=$(($cnt+1))
    done
}

OpenChannel()
{
    cnt=0
    while true
    do
        i2c-test -b 3 -s 0x71 -w -d 0x02 >/dev/null 2>&1
        if [ $? = 0 ]
        then
            break
		    fi
        if [ $cnt -eq 5 ]
        then
          echo "Unable to access 9548 channel2 !"
          exit 1
        fi
        cnt=$(($cnt+1))
    done
}

read_voltage(){
    cnt=0
    while true
    do
        val_v=$(i2c-test -b 3 -s 0x41 -m 1 -rc 2 -d 0x02)
        if [ $? = 0 ]
        then
        #echo $val_v  #08 aa
        hexval_v_h=${val_v:14:2}
        hexval_v_l=${val_v:17:2}
        hexval_v=${hexval_v_h}${hexval_v_l}
        dec_v_v=$((0x$hexval_v>>3))
        dec_v_v=$(($dec_v_v<<2))
        echo "INA220 Voltage : "$dec_v_v"mV"
              break
        fi
        if [ $cnt -eq 5 ]
        then
          echo "Unable to read INA220 voltage !"
          exit 1
        fi
        cnt=$(($cnt+1))
    done
}

DIV_ROUND_CLOSEST(){
    if [ $# -ne 2 ]
    then
    echo 0
    else
    __x=$1
    __d=$2
    A=$(((__x) > 0))
    B=$(((__d) > 0))
    C=$(($__d>>1))
    C=$(($__x+$C))
    C=$(($C/$__d))
    D=$(($__d>>1))
    D=$(($__x+$D))
    D=$(($D/$__d))
    E=$(($A==$B))
    echo $(($E?$C:$D))
    fi
}

Read_Reg()
{
    val=$(i2c-test -b 3 -s 0x41 -m 1 -rc 2 -d $1)
    val_h=${val:14:2}
    val_l=${val:17:2}
    val=${val_h}${val_l}
    echo $val
}

start_ipmistack()
{
    cnt=0
    while true
    do
        /etc/init.d/ipmistack start >/dev/null 2>&1
        s1=$(ps aux)
        s2="/usr/local/bin/IPMIMain"
        result=$(echo $s1 | grep "${s2}")
        if [[ "$result" != "" ]]
        then
            break
        fi
        if [ $cnt -eq 5 ]
        then
          echo "Unable to start ipmistack !"
          exit 1
        fi
        cnt=$(($cnt+1))
		    sleep 10
    done
}

start_ipmistack
stop_ipmistack
delete
access
OpenChannel
read_voltage

i2c-test -b 3 -s 0x41 -w -d 0x05 0x03 0x7f >/dev/null 2>&1  #0x37f上面的校正值
config_shunt_div=100
dividend=$(DIV_ROUND_CLOSEST 1000000000 $config_shunt_div)
shunt_val=$(Read_Reg 0x01)

current_lsb_uA=$(DIV_ROUND_CLOSEST $dividend 0x$shunt_val)
current_val=$(Read_Reg 0x04)
ret=$((0x$current_val * $current_lsb_uA))
ret=$(DIV_ROUND_CLOSEST $ret 1000)
echo "INA220 Current : "$ret"mA"
start_ipmistack

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/685651.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

产品的0到1概念篇

一、产品是什么&#xff1f; 产品是指被人们使用和消费&#xff0c;并能满足人们某种需求的任何东西&#xff0c;包括有形的物品、无形的服务、组织、观念或它们的组合。 产品本质是什么&#xff0c;产品的本质就是解决⽤户的痛点/满⾜⽤户的需求&#xff0c;这种满⾜的需求&…

KingbaseES的学习心得和知识总结(二)|Kingbase数据库闪回功能及插件kdb_flashback的使用

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、KingbaseES V8产品文档首页&#xff0c;点击前往 2、Kingbase 文档库&#xff0c;点击前往 3、北京人大金仓信息技术股份有限公司 官网首页&#xff0c;点击前往…

详解服务器端渲染 页面(SSR)

&#x1f48c;目录 &#x1f525;先了解服务器端渲染 (SSR)&#xff1f;&#x1f525;服务器端渲染的优点是什么呢&#xff1f;&#x1f525;有优点就有缺点&#xff1f;&#x1f525;根据Express来简单的建立一个服务端渲染 &#x1f525;先了解服务器端渲染 (SSR)&#xff1f…

Qt6.2教程——7.QT常用控件QTextEdit

一&#xff0c;QTextEdit简介 QTextEdit 是 Qt 的一个用于编辑和显示纯文本和富文本的控件。它是功能强大且高度灵活的&#xff0c;可以用于实现多种任务&#xff0c;如文本编辑&#xff0c;数据表示&#xff0c;以及HTML的显示和编辑等。QTextEdit 支持富文本功能&#xff0c…

Over 函数的使用

序言 其实也很少使用这个Over函数,毕竟mysql在5.7版本之前都是不支持的,但是over()的窗口概念被Flink中的窗口中借鉴了. 所以了解下,网上的Over()的使用有在Mysql中的例子,但是我的Mysql5.7 不支持,所以在Oracle中实验.但是语法都是一样的.cuiyaonan2000163.com 众所周知如果S…

转战VUE3学习

安装好vue3后&#xff0c;开始新的项目吧&#xff01; npm init vuelatest1.组合式API 在以前vue2的项目里&#xff0c;使用的选项式API将各种不同逻辑的代码分散到像data、methods等不同的对象里。如果想看某一方面的逻辑&#xff0c;鼠标滚轮都要磨出火星了&#xff01; 而…

LLM的工程实践思考

陆奇博士的主题演讲《新范式 新时代 新机会》非常震撼人心。我远程参加了深圳站和北京站两场演讲&#xff0c;深受感触。虽然了解大模型的机制和原理以了解新的范式非常重要&#xff0c;但是“行胜于言”&#xff0c;基于大模型的众多应用都需要工程技术才能落地。然而&#xf…

Ndk c++层 crash问题分析

首先你要从设备上拿到墓碑文件&#xff1a;tombstone&#xff0c;这里面会记录系统崩溃时的信息。位置在/data/tombstones目录下&#xff08;Logcat中也会有相应的信息&#xff09;&#xff0c;文件的确就像墓碑一样记录了死亡了的进程的基本信息&#xff08;例如进程的进程号&…

FlashAttention和PagedAttention

FlashAttention FlashAttention一般指的是FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness这篇&#xff0c;当然Transformer Quality in Linear Time这篇里非要说FLASH Fast Linear Attention with a Single Head&#xff0c;命名有点无语&…

JavaScript数据存储方式

内置对象 js内部提供的对象&#xff0c;包含各种属性和方法给开发者调用 document.write() console.log() Math Math对象是js提供的一个 “数学”对象&#xff0c;提供了一系列做数学运算的方法 max找最大值Math.max(3,8,5,4) 返回8min找最小值Math.min(3,8,5,4) 返回4ab…

printf不一样的玩法

Printf不一样的玩法 ❝ 在使用linux终端命令的时候&#xff0c;我们可以看到像more命令&#xff0c;它的显示方式与一般的字符串不同&#xff0c;是用了反显。同样&#xff0c;linux C下printf还有很多其他不常见的格式化输出形式。本文主要为你盘点这些形式。 ❞ 先看下效果&a…

MySQL:单行函数(全面详解)

MySQL&#xff1a;单行函数 前言一、函数的理解1、什么是函数2、不同DBMS函数的差异3、MySQL的内置函数及分类 二、数值函数1、基本函数2、角度与弧度互换函数3、三角函数4、指数与对数5、进制间的转换 三、字符串函数四、日期和时间函数1、获取日期、时间2、日期与时间戳的转换…

Bpmn.js流程建模结合业务整合工作流(二)

上一篇文章讲述了bpmn.js的基本搭建使用过程,下面介绍工具栏的按钮使用 以及右侧属性如何绑定到节点保存的 保存方法 /** 保存xml */async save() {await this.getNewXML() //获取最新的xmlawait this.getRootElement() //获取流程基本信息 节点信息const params = {name: th…

SSM+校园网上订餐系统 毕业设计-附源码211510

校园网上订餐系统的设计与实现 摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对校园网上订…

API 接口协作,swagger不再是第一选择了

目录 一、前言 1.1. 场景一、后端视角&#xff1a; 1.2. 场景二、前端视角&#xff1a; 1.3. 场景三、测试视角&#xff1a; 二、Apifox 2.1 场景一、后端视角&#xff1a; 漂亮的接口文档 2.2 场景二、前端视角&#xff1a; 2.3 场景三、测试视角&#xff1a; 三、总…

SOAP教程

参考 SOAP 教程 1、介绍 SOAP 中文解释为&#xff1a;简单对象访问协议。 SOAP 是一种简单的基于 XML 的协议&#xff0c;它使应用程序通过 HTTP 来交换信息。 SOAP 是基于 XML 的简易协议&#xff0c;可使应用程序在 HTTP 之上进行信息交换。或者更简单地说&#xff1a;SOAP…

ASP.NET Core Web API之Token验证

在实际开发中&#xff0c;我们经常需要对外提供接口以便客户获取数据&#xff0c;由于数据属于私密信息&#xff0c;并不能随意供其他人访问&#xff0c;所以就需要验证客户身份。那么如何才能验证客户的身份呢&#xff1f;今天以一个简单的小例子&#xff0c;简述ASP.NET Core…

一、枚举类型——使用枚举类型分发

如果将 RoShamBo1.java 直接转换为基于枚举的实现版本&#xff0c;则会出现问题。因为枚举实例并不是类型&#xff0c;所以无法重载 eval() 方法&#xff0c;你无法将枚举实例作为参数类型。不过&#xff0c;还有别的方法可以利用枚举来实现多路分发。 一种方法是通过构造方法…

实战:SonarQube平台安装配置-2023.6.24(安装成功)(docker方式)

实战&#xff1a;SonarQube平台安装配置-2023.6.24(安装成功)(docker方式) 目录 推荐文章 https://www.yuque.com/xyy-onlyone/aevhhf?# 《玩转Typora》 实验环境 sonarqube:9.9.0-community (docker方式部署) SonarScanner 4.8.0.2856 (部署在宿主机上)实验软件 链接&…

开关电源-PFC驱动电路的工作原理

PFC驱动电路的工作原理 由于PFC的控制地和MOS管组成的双向开关的源极不共地&#xff0c;因此需要解决开关管浮地驱动问题。 图2 驱动电路图 电路图说明&#xff1a; PFCPWM是DSP的PWM信号&#xff1b;VCC_4V和AGND是DSP侧的电源和控制地&#xff1b;Vccp_14V和AGND_DRV是MO…