【问题标题】:AVR-C: USB connection can be detected successfully, not an USB disconnectAVR-C:可以成功检测到 USB 连接,而不是 USB 断开连接
【发布时间】:2017-10-13 12:56:02
【问题描述】:

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

例如:

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 hex)。

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

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 年 14 月编辑:

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

【问题讨论】:

    标签: c connection usb avr cpu-registers


    【解决方案1】:

    最后,感谢“@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(); }
    

    实际代码:-) :

    【讨论】:

      【解决方案2】:

      在数据表的第 261 页和第 279 页中说有VBUSTI 中断用于 USB 插入和移除。 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(电压总线)垫。其状态可以在VBUS 位/标志的USBSTA(USB 状态)中访问,这在第 268 页的数据表中。

      为此捕获VBUSTI 中断,并在发生中断时检查USBSTA 寄存器中的VBUS 位/标志。如果VBUS 高 (1) 电池已连接(VBUS 焊盘上的电压 > 1.4 V,数据表第 265 页)如果电池低,则未连接电池(VBUS 焊盘上的电压

      【讨论】:

      • 嗨,感谢您的回答,但链接不起作用:404 他发生以下错误:在此服务器上找不到请求的 URL。请查看网址或联系站长。
      • 谢谢,我看了一下,但没有找到解决方案,至少对我来说不是。另请参阅我对我的问题的编辑。
      • 感谢 talf htp 帮助我,另请参阅我的回答。竖起大拇指!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-30
      相关资源
      最近更新 更多