上一篇文章介绍了在Linux用户空间使用outb接口,直接访问Superio芯片,操作GPIO寄存器的教程,这次继续利用Superio读取CPU风扇转速。
CPU风扇属于环境控制器(EC),内置在IT8786E-I中,包括五个电压输入,三个温度传感器输入,五个FAN转速计输入和五组先进的风扇控制器。 EC监控硬件环境,实现个人电脑的环境控制。
先查看芯片手册找到EC控制器接口总线地址
大致流程
- 进入MB PnP 模式(87h, 01h, 55h, 55h;)
- 使能 EC(LDN=04h, Index 30h=01)
- 获取EC Base Address
基地址由逻辑设备寄存器确定(index=60h, 61h)
数据端口(Base+05h);数据端口(Base+06h) - 配置风扇转速寄存器(index=0Ch,default=00h)
- 计算出风扇转速(index=0Dh,18h)
CPU风扇转速计算公式如下:
代码如下:
#include<stdio.h>
#include<sys/io.h>
#include<unistd.h>
#include<math.h>
#define REG 0x2e
#define VAL 0x2f
#define CHIPID 0x20
#define CHIPREV 0x22
static int superio_inw(int reg)
{
int val;
outb(reg++, REG);
val = inb(VAL) << 8;
outb(reg, REG);
val |= inb(VAL);
return val;
}
static void init_ec()
{
//Enter MB PnP Mode
outb(0x87, REG);
outb(0x01, REG);
outb(0x55, REG);
outb(0x55, REG);
//使能EC控制器
outb(0x07, REG);
outb(0x04, VAL);
outb(0x30,REG);
outb(0x01,VAL);
}
int main()
{
unsigned int ec_base,addr_port,data_port,fan_speed,fan_rpm;
int ret = iopl(3);
if(ret == -1)
{
printf("iopl error.\n");
return -1;
}
//初始化
init_ec();
//获取EC控制器基地址
ec_base = superio_inw(0x60);
printf("ec_base addr:0x%x\n", ec_base);
addr_port = ec_base+0x05;
data_port = ec_base+0x06;
printf("addr_port is 0x%x data_port is 0x%x\n",addr_port,data_port);
//配置风扇转速计控制寄存器
outb(0x0c, addr_port);
outb(0x00, data_port);
//一起有三组,这里使用的第一组,也就是CPU_FAN
//1:CPU_FAN 2:SYS_FAN 3:PWR_FAN
//1-3 Reading Registers[7:0] (Index=0Dh-0Fh)
outb(0x0d,addr_port);
int lval = inb(data_port);
//1-3 Extended Reading Registers [15:8] (Index=18h-1Ah)
outb(0x18,addr_port);
int mval = inb(data_port);
//每转的内部时钟计数,这里是16位
fan_speed = (mval<<8) | lval;
printf("mval:%02x lval:%02x fan_speed is %d\n",mval, lval, fan_speed);
//最后根据芯片手册的公式计算出风扇转速
fan_rpm = 1.35*pow(10,6)/(fan_speed*2);
printf("fan_rpm is %d\n",fan_rpm);
//读取tmp1温度寄存器
outb(0x29, addr_port);
float tmpin1 = inb(data_port);
printf("tmpin1 is %.1f °C\n",tmpin1);
//Exit MB PnP Mode
outb(0x02, REG);
outb(0x02, VAL);
iopl(0);
return 0;
}
能不能写个windows下C语言的代码