C# 你能拼凑以下线索来帮助我读取Winbond W83793芯片的温度吗?
我正试图从我的超微型X7DWA主板上读取温度数据。问题是我没有任何低级编程经验,而且在线可用的文档似乎不足以解释如何访问温度 然而,在我研究这个问题的一个月里,我发现了一些可能是解决我的问题的关键的值和低级方法。我只是想知道如何使用它们来得到我想要的。这就是我向你们求助的地方,因为你们可能理解这些信息的含义,以及如何应用它们,不像我。我已经做了相当多的闲逛,导致了许多蓝屏和电脑重启。猜够了,我需要把这些线索拼凑起来。以下是我目前所知道的:C# 你能拼凑以下线索来帮助我读取Winbond W83793芯片的温度吗?,c#,open-source,hardware,monitoring,bus,C#,Open Source,Hardware,Monitoring,Bus,我正试图从我的超微型X7DWA主板上读取温度数据。问题是我没有任何低级编程经验,而且在线可用的文档似乎不足以解释如何访问温度 然而,在我研究这个问题的一个月里,我发现了一些可能是解决我的问题的关键的值和低级方法。我只是想知道如何使用它们来得到我想要的。这就是我向你们求助的地方,因为你们可能理解这些信息的含义,以及如何应用它们,不像我。我已经做了相当多的闲逛,导致了许多蓝屏和电脑重启。猜够了,我需要把这些线索拼凑起来。以下是我目前所知道的: 要从芯片读取数据,我需要访问SMBus,因为这是监控程序
void Ring0.WriteIOPort(uint port, byte value);
byte Ring0.ReadIOPort(uint port);
这一定意味着我需要以某种方式将I/O地址与芯片地址结合起来,芯片地址似乎是0x2F。我试着把它们加在一起,但是我得到的所有温度读数都是255,所以这不是正确的猜测。IO方法是您需要的。在x86硬件上,实际上有两个地址池,而不是一个。其中一个用于存储,在读取指令时被芯片引用,并且有数千种有用且方便的访问方法。另一个用于寻址外部芯片,读写操作非常有限且相对较慢。您确定的方法允许您访问第二个区域 由于要读取的寄存器位于第0列,因此首先需要在芯片上选择第0列,如第12页所示。根据第8.1.2.1节中的图表,您需要将0x80写入地址00。根据您的报告,芯片的基址为0x01100,这意味着通过
WriteIOPort
将0x80写入0x01100
然后,您可能应该能够通过ReadIOPort
从0x01100+0x1c、0x01100+0x1d等读取所需的值
我还没有时间完全消化您链接到的文档,但这些都是合理的猜测。有些芯片有一个稍微复杂一点的过程,你必须写一个值,然后确认结果,但我在文档中没有看到类似的内容。您还需要警惕多任务处理-如果您的代码在设置组0和读取相关寄存器之间被中断,则中间的某些进程可能会设置其他组,从而导致您读取的值为任意其他值。我假设OpenHardwareMonitor有某种机制来处理这个问题,但如果您尝试快速的纯用户空间实现,偶尔会得到奇怪的结果,那么值得记住。最后,OpenHardwareMonitor的作者好心地帮了我一把,现在我可以从芯片中读取温度。虽然这个问题的整个解决方案有点复杂,我仍然无法理解,但对于任何感兴趣的人来说,下面是使用Ring0类进行的基本阅读和写作。请注意,这是特定于我的机器和芯片。对于您来说,基址和从属地址可能不同,但您可以通过打印报告使用CPUID HWMonitor找到它们 首先,这里是使用的常量:
private const int BASE_ADDRESS = 0x1100;
private const uint SLAVE_ADDRESS = 0X2F; // as we figured out already
private const byte HOST_STAT_REG = 0; // host status register
private const byte HOST_BUSY = 1;
private const byte HOST_CTRL_REG = 2; // host control register
private const byte HOST_CMD_REG = 3; // host command register
private const byte T_SLAVE_ADR_REG = 4; // transmit slave address register
private const byte HOST_DATA_0_REG = 5;
private const byte BYTE_DATA_COMM = 0x08; // byte data command
private const byte START_COMM = 0x40; // start command
private const byte READ = 1;
private const byte WRITE = 0;
接下来,这里是基本的c
// first wait until ready
byte status;
do
{
status = Ring0.ReadIoPort(BASE_ADDRESS + HOST_STAT_REG);
} while ((status & HOST_BUSY) > 0);
if ((status & 0x1E) != 0)
{
Ring0.WriteIoPort(BASE_ADDRESS + HOST_STAT_REG, status);
}
// now get the value
Ring0.WriteIoPort(BASE_ADDRESS + HOST_DATA_0_REG, 0);
Ring0.WriteIoPort(BASE_ADDRESS + HOST_COMM_REG, theRegister)
Ring0.WriteIoPort(BASE_ADDRESS + T_SLAVE_ADR_REG,
(byte)((SLAVE_ADDRESS << 1) | READ));
Ring0.WriteIoPort(BASE_ADDRESS + HOST_CTRL_REG,
START_COMM | BYTE_DATA_COMM);
Ring0.ReadIoPort(BASE_ADDRESS + HOST_DATA_0_REGISTER); // this returns the value
// now wait for it to end
while ((Ring0.ReadIoPort(BASE_ADDRESS + HOST_STAT_REG) & HOST_BUSY) > 0) {}