This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TPS63811EVM:错误(?) 使用 Arduino Wire 库读取寄存器值-寄存器读取值始终为'0'-但寄存器写入正常

Guru**** 2379100 points
Other Parts Discussed in Thread: TPS63811, TPS63811EVM, TPS63810, USB2ANY, TPS63810EVM
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/power-management-group/power-management/f/power-management-forum/1359758/tps63811evm-error-reading-register-values-with-arduino-wire-library---register-read-value-is-always-0---but-register-writes-work-fine

器件型号:TPS63811EVM
主题中讨论的其他器件: TPS63810USB2ANYTPS63810EVM、TPS63811

我使用的是带有 TPS63811EVM 模块的 Arduino MEGA2560_R3、通过 I2C (线库)进行通信。  我可以写入器件寄存器、但读取寄存器值时似乎遇到错误。  即使无法读回寄存器值、我也可以确认寄存器写入有效、因为在寄存器写入后输出会按预期变化。  我的简化版 Arduino sketch 展示了问题:

//电路板跳线:VSEL 引脚跳线选择 VOUT1寄存器、EN 跳线将 EN_PIN 设置为 ON
//位于 SDA、SCL I2C 线路上的外部10k 上拉电阻器
//我在代码注释中添加了一些说明。 希望有人能帮我解决问题。

#include <Wire.h>

#define ADDR 0x75     // TPS63811 I2C address
#define CONTROL 0x01  // TPS63811 control register address
#define VOUT1 0x04              // VOUT1 register address
#define VOUT1_RESET 0b0111100   // VOUT1 default bits

/***** using *****
 *  
 * Arduino MEGA2560_R3
 * Wire library (I2C)
 * TI TPS63811EVM
 * 
 */

void setup()
{
  int val;
  uint8_t result = 0x4A;

  /* I am using external 10k resistors */
  pinMode(7, OUTPUT);         // SDA pull-up resistor
  pinMode(8, OUTPUT);         // SCL pull-up resistor
  pinMode(10, OUTPUT);        // TPS63811 VIN

  /* all 5V */
  digitalWrite(10, HIGH);     // power on TPS63811
  digitalWrite(7, HIGH);
  digitalWrite(8, HIGH);

  /***** board jumper settings *****
   * VSEL jumper is set to select VOUT1
   * EN jumper is in the ON position
   */

  Serial.begin(115200);
  delay(1000);

  Wire.begin();
  Wire.setClock(100000);
  delay(1000);

  /* set CONTROL register bits, set RANGE bit prior to setting ENABLE bit (required) */
  Wire.beginTransmission(ADDR);
  Wire.write(CONTROL);          // select control register
  Wire.write(0x4A);             // 0b1001010, 0x4A - sets range bit, fpwm, slew == 5V/ms
  val = Wire.endTransmission();
  if (val != 0)
  {
    Serial.println("error writing initial control register value");
  }

  /* set VOUT to desired voltage */
  Wire.beginTransmission(ADDR);
  Wire.write(VOUT1);
  Wire.write(0x64);         // should yield ~ 4.5V with the RANGE bit set
  // Wire.write(0x77);      // 0b1110111, 0x77 - will yield 5.0V when RANGE bit set
  val = Wire.endTransmission();
  if (val != 0)
  {
    Serial.println("error writing to vout1 register");
  }

  /* set ENABLE bit in CONTROL register - enables the converter */
  Wire.beginTransmission(ADDR);
  Wire.write(CONTROL);
  Wire.write(0x6A);         // 0b1101010, 0x6A - sets range, enable, fpwm and slew bits (converter gets enabled)
  val = Wire.endTransmission();
  if (val != 0)
  {
    Serial.println("error setting enable bit in control register");
  }
  else
  {
    Serial.println("output converter enabled for 10 seconds");
    delay(10000);                   // load (LED+resistor) connected to VOUT/GND - LED illuminates properly for 10 seconds
    Wire.beginTransmission(ADDR);
    Wire.write(CONTROL);
    Wire.write(0x4A);               // clears the enable bit, disabling the converter
    val = Wire.endTransmission();   // LED goes dark as it should
    Serial.println("converter disabled");
  }

  /* Everything above works.  I have confirmed 4.5V output if I write 0x64 to VOUT1 register.
   * I have confirmed 5.0V if I write 0x77 to VOUT1 register.  Converter is enabled/disabled as expected
   * when setting/clearing the ENABLE bit in the CONTROL register...
    
   * but when I try reading any register value I always get '0' - doesn't matter which register I select,
   * they all return 0.  I have tried all sorts of things but I can't get it to work.
   * 
   * I read this in the TPS6381x datasheet (section 8.5.2) - 
   * "Attempting to read data from register addresses not listed in this section results in 00h being read out."
   * 
   * that would explain my problem excecpt that I have checked all my addresses repeatedly (to the point of absurdity)
   * and they are all correct.
   */

  /***** this read fails - I don't know why *****/
  Wire.beginTransmission(ADDR);
  Wire.write(VOUT1);          // select VOUT1 register
  Wire.endTransmission();
  Wire.requestFrom(ADDR, 1);
  if (Wire.available() == 1)    // I get one byte of data as I should
  {
    result = Wire.read();
  }
  Serial.print("result:  ");
  Serial.println(result);     // but that byte is always is 0
  Wire.end();
}

void loop()
{
  Serial.print(".");
  delay(1000);
}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Brian、您好!

    我以前没有遇到类似的问题、您能否尝试使用 TPS63810的 GUI 并看看会发生什么情况? 链接。

    www.ti.com/.../TPS63811

    BRS

    TAO

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Tao、

    我没有 USB2ANY 适配器、因此无法尝试 GUI 软件。  我只需使用 J3接头上的引脚9和10作为 I2C 与我的 Arduino。

    我确实使用了 TPS63810EVM (双电压-不可编程)、并想尝试一下。  63810不像63811那样可编程、但我在不更改代码的情况下将其连接到 Arduino。  63810的寄存器写入失败(这是预期结果)、但我在 VOUT1 = 0x4A 上获得成功的寄存器读取

    *edit -我的示例 sketch 中的错误最初指定 result = 0x4A、但应该为 result = 0。

    请参阅随附的带有注释的屏幕截图。  我首先在63811上运行 sketch、其中您可以看到"0"返回、然后在63810上看到74 (0x4A)。  我连续运行它们、因此结果位于相同的串行输出窗口中。  当我有更多的时间但现在我不得不问-我可能有一个坏的63811EVM 吗?

    呃…… 我无法显示屏幕截图、因此我将手动键入输出-

    输出转换器启用10秒
    转换器禁用
    结果:0                                                     <--这是 TPS63811
    …………
    写入初始控制寄存器值时出错
    写入 Vout1寄存器时出错
    设置控制寄存器中的 ENABLE 位时出错
    结果:74                                                      <--这是 TPS63810、74 =0x4A ==0b1001010

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

     Brian、您好!

    很抱歉、我不能向您提供有关此案例的有用建议。

    您可能能够更改 SDA 和 SCL 的波形、以查看您这边发生了什么。

    此致

    TAO

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    首先、我需要澄清的是、我说 TPS63810寄存器读取正在工作、这是错误的。  63810或63811模块的寄存器读取均不起作用。

    不过、寄存器写入确实适用于 TPS63811EVM。  我捕获了 TPS63811EVM 的一些波形。  第一个附件显示了一个更大的图。  下面的捕获图已经过缩放、特别着重于在尝试读取之前 SDA 线降到-2.0V (是的、负的)。  在图中:

    SCL—黄色

    SDA -紫色

    且电压范围为~ 0-5V。

    不确定为什么会出现急剧的负电压尖峰。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    嗨、 Brain、

    很好听到。

    对于尖峰、这取决于您的实际系统、例如 SDA 电缆中的大寄生电感器或者不适合您的测试系统的设置。 但是、我们可以非常肯定、这种尖峰的根本原因不是器件本身。

    此致

    TAO

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    TAO、

    好的、我为 I2C 连接了一个逻辑电平转换器(bob12009)、尽管这并不是绝对必要、但我将10k 电阻器互换为8.2k、并在软 Arduino 复位而不是初始上电时触发。  似乎尖峰主要是由于 Arduino 启动后立即触发。  我修改了 Arduino sketch、更加详细、添加了一些缺失的返回值检查、并将启用 Vout 的持续时间削减为5ms、以便我能够在单个屏幕上捕获整个 sketch 执行情况。

    一切都正常运行、但如果在执行结束时读取 VOUT1寄存器、我仍然得到0作为返回值。  它应该是可读的、对吧?  我仍然不明白为什么我会得到0。

    显示的波形:

    1.全部执行

    2.工作寄存器写入(早期)

    3.禁用 Vout (清除启用位)、选择 VOUT、请求从、检查可用、读取

    4.读取 VOUT 导致0

    5. Arduino 串行监视器输出(显示没有错误的功能返回)

    有什么想法吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Brian、您好!

    Vout1应可读、正确。

    您是否有可能将输出电压控制寄存器设置为 VOUT2?

    此致

    TAO

                                          

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Tao、

    我进行了检查、设置是否正确。  正如我在上面提到的、我不仅无法读取 VOUT1、还无法读取任何寄存器。  我添加了一个简单函数循环遍历寄存器、您可以看到每个都返回读取值0。

    修正后的代码

    #include <Wire.h>
    
    #define ADDR 0x75     // TPS63811 I2C address
    #define CONTROL 0x01  // TPS63811 control register address
    #define STATUS 0x02   // TPS63811 status register address
    #define DEVID 0x03    // device ID register address
    #define VOUT1 0x04              // VOUT1 register address
    #define VOUT2 0x05              // VOUT2 register address
    #define VOUT1_RESET 0b0111100   // VOUT1 default bits
    #define VOUT2_RESET 0b1000010   // VOUT2 default bits
    #define SDA 20    // data line
    #define SCL 21    // clock
    
    #define DEBUG
    
    int val;
    uint8_t result = 0xFF;
    
    void wire_read(uint8_t reg)
    {
      result = 0xFF;    // reset to error value
      Wire.beginTransmission(ADDR);
      Serial.print("select register ");
      Serial.println(reg, HEX);
      Wire.write(reg);              // select register
      val = Wire.endTransmission();
      Serial.print("val: ");
      Serial.println(val);
      if (val != 0)
      {
        Serial.print("error selecting register ");
        Serial.println(reg, HEX);
      }
      else
      {
        Serial.print("success selecting register ");
        Serial.println(reg, HEX);
        val = Wire.requestFrom(ADDR, 1);
        Serial.print("requestFrom bytes: ");
        Serial.println(val);
        if (Wire.available() == 1)
        {
          result = Wire.read();
        }
      }
      Serial.print("result: ");
      Serial.println(result, HEX);
    }
    
    void setup()
    {
      // int val;
      // uint8_t result = 0xFF;
    
      pinMode(7, OUTPUT);
      digitalWrite(7, HIGH);
      pinMode(8, OUTPUT);
      digitalWrite(8, HIGH);
    
      pinMode(10, OUTPUT);
      digitalWrite(10, HIGH);   // power on TPS63811
      Serial.begin(115200);
      delay(1000);
    
      Wire.begin();
      delay(1000);
      Wire.setClock(100000);
      delay(1000);
    
    #ifdef DEBUG
    wire_read(CONTROL);
    wire_read(STATUS);
    wire_read(DEVID);
    wire_read(VOUT1);
    wire_read(VOUT2);
    #endif
    
    ... (rest of code omitted)

    串行输出

    我现在都不知道该怎么说了

    感谢您的所有帮助。

    此致、

    Brian

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Brian、您好!

    我真的很想帮助你,但这个问题是我的技能。  我确信、我们没有读问题。

    抱歉。

    此致

    TAO

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    TAO、

    我理解。  感谢您努力帮助解决此问题。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

     Brian、您好!

    感谢您的理解、这很好。 希望您能尽快找出根本原因。

    此致

    TAO

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    TAO、

    这种行为是否可能是内部损坏引起的?  我问,因为当在我的63810模块上运行一个常见的 I2C 扫描器(我稍微修改了一下),我甚至不能得到一个 ACK。  不过会找到我的63811EVM。  除了板之外、我不会更改任何其他内容。  很可能我很早就弄乱了我的线路、把3.3V 放在它不应该的地方。

    tps63810

    TPS63810

    tps63811

    63811.

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Brian、您好!

    您可以将 EVM 发送给我吗? 然后、我可以检查器件是否有问题。

    大多数情况下、我认为器件内部没有损坏。

    此致

    TAO

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是的,我给你发送了一个 dm 询问哪里发送。

    谢谢!

    Brian

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

     Brian、您好!

    请检查您的 PM、我发送了您的地址信息。 THX。

    此致

    TAO

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Tao、

    在连接了 TPS63810的情况下进行扫描时、我可以获得一个 ACK (有关下面的更多内容) 、因此我要推迟发送电路板、因为问题似乎不是 EVM、而是我的设置中出现了一些严重的恶意行为。  我倾向于认为电路板的测试良好。

    我想提一下是什么阻止了 I2C 扫描仪找到我的 TPS63810、I2C 似乎完全不能使用、以防其他人发现该问题。  最初、我将 SDA 和 SCL 上拉电阻器连接到 Arduino 引脚7和8、将引脚模式设置为输出并将引脚驱动为高电平-我确实在它们上测量了5V。  但是、使用此配置时、I2C 扫描无法找到 TPS63810。  将上拉电阻连接到专用5V Arduino 引脚、而我得到了 ACK。  奇怪的是、TPS63811将在引脚7和8上连接上拉电阻进行 ACK。  我不知道这是不是由噪声/EMI 造成(引脚7和8为数字/PWM)、但由于它们为高电平、它们真的不应该被削波。

    我仍然只得到寄存器读取返回0、但我认为最好暂时关闭此讨论、因为我相信您是正确的、问题出在我的最后  如果我发现问题、我将继续调试并报告。

    谢谢!

    Brian

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

     Brian、您好!

    感谢您的理解、希望您能快速找出根本原因。

    是的、因为我无法为您的问题提供帮助、让我们关闭此主题。

    此致

    TAO

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我今天早些时候再次讨论了这一点、并最终成功读取了寄存器。  如果我在读取前使用"endTransmission (false)"、则会起作用。  endTransmission ()参数默认为 true。  将参数假信号设置为不会生成停止条件。  仅在读取时才需要设置参数 false。  我不确定这是否为预期行为、但它在工作... 最后:)

    最新代码片段和屏幕截图如下。  *注意-我禁用了 Arduino 内部上拉,但有适当的外部上拉。

    #include <Wire.h>
    
    const uint8_t ADDR = 0x75;      // TPS6381x I2C address
    const uint8_t CONTROL = 0x01;   // TPS63811 control register address
    const uint8_t STATUS = 0x02;    // TPS63811 status register address
    const uint8_t DEVID = 0x03;     // device ID register address
    const uint8_t VOUT1 = 0x04;     // VOUT1 register address
    const uint8_t VOUT2 = 0x05;     // VOUT2 register address
    
    const uint8_t VOUT1_RESET = 0b0111100;    // VOUT1 default bits
    const uint8_t VOUT2_RESET = 0b1000010;    // VOUT2 default bits
    const uint8_t REG[6] = {0x01, 0x02, 0x03, 0x04, 0x05, '\0'};
    
    #define SDA 20
    #define SCL 21
    #define DEBUG
    
    uint8_t wire_read(uint8_t reg)
    {
      int val = 0xFF;
      uint8_t result = 0xFF;          // set to error value
    
      Wire.beginTransmission(ADDR);
      Serial.print("select register ");
      Serial.println(reg);
      Wire.write(reg);								// select register
      val = Wire.endTransmission(false);			// don't generate a STOP condition - this works :)
      Serial.print("val: ");
      Serial.println(val);
      if (val != 0)
      {
        Serial.print("error selecting register ");
        Serial.println(reg);
      }
      else
      {
        Serial.print("success selecting register ");
        Serial.println(reg);
        val = Wire.requestFrom(117, 1);         // 0x75, 117
        Serial.print("requestFrom bytes: ");
        Serial.println(val);
        if (Wire.available() == 1)
        {
          result = Wire.read();
        }
      }
      return result;
    }
    
    void setup()
    {
      int val = 0xFF;
      uint8_t result = 0xFF;
    
      //pinMode(7, OUTPUT);
      //digitalWrite(7, HIGH);
    
      Serial.begin(115200);
      delay(1000);
      Wire.begin();
      delay(1000);
      digitalWrite(SDA, 0);
      digitalWrite(SCL, 0);
    
    #ifdef DEBUG
      for (int i=0; i<6; i++)
      {
        Serial.println();
        result = wire_read(REG[i]);
        delay(500);
        Serial.print("result: ");
        Serial.println(result);
      }
    #endif
    
    rest of code omitted...

    感谢 Tao 的所有帮助。  你对我很有耐心并且乐于助人/支持。  我非常感谢-谢谢。

    此致、

    Brian

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

      Brian、您好!

    不要观看调试 过程、我真的希望我能为您提供一些有用的建议。 不幸的是,这是 我的技能,我只被迫在硬件上。

    感谢您的出色工作、祝一切顺利。

    此致

    TAO