You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于LUFA的AT90USB162 USB字节接收问题:输出无限FF

问题:LUFA虚拟串口回显时无限输出FF字符

我基于LUFA的VirtualSerial示例(路径/Demos/Device/ClassDriver/VirtualSerial/)修改了代码,移除了摇杆、LED相关冗余代码,只保留核心虚拟串口功能。现在微控制器能被电脑识别,串口终端可以显示“Byte received: ”,但配置回显发送字符时,即使没有发送字符,终端也会无限输出FF。

问题代码

#include "VirtualSerial.h"

USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface =
    {
        .Config =
            {
                .ControlInterfaceNumber   = INTERFACE_ID_CDC_CCI,
                .DataINEndpoint           =
                    {
                        .Address          = CDC_TX_EPADDR,
                        .Size             = CDC_TXRX_EPSIZE,
                        .Banks            = 1,
                    },
                .DataOUTEndpoint =
                    {
                        .Address          = CDC_RX_EPADDR,
                        .Size             = CDC_TXRX_EPSIZE,
                        .Banks            = 1,
                    },
                .NotificationEndpoint =
                    {
                        .Address          = CDC_NOTIFICATION_EPADDR,
                        .Size             = CDC_NOTIFICATION_EPSIZE,
                        .Banks            = 1,
                    },
            },
    };

/** Standard file stream for the CDC interface when set up, so that the virtual CDC COM port can be
 *  used like any regular character stream in the C APIs.
 */
static FILE USBSerialStream;


int main(void)
{
    SetupHardware();

    /* Create a regular character stream for the interface so that it can be used with the stdio.h functions */
    CDC_Device_CreateStream(&VirtualSerial_CDC_Interface, &USBSerialStream);

    GlobalInterruptEnable();

    for (;;)
    {

        /* Must throw away unused bytes from the host, or it will lock up while waiting for the device */
        CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
        char echo = 0;
        echo = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
        if(echo)
        {
            fprintf(&USBSerialStream, "Byte received: %c\n\r", echo);
        }

        CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
        USB_USBTask();
        
        // fputs("hello\n\r", &USBSerialStream);
    }
}

/** Configures the board hardware and chip peripherals for the demo's functionality. */
void SetupHardware(void)
{
#if (ARCH == ARCH_AVR8)
    /* Disable watchdog if enabled by bootloader/fuses */
    MCUSR &= ~(1 << WDRF);
    wdt_disable();

    /* Disable clock division */
    clock_prescale_set(clock_div_1);
#endif

    /* Hardware Initialization */
    USB_Init();
}



/** Event handler for the library USB Connection event. */
void EVENT_USB_Device_Connect(void)
{
}

/** Event handler for the library USB Disconnection event. */
void EVENT_USB_Device_Disconnect(void)
{
}

/** Event handler for the library USB Configuration Changed event. */
void EVENT_USB_Device_ConfigurationChanged(void)
{
    bool ConfigSuccess = true;

    ConfigSuccess &= CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface);

}

/** Event handler for the library USB Control Request reception event. */
void EVENT_USB_Device_ControlRequest(void)
{
    CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface);
}

/** CDC class driver callback function the processing of changes to the virtual
 *  control lines sent from the host..
 *
 *  \param[in] CDCInterfaceInfo  Pointer to the CDC class interface configuration structure being referenced
 */
void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t *const CDCInterfaceInfo)
{
    /* You can get changes to the virtual CDC lines in this callback; a common
       use-case is to use the Data Terminal Ready (DTR) flag to enable and
       disable CDC communications in your application when set to avoid the
       application blocking while waiting for a host to become ready and read
       in the pending data from the USB endpoints.
    */
    bool HostReady = (CDCInterfaceInfo->State.ControlLineStates.HostToDevice & CDC_CONTROL_LINE_OUT_DTR) != 0;
}

现象

串口终端持续输出包含FF的“Byte received: ”内容,即使未向设备发送任何字符。


解决方案

问题根源

  1. CDC_Device_ReceiveByte的返回值为int类型:成功接收数据时返回字节值(0-255),无数据时返回-1(对应十六进制0xFFFFFFFF,截断为char类型时会变成0xFF)。
  2. 代码中用char类型接收返回值,且判断条件if(echo)会把0xFF(有符号char为-1)判定为非零,触发无限输出。
  3. 重复调用CDC_Device_ReceiveByte会丢弃主机发送的第一字节数据。

修复后的main函数代码

int main(void)
{
    SetupHardware();

    CDC_Device_CreateStream(&VirtualSerial_CDC_Interface, &USBSerialStream);

    GlobalInterruptEnable();

    for (;;)
    {
        // 用int类型接收,正确区分无数据(-1)和有效字节0xFF(255)
        int echo = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
        // 仅当接收到有效数据时执行回显
        if(echo != -1)
        {
            fprintf(&USBSerialStream, "Byte received: %c\n\r", (char)echo);
        }

        CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
        USB_USBTask();
    }
}

修复说明

  • 改用int类型接收返回值,避免将“无数据”标识误判为有效字符。
  • 移除多余的CDC_Device_ReceiveByte调用,防止丢失主机数据。
  • 调整判断条件为echo != -1,仅在真正接收到数据时触发输出,解决无限循环输出FF的问题。

内容的提问来源于stack exchange,提问作者piro-s

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 15:09:52