c - AVR-C : USB connection can be detected successfully, 不是 USB 断开连接

标签 c connection usb avr cpu-registers

它在 ATMega32U4 MCU 上运行良好,但是......当电池供电时,它无法检测到与 USB 的断开连接。它可以检测到重新连接 (false),然后是 true 状态,但不会断开连接。

例如:

bool TEnjoyPad::isUSBConnected()
{
#if defined(UDADDR) && defined(_BV) && defined(ADDEN)

  //setDelay( 1000 );
  Serial1.println( "--------" );
  Serial1.println( UDADDR & _BV(ADDEN), HEX );
  //Serial1.println( UDADDR, HEX );     // 97 or 98 hex
  //Serial1.println( _BV(ADDEN), HEX ); 

  return (UDADDR & _BV(ADDEN));
#else
  return false;
#endif
} 

当您查看该行时:

Serial1.println( UDADDR & _BV(ADDEN), HEX );

它打印:

Connected: 0x80 (function result = true)
Not connected: 0x00 (function result = false)

它可以检测从未连接到已连接但未连接到未连接(断开连接)的变化。

有没有简单的解决办法?


2017 年 13 月编辑:

只需弄清楚这一点,它就可以工作,但并非总是如此。在这里找到它: http://forum.arduino.cc/index.php?topic=28567.0

UDINT 寄存器,连接时报告 16 十进制(0x10 十六进制)。

上面这个函数的第一个版本的修改版本:

bool TEnjoyPad::isUSBConnected()
{
#if defined(UDADDR) && defined(_BV) && defined(ADDEN) && defined(UDINT) && defined(USBCON) 
  return ( (UDADDR & _BV(ADDEN)) && (UDINT) );
#else
  return false;
#endif
}

但只有在满足这些条件时才有效:

- Device is connected to computer, phone etc
- Device is disconnected from computer, phone etc

例如,如果您使用 USB 电池组,它会报告 true,并且对于某些电池组,在断开连接时状态仍然为 true。总线困惑?当您再次连接到计算机、电话等时,它会先报告错误,然后再报告正确,当断开连接时,它会报告错误(这是应该的)。

有什么想法吗?和构造USB数据线有关系吗?

在示例中,他们使用了这一行。当我添加它时,它对我没有影响:

USBCON = USBCON | B00010000;

2017 年 10 月 14 日编辑:

感谢@ralph htp,请参阅下面我发布的答案,也许它也可以帮助其他人。

最佳答案

最后,感谢“@ralf htp”,它可以完美运行。他是对的,USBSTA 寄存器在连接到 USB 时更改为 1,在未连接时更改为 0。您必须 include pins_arduino.h 否则寄存器是未知的。因此,这使得检测 USB 电源状态变得非常容易。

但是,当你想知道USB总线的状态、数据线是否连接、连接是否建立时,就有点复杂了。当 MCU 需要作为 USB HID 设备运行时,您需要知道建立 USB 连接。


我不知道这是一个错误还是 USB 的工作方式,即使设备断开连接或连接到 USB 电池组,MCU 也会保留 USB 设备的地址。一些寄存器甚至在“无效”状态下仍保持其值。

但是,当建立连接时,地址会发生变化。因此可以确定存在真正的连接,建立连接,MCU 被 USB 主机识别。


在我的以下代码中,我可以检测到:

  • 它已连接到外部 USB 电源;
  • 数据连接建立,设备是否被识别;
  • 结合这些因素,很容易弄清楚它是如何供电和/或连接的。

现在您可以决定设备功能是否可用,或者向用户报告设备的状态。


我更新后的代码是这样的:

// enjoypad.h
#include <pins_arduino.h> // Required to access some register defines
..........
..........
..........

 // Via pins_arduino.h => defined in avr/iom32u4.h
#ifdef USBSTA
 #define TEP_USB_VBUS_CONNECTED    (USBSTA == 3) 
 #define TEP_USB_VBUS_DISCONNECTED (USBSTA == 2) 
#endif

#ifdef UDADDR
 #define TEP_USB_ADDRESS (isOnUSBPower()?UDADDR:0)
#endif

#if defined(ADDEN) && defined(UDINT)   
 #define TEP_USB_ADDRESS_ESTABLISHED (_BV(ADDEN)== 0x80 && UDINT > 0 )
#endif

..........
..........
..........

// enjoypad.cpp

uint8_t TEnjoyPad::getUSBaddress()
{ 
  #ifdef TEP_USB_ADDRESS
   return TEP_USB_ADDRESS; 
  #else 
   return 0;
  #endif 
}

bool TEnjoyPad::isOnUSBPower()
{
  #ifdef TEP_USB_VBUS_CONNECTED   
    return TEP_USB_VBUS_CONNECTED;
  #else 
   return false;
  #endif 
}

bool TEnjoyPad::isUSBDataEstablished()
{
 #ifdef TEP_USB_ADDRESS_ESTABLISHED
  static uint8_t iLastAddress = 0;
  static uint8_t bUSBDataEstablished = false;

  // The address changes from 0 to something (byte) or increases 
  // with one each time you plugin the device, when this is an USB host. 
  // If the VBUS not connected, it returns always 0 (zero) 
  uint8_t iAddress = getUSBaddress();
  if( iAddress > 0 ) 
  {
    //Serial1.println( _BV(ADDEN), HEX );
    //Serial1.println( UDINT, HEX );

    if( TEP_USB_ADDRESS_ESTABLISHED )
    {
      //Serial1.println( iAddress );
      // Need update? On USB Battery for example, address stays the same
      // so it never perform an update and never reports there is a 
      // data connection established.
      if( iAddress != iLastAddress )
      {
        bUSBDataEstablished = true;
        iLastAddress = iAddress;
      }
    }  
  }
  else { bUSBDataEstablished = false; }

  return bUSBDataEstablished; 
 #else
  return false;
 #endif
}

bool TEnjoyPad::isOnUSBPowerBattery() // Or something else providing power
{ return ( isOnUSBPower() && !isUSBDataEstablished() ); }

bool TEnjoyPad::isOnBatteryPower()
{ return !isOnUSBPower(); }

实际代码 :-) :

Code in action

关于c - AVR-C : USB connection can be detected successfully, 不是 USB 断开连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46730468/

相关文章:

javascript - PHP从textarea读取文本,使用convert_uuencode并将其写入另一个textarea

c++ - 如何判断数组100的个数不相等

带有自定义证书的 Android https 连接

windows - Windows 下优盘和优盘的区别

c - 我怎样才能阻塞线程直到找到素数,解除阻塞,然后让它们等到下一个素数?

c - 从 "char"到 "char *"的转换无效

android - 无法更新 Android Development Toolkit 中的加载项

mysql - 127.0.0.1 :3306 with user root access denied for user 'root' @'localhost' (using password:YES) 连接mysql失败

java - 通过 USB 从 Android 发送简单命令

linux - 如何在 Linux 设备驱动程序中从 usb 端点接收连续数据