AVR-C:可以成功检测到USB连接,而不是USB断开连接

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AVR-C:可以成功检测到USB连接,而不是USB断开连接相关的知识,希望对你有一定的参考价值。

它可以在ATMega32U4 MCU上正常工作......但是当电池供电时,它无法检测到与USB的断开连接。它可以检测到重新连接(false),然后是真正的状态,但没有断开连接。

例如:

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年10月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 batterypack,它会报告为true,并且对于某些batterypack,断开状态时状态仍为真。公交车很困惑?再次连接到计算机,电话等时,它报告为false然后为true,断开连接时报告为false(应该如此)。

有任何想法吗?与构建USB数据线有什么关系?

在示例中,他们使用此行。当我添加它时,它对我没有任何影响:

USBCON = USBCON | B00010000;

编辑2017年10月14日:

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

答案

最后,由于“@ralf htp”,它完美无瑕。当连接到USB和USBSTA没有连接时,他是正确的1寄存器更改为0。你必须include pins_arduino.h否则寄存器是未知的。因此,这使得检测USB电源状态变得非常容易。

但是,当您想知道USB总线的状态,数据线已连接,建立连接时,它会更复杂一些。当MCU需要作为USB HID设备运行时,您需要知道建立了USB连接。


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

但是,建立连接时地址会更改。因此可以确定存在真正的连接,建立连接,USB主机识别MCU。


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

  • 它连接到外部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

另一答案

在数据表的第261和279页说,有插入一个VBUSTI中断插入删除。 LUFA堆栈中有一个实现(如果在主机模式下则为EVENT_USB_Host_DeviceUnattached(),如果在设备模式下则为EVENT_USB_Device_Disconnect()

源代码也在http://caves.org/section/commelect/DUSI/openmag/src/myusb/MyUSB/MyUSB/Drivers/USB/HighLevel/USBInterrupt.h

编辑

仅在USB设备模式下有效:

如果您想检测是否安装或拆卸了像电池组这样的纯电压源,您可以使用VBUS(电压总线)焊盘。其状态可以在USBSTA位/标志的VBUS(USB状态)中访问,这在第268页的数据表中。

这样做可以捕获VBUSTI中断,每当中断发生时,检查VBUS寄存器中的USBSTA位/标志。如果VBUS很高(1)电池连接(VBUS焊盘上的电压> 1.4 V,数据表第265页)如果电池电量不足(VBUS焊盘上的电压<1.4 V)

以上是关于AVR-C:可以成功检测到USB连接,而不是USB断开连接的主要内容,如果未能解决你的问题,请参考以下文章

Chrome 32 上的本机 USB 调试未检测到设备

如何使用C#查找通过USB电缆连接的相机,这样我便可以复制存储的图像

检测连接的 USB 设备

linux环境usb hub 下连接usb口和sd读卡器,sd卡热插拔的问题?

安卓手机跟电脑连接,用哪个软件好,搜索不到?

在 C# 中查找有关通过 USB 连接的所有串行设备的信息