OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 286|回复: 2

板子芯片是STM32F103VCT6,USB虚拟串口,怎么知道串口助手已经打开或关闭?

[复制链接]

1

主题

2

帖子

0

精华

新手上路

积分
32
金钱
32
注册时间
2019-8-3
在线时间
3 小时
发表于 2026-7-6 15:14:49 | 显示全部楼层 |阅读模式
1金钱
USB采用早期的官方库函数,USB VCP在电脑端已识别,现在的疑问如下:1.怎么判断串口助手打开虚拟串口?
2.怎么判断串口助手关闭虚拟串口?
另外单片机通过虚拟串口每隔5秒发送一次,当串口助手关闭一段时间再打开,关闭时间内的数据全部在串口助手显示,请问怎么清除发送缓冲区?
谢谢!
                                                          usb_tlen=9;
                                                        USB_TxWrite(usb_tx, usb_tlen);

uint32_t USB_TxWrite(uint8_t *buffter, uint32_t writeLen)
{
    return QUEUE_PacketIn(&m_QueueUsbComTx, buffter, writeLen);
}




回复

使用道具 举报

0

主题

89

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
487
金钱
487
注册时间
2026-1-29
在线时间
29 小时
发表于 2026-7-6 17:55:06 | 显示全部楼层
本帖最后由 664929323 于 2026-7-6 17:56 编辑

针对您的问题,我将分三个部分解答:判断串口助手开闭状态、解决数据堆积问题、以及相关代码优化建议。
一、判断串口助手打开/关闭状态
方法1:监听DTR信号(推荐)
虚拟串口的DTR(Data Terminal Ready)信号可以反映PC端状态:


// 在USB回调函数中检测DTR状态
void USB_CDC_Handler(void)
{
    if (pProperty->USB_IsConnected)
    {
        if (pProperty->USB_DtrStatus)  // DTR=1 表示串口助手已打开
        {
            // 串口助手打开处理
        }
        else  // DTR=0 表示串口助手关闭
        {
            // 串口助手关闭处理
        }
    }
}

      
方法2:监控USB总线活动
通过检测USB端点的活跃状态间接判断:

      


// 在USB发送完成回调中判断
void USB_TxCompleteCallback(void)
{
    if (/* 连续多次发送无响应 */)
    {
        // 判定为串口助手已关闭
    }
}

      
二、解决数据堆积问题
方案A:立即清空发送队列
      

void FlushTxBuffer(void)
{
    // 清空您的发送队列
    QUEUE_Reset(&m_QueueUsbComTx);
   
    // 同时清空USB硬件FIFO(如有必要)
    // 需查阅具体USB外设寄存器手册
}

      
方案B:智能发送控制(推荐)
      

// 修改发送函数
uint32_t USB_TxWrite(uint8_t *buffter, uint32_t writeLen)
{
    // 只在USB在线时发送
    if (pProperty->USB_IsConnected && pProperty->USB_DtrStatus)
    {
        return QUEUE_PacketIn(&m_QueueUsbComTx, buffter, writeLen);
    }
    return 0; // 丢弃数据
}

      
三、完整解决方案示例
1. 初始化检测
      


// 系统启动时立即清空缓冲区
FlushTxBuffer();

      
2. 状态监测任务
      

        

void USB_MonitorTask(void *argument)
{
    uint8_t lastDtrState = 0;
   
    while(1)
    {
        uint8_t currentDtr = pProperty->USB_DtrStatus;
        
        // 状态变化检测
        if (lastDtrState != currentDtr)
        {
            if (currentDtr)
            {
                FlushTxBuffer(); // 新打开时清空旧数据
            }
            lastDtrState = currentDtr;
        }
        
        vTaskDelay(pdMS_TO_TICKS(100)); // 100ms检测周期
    }
}

      
3. 发送策略优化
      


// 带超时机制的发送函数
uint32_t USB_SmartTxWrite(uint8_t *buffer, uint32_t length)
{
    static uint32_t failCount = 0;
   
    if (!pProperty->USB_IsConnected || !pProperty->USB_DtrStatus)
    {
        failCount++;
        if (failCount > 10)  // 连续10次失败认为离线
        {
            FlushTxBuffer();
            failCount = 0;
        }
        return 0;
    }
   
    failCount = 0;
    return USB_TxWrite(buffer, length);
}

      
四、关键注意事项
端点配置:确认使用了正确的端点配置(通常批量传输端点EP1):


#define EP1_TX_SIZE 64  // 确保端点大小足够

      
中断优先级:USB中断应设置为最高优先级:

NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 0);

      
队列管理:建议采用环形队列:


typedef struct {
    uint8_t buffer[512];
    volatile uint16_t head, tail;
} RingBuffer;

      
五、调试建议
观察LED指示:

      

#define LED_ON()  GPIO_SetBits(GPIOC, GPIO_Pin_13)
#define LED_OFF() GPIO_ResetBits(GPIOC, GPIO_Pin_13)

      
使用逻辑分析仪:监测USB D+/D-信号质量

PC端验证:使用Tera Term等工具测试各种插拔场景

这种方案能有效解决您遇到的三个问题:实时检测串口状态、防止数据堆积、确保重连后数据同步。实际部署时建议先通过示波器观察USB总线活动验证检测逻辑的可靠性。
回复

使用道具 举报

1

主题

2

帖子

0

精华

新手上路

积分
32
金钱
32
注册时间
2019-8-3
在线时间
3 小时
 楼主| 发表于 2026-7-6 19:11:22 | 显示全部楼层
664929323 发表于 2026-7-6 17:55
针对您的问题,我将分三个部分解答:判断串口助手开闭状态、解决数据堆积问题、以及相关代码优化建议。
一 ...

谢谢您的解答 这个解释太详细
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /1 下一条

正点原子公众号

如发现本坛存在违规或侵权内容, 请点击这里发送邮件举报 (或致电020-38271790)。请提供侵权说明和联系方式。我们将及时审核依法处理,感谢配合。

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2026-7-15 05:49

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表