2017-10-13 328 views
1

它在ATMega32U4 MCU上工作正常,但是.....当电池供电时,它无法检测到与USB断开连接。它可以检测到重新连接(false),并在此之后成为真实状态,但不会断开连接。AVR-C:可以成功检测到USB连接,而不是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) 

它可以探测到这一变化,从没有连接到连接但未连接到未连接(断开连接)。

有没有简单的解决方案呢?


编辑13十月2017年:

只是弄清楚这一点,它的工作原理却并非总是如此。在这里找到它: 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蓄电池组,它会报告真实的,有些电池组断开时,状态仍然为真。公交车很困惑?当你再次连接到计算机,电话等时,它报告错误,然后是真实的,当断开连接时,它报告错误(它应该)。

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

在这个例子中,他们使用这一行。它不会有所作为,我当我说的:

USBCON = USBCON | B00010000; 

编辑14十月2017年:

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

回答

1

最后,它作品完美无瑕,感谢“@ralf htp”。他正确USBSTA寄存器更改为1连接到USB和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

0

在第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(电压总线)焊盘。其状态可以在USBSTA(USB状态)在VBUS位/标志进行访问,这是第268

做到这一点渔获VBUSTI中断,每当发生中断检查VBUS位/对数据表国旗在USBSTA注册。如果VBUS为高(1)的电池附接(在VBUS焊盘电压是> 1.4 V,数据表页面265),如果它是低电池未连接(上VBUS焊盘电压是< 1.4V)

+0

海,感谢您的答案,但没有按链接” t工作:404他发生以下错误: 未找到请求的URL o在这台服务器上。 请检查网址或与网站管理员联系。 – Codebeat

+1

固定链接和LUFA堆栈在设备和主机模式下有不同的功能... –

+0

谢谢,我看看它,但没有导致解决方案,至少不适合我。另请参阅我在我的问题编辑。 – Codebeat