Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 你能拼凑以下线索来帮助我读取Winbond W83793芯片的温度吗?_C#_Open Source_Hardware_Monitoring_Bus - Fatal编程技术网

C# 你能拼凑以下线索来帮助我读取Winbond W83793芯片的温度吗?

C# 你能拼凑以下线索来帮助我读取Winbond W83793芯片的温度吗?,c#,open-source,hardware,monitoring,bus,C#,Open Source,Hardware,Monitoring,Bus,我正试图从我的超微型X7DWA主板上读取温度数据。问题是我没有任何低级编程经验,而且在线可用的文档似乎不足以解释如何访问温度 然而,在我研究这个问题的一个月里,我发现了一些可能是解决我的问题的关键的值和低级方法。我只是想知道如何使用它们来得到我想要的。这就是我向你们求助的地方,因为你们可能理解这些信息的含义,以及如何应用它们,不像我。我已经做了相当多的闲逛,导致了许多蓝屏和电脑重启。猜够了,我需要把这些线索拼凑起来。以下是我目前所知道的: 要从芯片读取数据,我需要访问SMBus,因为这是监控程序

我正试图从我的超微型X7DWA主板上读取温度数据。问题是我没有任何低级编程经验,而且在线可用的文档似乎不足以解释如何访问温度

然而,在我研究这个问题的一个月里,我发现了一些可能是解决我的问题的关键的值和低级方法。我只是想知道如何使用它们来得到我想要的。这就是我向你们求助的地方,因为你们可能理解这些信息的含义,以及如何应用它们,不像我。我已经做了相当多的闲逛,导致了许多蓝屏和电脑重启。猜够了,我需要把这些线索拼凑起来。以下是我目前所知道的:

  • 要从芯片读取数据,我需要访问SMBus,因为这是监控程序(如CPUID HWMonitor)获取信息的方式。据我所知,OpenHardwareMonitor中没有任何用于访问SMBus的代码,这就是它可能没有从芯片读取数据的原因。但是,OpenHardwareMonitor的its中包含以下方法,它使用这些方法访问来自其他芯片的信息。我可能能够利用这些方法为自己带来好处:

    void Ring0.WriteIOPort(uint port, byte value);
    byte Ring0.ReadIOPort(uint port);
    
  • 在其他信息中,HWMonitor在我保存报告时向我报告有关Winbond W83793芯片的以下信息:

    寄存器空间:SMBus,基址=0x01100

    SMBus请求:通道0x0,地址0x2F

    看起来这些都是重要的值,但我不知道它们的确切含义,以及如何将它们与上面的Ring0方法结合使用。隐马尔可夫模型。。。这么多线索。HWMonitor向我显示的其他值是实际电压、温度和风扇转速,以及表示芯片上某处数据的十六进制值数组,如果您想查看,我将在这里复制这些值

  • 最后,在W83793数据表的第53页(如果您打开了文档),以下是我希望阅读的十六进制温度地址(我相信):

    TD1读数-气缸组0地址1C

    TD2读数-气缸组0地址1D

    TD3读数-气缸组0地址1E

    TD4读数-气缸组0地址1F

    低位读出-气缸组0地址22

    TR1读数-气缸组0地址20

    TR2读数-气缸组0地址21

  • 到目前为止我只知道这些。OpenHardwareMonitor、W83793芯片和Ring0代码可通过上述链接获得。正如我之前所说,我已经做了一个月了,只是还没能解开这个谜。我希望你能帮助我。所有这些信息可能看起来有点吓人,但我相信对于一些有低级编程经验的人来说,这些信息是有意义的

    为了总结我的问题,请使用上面提供的线索,找出如何让OpenHardwareMonitor读取W83793芯片的温度。我不需要在OpenHardwareMonitor中创建芯片的详细信息。我已经准备好上课了。我只需要序列和格式来编写Ring0命令,如果这是我需要做的

    编辑:我找到了更多的信息。我从HWMonitor打印了一份SMBus设备报告,除此之外,我得到了这一行,包括在这里,因为它显示0x2F:

    SMB设备:I/O=0x1100,地址0x2F,通道=0


    这一定意味着我需要以某种方式将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) {}