找回密码
 立即注册
查看: 107|回复: 15

请问USB连接状态如何判断

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-04-16 13:09:19
已绑定手机

2

主题

7

回帖

44

积分

新手上路

积分
44
发表于 2025-4-11 18:02:58 | 显示全部楼层 |阅读模式
我用的 ai8h2k12u单片机,采用 usb cdc 模拟串口,stc32_stc8_usb.h 库,单片机内部程序如何判断当前USB连接是否成功,串口状态是打开还是关闭?我需要实时判断当前的USB状态,避免影响其他程序,但现在USB上位机的串口如果关闭,即使USB线缆正常连接,USB_SendData这个函数却会阻塞,影响其他程序,如果当前USB离线,或者上位机串口未打开,我就跳过USB_SendData函数,避免阻塞


下图,串口关闭,单片机虽然正常在跑,也会响应,但响应就慢了





串口关闭

串口关闭
回复

使用道具 举报 送花

3

主题

1160

回帖

1031

积分

等待验证会员

积分
1031
发表于 2025-4-11 18:03:00 | 显示全部楼层
在STC AI8H2K12U单片机中,通过USB CDC模拟串口通信时,判断USB连接状态及串口状态是一个关键问题。以下是一个专业的解决方案,帮助您实时判断USB连接状态,避免USBSendData函数阻塞其他程序。

1. USB连接状态的判断
USB连接状态可以通过检测USB设备的枚举状态来判断。STC32STC8USB库提供了相关的函数和标志位,用于检测USB是否成功枚举并与主机建立连接。

关键函数与标志位:
USBGetDeviceState():该函数返回USB设备的当前状态。常见的状态包括:
USBSTATEDEFAULT:设备未连接或未枚举。
USBSTATEADDRESSED:设备已枚举但未配置。
USBSTATECONFIGURED:设备已成功配置并与主机建立连接。
USBIsConfigured():该函数直接返回设备是否已配置(即是否已成功连接)。

示例代码:
  1. c
  2. include "stc32stc8usb.h"
  3. bool isUSBConnected() {
  4.     return USBIsConfigured(); // 返回USB是否已配置
  5. }
复制代码

2. 串口状态的判断
串口状态(即上位机是否打开串口)可以通过检测USB CDC的通信状态来判断。STC32STC8USB库提供了相关的函数和标志位,用于检测串口是否打开。

关键函数与标志位:
CDCGetLineState():该函数返回CDC通信线路的状态。常见的状态包括:
CDCLINESTATEDTR:数据终端就绪(DTR)信号,表示上位机已打开串口。
CDCLINESTATERTS:请求发送(RTS)信号,表示上位机已准备好接收数据。
CDCIsOpen():该函数直接返回串口是否已打开。

示例代码:
  1. c
  2. include "stc32stc8usb.h"
  3. bool isSerialPortOpen() {
  4.     return CDCIsOpen(); // 返回串口是否已打开
  5. }
复制代码

3. 综合判断与处理
在实际应用中,您需要综合判断USB连接状态和串口状态,并在发送数据前进行检测,以避免USBSendData函数阻塞。

示例代码:
  1. c
  2. include "stc32stc8usb.h"
  3. void sendDataIfReady(uint8t data, uint16t length) {
  4.     if (isUSBConnected() && isSerialPortOpen()) {
  5.         USBSendData(data, length); // 仅在USB连接且串口打开时发送数据
  6.     } else {
  7.         // 处理USB未连接或串口未打开的情况
  8.         // 例如跳过发送或记录日志
  9.     }
  10. }
复制代码

4. 避免阻塞的优化
如果USBSendData函数在串口未打开时仍然阻塞,您可以考虑以下优化措施:
超时机制:为USBSendData函数设置超时时间,避免长时间阻塞。
异步发送:使用异步发送机制,将数据发送任务放入队列中,由后台任务处理。

示例代码(超时机制):
  1. c
  2. include "stc32stc8usb.h"
  3. bool sendDataWithTimeout(uint8t data, uint16t length, uint16t timeout) {
  4.     uint16t startTime = GetSystemTick(); // 获取当前系统时间
  5.     while (!USBSendData(data, length)) {
  6.         if (GetSystemTick() - startTime > timeout) {
  7.             return false; // 超时返回失败
  8.         }
  9.     }
  10.     return true; // 发送成功
  11. }
复制代码

5. 总结
通过上述方法,您可以实时判断USB连接状态和串口状态,并在发送数据前进行检测,避免USBSendData函数阻塞其他程序。建议在实际应用中结合超时机制或异步发送机制,进一步提升系统的稳定性和响应速度。

希望以上内容对您有所帮助!如有进一步问题,欢迎继续交流。

[本文内容由国芯人工智能辅助生成,仅供参考]
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-04-16 13:09:19
已绑定手机

2

主题

7

回帖

44

积分

新手上路

积分
44
发表于 2025-4-11 18:21:51 | 显示全部楼层
楼上AI回答的不行,stc32_stc8_usb.h这个库里面没有那些要用到的函数
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-04-16 13:09:19
已绑定手机

2

主题

7

回帖

44

积分

新手上路

积分
44
发表于 2025-4-11 18:43:09 | 显示全部楼层
#ifndef __USB_H__
#define __USB_H__

#include "def.h"

//使用串口“printf”打印信息需屏蔽以下两个定义
//#define PRINTF_SEGLED         //printf输出重定向到ISP下载软件中的7段数码管
//#define PRINTF_HID            //printf输出直接重定向到USB口
//#define PRINTF_USB            //printf输出直接重定向到USB口

#define DEVSTATE_ATTACHED       0
#define DEVSTATE_POWERED        1
#define DEVSTATE_DEFAULT        2
#define DEVSTATE_ADDRESS        3
#define DEVSTATE_CONFIGURED     4
#define DEVSTATE_SUSPENDED      5

void usb_init();
void usb_OUT_done();
void USB_SendData(BYTE *dat, int size);

void set_usb_OUT_callback(void (*pfn)(void));   //如果需要实现USB接收中断,需要调用此函数来设置回调函数
void set_usb_IN_callback(void (*pfn)(void));    //如果需要实现USB发送中断,需要调用此函数来设置回调函数
void set_usb_ispcmd(char *cmd);                 //设置不停电下载的用户自定义命令,不设置时默认下载命令为“@STCISP#”

int SEG7_ShowString(const char *fmt, ...);
void SEG7_ShowLong(long n, char radix);
void SEG7_ShowFloat(float f);
void SEG7_ShowCode(BYTE *cod);

void LED40_SendData(BYTE *dat, BYTE size);
void LED40_SetPort(BYTE port, BYTE dat);
void LED40_SetBit(BYTE port, BYTE bt);
void LED40_ClrBit(BYTE port, BYTE bt);

void LED64_SendData(BYTE *dat, BYTE size);
void LED64_SetPort(BYTE port, BYTE dat);
void LED64_SetBit(BYTE port, BYTE bt);
void LED64_ClrBit(BYTE port, BYTE bt);

void LCD12864_DisplayOff();
void LCD12864_DisplayOn();
void LCD12864_CursorOff();
void LCD12864_CursorOn();
void LCD12864_CursorMoveLeft();
void LCD12864_CursorMoveRight();
void LCD12864_CursorReturnHome();
void LCD12864_ScrollLeft();
void LCD12864_ScrollRight();
void LCD12864_ScrollUp(BYTE line);
void LCD12864_AutoWrapOff();
void LCD12864_AutoWrapOn();
void LCD12864_ReverseLine(BYTE line);
void LCD12864_DisplayClear();
void LCD12864_ShowString(BYTE x, BYTE y, char *str);
void LCD12864_ShowPicture(BYTE x, BYTE y, BYTE cx, BYTE cy, BYTE *dat);

void OLED12864_DisplayOff();
void OLED12864_DisplayOn();
void OLED12864_DisplayContent();
void OLED12864_DisplayEntire();
void OLED12864_HorizontalMirror();
void OLED12864_VerticalMirror();
void OLED12864_DisplayReverse();
void OLED12864_SetContrast(BYTE bContrast);
void OLED12864_SetAddressMode(BYTE bMode);
void OLED12864_ScrollLeft(BYTE bPageStart, BYTE bPageEnd, WORD nInterval);
void OLED12864_ScrollRight(BYTE bPageStart, BYTE bPageEnd, WORD nInterval);
void OLED12864_ScrollUp(BYTE bPageStart, BYTE bPageEnd, WORD nInterval);
void OLED12864_ScrollStart();
void OLED12864_ScrollStop();
void OLED12864_ShowPicture(BYTE x, BYTE y, BYTE cx, BYTE cy, BYTE *dat);

int printf_usb (const char *fmt, ...);

#if defined PRINTF_SEGLED
#define printf  SEG7_ShowString
#elif defined PRINTF_USB
#define printf  printf_usb
#elif defined  PRINTF_HID
#define printf  printf_usb
#endif


extern BYTE xdata UsbFeatureBuffer[64];
extern BYTE xdata UsbInBuffer[64];
extern BYTE xdata UsbOutBuffer[64];
extern BOOL bUsbFeatureReady;
extern BOOL bUsbInBusy;
extern BOOL bUsbOutReady;
extern BYTE DeviceState;
extern BYTE OutNumber;


#endif

这些个函数的使用方法,哪里有解释?
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:458
  • 最近打卡:2025-05-01 07:48:22
已绑定手机
已实名认证

110

主题

2219

回帖

5452

积分

版主

积分
5452
发表于 2025-4-11 18:43:59 | 显示全部楼层
使用最新的usb库函数,已经内置这部分的判断逻辑了。
在串口没有打开的事情不会堵塞程序执行了。
https://www.stcai.com/khs
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:162
  • 最近打卡:2025-05-01 06:56:44
已绑定手机

56

主题

1319

回帖

2938

积分

荣誉版主

无情的代码机器

积分
2938
发表于 2025-4-11 18:49:44 | 显示全部楼层
方案1:更新usb库,最新版usb库里添加了超时判断不会阻塞
stc32g_cdc_query_demo - 副本.zip (74.39 KB, 下载次数: 3)
方案2:修改范例,检测ctrl_line_st请求,这个请求改了DTR和RTS状态,可以区分串口是否打开。
截图202504111843258377.jpg
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-04-16 13:09:19
已绑定手机

2

主题

7

回帖

44

积分

新手上路

积分
44
发表于 2025-4-11 18:52:44 | 显示全部楼层
王*** 发表于 2025-4-11 18:43
使用最新的usb库函数,已经内置这部分的判断逻辑了。
在串口没有打开的事情不会堵塞程序执行了。
https://w ...

用的就是最新的库,但还是会有一点阻塞

点评

或者自定义个超时标识,多长时间pc没数据过来判断短链,跳过发送  详情 回复 发表于 2025-4-11 18:59
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:162
  • 最近打卡:2025-05-01 06:56:44
已绑定手机

56

主题

1319

回帖

2938

积分

荣誉版主

无情的代码机器

积分
2938
发表于 2025-4-11 18:59:46 | 显示全部楼层
ykeu*** 发表于 2025-4-11 18:52
用的就是最新的库,但还是会有一点阻塞

或者自定义个超时标识,多长时间pc没数据过来判断短链,跳过发送
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-04-16 13:09:19
已绑定手机

2

主题

7

回帖

44

积分

新手上路

积分
44
发表于 2025-4-11 19:03:01 | 显示全部楼层
erci*** 发表于 2025-4-11 18:59
或者自定义个超时标识,多长时间pc没数据过来判断短链,跳过发送

我的单片机,只向上位机发送数据,上位机串口不下发数据,如果能够直接判断当前的USB连接状态,以及串口开关状态,那就最好了。不知道能否实现
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-04-16 13:09:19
已绑定手机

2

主题

7

回帖

44

积分

新手上路

积分
44
发表于 2025-4-11 19:04:20 | 显示全部楼层
erci*** 发表于 2025-4-11 18:49
方案1:更新usb库,最新版usb库里添加了超时判断不会阻塞

方案2:修改范例,检测ctrl_line_st请求,这个请 ...

用的就是最新的库,但还是会有一点阻塞,有没有能够直接判断当前的USB连接状态,以及串口开关状态的标志位或者函数?

点评

当前版本没这样的标识或函数 写了个临时措施:  详情 回复 发表于 2025-4-11 19:53
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 04:16 , Processed in 0.220992 second(s), 116 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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