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

时间:2017-10-13 12:56:03

标签: c connection usb avr cpu-registers

它在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)

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

这有一个简单的解决方案吗?

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

有什么想法吗?是否与构造USB数据线有关?

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

USBCON = USBCON | B00010000;

编辑14 okt 2017:

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

2 个答案:

答案 0 :(得分:1)

最后,由于&#34; @ralf htp&#34;它完美无瑕。当连接到USB时,USBSTA寄存器更改为1,而未连接时0更改为include pins_arduino.h。你必须// 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(); } ,否则寄存器是未知的。因此,这使得检测USB电源状态非常容易。

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

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

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

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

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

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

我续订的代码如下:

function genPDF_fromUrl(link) {
    var doc = new jsPDF();
    doc.setFontSize(40);
    doc.text(80, 25, 'MAP001');

    const rtnimg = compute(doc, link);
    console.log(rtnimg)
    Promise.all(rtnimg).then((success) => {
        doc.save("map.pdf");
    });
    console.log("Finish hello PDF!")
}
function compute(doc, link) {       
    return link.map(l => {
        let x = 0;
        let y = 0;
        x += 10;
        y += 10;
        return new Promise((resolve, reject) => {
            var genImg = new Image();
            genImg.setAttribute('crossOrigin', 'anonymous');
            genImg.src = l;
            console.log("genimg: ", genImg);

            genImg.onload = function () {   
            console.log("doc: ", doc);  
                doc.addImage(genImg, 'PNG',  x, y, 100, 100);    
            }
            resolve();
        });
    });
}

行动中的代码:-):

Code in action

答案 1 :(得分:0)

数据表第261页和第279页中的

表示USB插入有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)。 1.4 V)