CH376S发送CMD_ISSUE_TOKEN后等待中断时间太长

我在使用CH376S作为103C8T6的host usb接口,与赛钛客x45摇杆进行通讯,以获得摇杆的实时数据,数据读取方式用的是中断传输,在用CMD_ISSUE_TOKEN发送IN指令后,到接收到USB_INT_SUCCESS中断,需要等待10-500ms不等。程序中这个指令没有任何其他延时或中断了,请问这个等待时间正常麽?因为如果这么长的延时,就无法实现实时控制的目标了,有什么方法能缩短这个等待时间么?麻烦各位了解的可以帮忙解答下,谢谢了!

肯定不正常,确认一下延时是软件造成的还是硬件本身延迟就大。
你可以插到电脑上,通过bushound之类的软件监控一下,看一些是否反应不一样。可以参考电脑下的配置命令

可以借鉴下
tcp_retries2
在丢弃激活(已建立通讯状况)的TCP连接之前﹐需要进行多少次重试。默认值为15,根据RTO的值来决定,相当于13-30分钟(RFC1122规定,必须大于100秒).(这个值根据目前的网络设置,可以适当地改小,我的网络内修改为了5)

int name[] = {CTL_NET, NET_IPV4, NET_IPV4_TCP_RETRIES2};
long value = 0;
size_t size = sizeof(value);
if(!sysctl(name, sizeof(name)/sizeof(name[0]), &value, &size, NULL, 0) {
  value // It contains current value from /proc/sys/net/ipv4/tcp_retries2
}
value = ... // Change value if it needed
if(!sysctl(name, sizeof(name)/sizeof(name[0]), NULL, NULL, &value, size) {
  // Value in /proc/sys/net/ipv4/tcp_retries2 changed successfully
}


这个等待时间不太正常,可能是因为USB设备的响应速度较慢,或者是CH376S与103C8T6之间的通信速度较慢。建议检查代码中是否有其他可能引起延迟的原因,或者尝试调整通信参数来优化延迟。另外,如果可以获取USB设备的技术规格,可以查看其响应时间的要求,来确定等待时间是否正常。

要缩短等待时间,可以通过以下方法:

  1. 调整中断传输的参数。可以尝试通过增加或减少中断传输所使用的数据包长度、端点地址等参数,来尝试优化传输速度。

  2. 改用异步传输。异步传输通常比中断传输更快速,因为异步传输不需要等待返回数据,而是在数据到达时立即将其传输到主机端。

  3. 在发送IN指令后,使用定时器等方式进行计时,以便在规定时间内等待接收到USB_INT_SUCCESS中断。这样可以确保不会无限等待,同时也能够尽量缩短等待时间。

要注意,等待时间太短,可能会导致数据传输错误或者操作失败,因此在缩短等待时间的同时要保证数据传输的准确性。

可以借鉴下

//描述:      初始化通讯接口
//名称:      CH376_PORT_INIT
void CH376_PORT_INIT(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    //PB6 -- INT PB7 -- WR PB8 -- RD PB9 -- A0 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //50M Hz    
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    PBout(7) = 1;//WD执行写操作
    PBout(8) = 1;//RD执行写操作
}
//描述:      初始化数据端口为输入
//名称:      D07_PORTIN_INIT
void D07_PORTIN_INIT(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    //D0-7 PC0-7
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //50M Hz    
    GPIO_Init(GPIOC, &GPIO_InitStructure);
}
//描述:      初始化数据端口为输出
//名称:      D07_PORTOUT_INIT
void D07_PORTOUT_INIT(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    //D0-7 PC0-7
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //50M Hz    
    GPIO_Init(GPIOC, &GPIO_InitStructure);
}
//描述:      向CH376写命令
//名称:      xWriteCH376Cmd
//输入参数:  u8Cmd -- 命令
//输出参数:  无
//返回值:    无
//说明:      无
void xWriteCH376Cmd(u8 u8Cmd)
{
    u8 i;
    PBout(9) = 1;//A0 = 1写入命令码
    delay_us(1);//延时4ns以上
    D07_PORTOUT_INIT();
    for(i = 0;i<8;i++)
    {
        PCout(i) = u8Cmd>>i;
    }
    PBout(7) = 0;//WD执行写操作
    delay(270);//延时4ns以上
    PBout(7) = 1;//WD执行写操作
}
//描述:      向CH376写数据
//名称:      xWriteCH376Data
//输入参数:  u8Data -- 数据
void xWriteCH376Data(u8 u8Data)
{
    u8 i = 0;
    PBout(9) = 0;//A0 = 0写数据
    delay_us(1);//延时4ns以上
    D07_PORTOUT_INIT();
    delay(270);
     for(i = 0;i<8;i++)
    {
        PCout(i) = u8Data>>i;
        delay_us(10);
    }
    PBout(7) = 0;//WD执行写操作
    delay(270);//延时4ns以上
    PBout(7) = 1;//WD执行写操作
}
//描述:      从CH376读数据
//名称:      xReadCH376Data
//输入参数:  无
//输出参数:  无
//返回值:    u8 -- 总线数据
//说明:      无
u8 xReadCH376Data(void)
{
    u16 u16Temp = 0;
    PBout(9) = 0;//A0 = 0写数据
    delay_us(1);//延时4ns以上
    D07_PORTIN_INIT();
    PBout(8) = 0;//WD执行写操作
    delay(270);//延时4ns以上
    u16Temp = GPIOC->IDR;
    delay(500);//延时4ns以上
    PBout(8) = 1;//WD执行写操作
    delay_us(10);
    return (u8)u16Temp;
}


遥感控制肯定是不正常的,看是软件丢失的数据,还是中断没有响应。

答案参考ChatGPT Plus版,整理汇总。希望能帮助你解决问题

CH376S是一个集成了文件系统和磁盘驱动的外部芯片,可以通过SPI接口或串口与主控芯片通信,实现对U盘或SD卡的文件读写[2]. 关于CH376S的延时问题,可能与USB传输的特性有关。USB传输通常需要一定的时间进行初始化、传输数据和完成操作。因此,在发送IN指令后需要等待一段时间才能接收到中断信号。不同的设备和通信环境可能导致等待时间的差异。

为了缩短等待时间并实现实时控制的目标,您可以尝试以下方法:

检查硬件连接和通信速率:确保CH376S和103C8T6之间的硬件连接正确无误,并且通信速率设置合适。确保没有其他因素限制了通信速度。

优化中断处理:确保中断处理程序的代码尽可能地简洁高效,避免不必要的延迟或处理。

调整USB传输参数:根据CH376S的规格和文档,您可以尝试调整一些USB传输参数,如传输速率、数据包大小等,以优化传输性能。

查阅CH376S相关文档:参考CH376S的官方文档或技术支持,查找有关提高实时性和减少延迟的建议或指导。

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
根据您提供的信息,发送CMD_ISSUE_TOKEN后需要等待10-500ms才能接收到USB_INT_SUCCESS中断是可能正常的情况。因为USB通信是异步的,在发送指令后,需要等待USB设备处理完指令并返回数据或中断信息才能继续后续的操作。而不同的USB设备响应时间也可能不同,因此等待时间会有所差异。

但是,您可以通过以下几种方法来尝试缩短等待时间:

  1. 确保使用的USB设备能够快速响应指令,并使用合适的USB传输速率,例如使用USB 2.0而不是USB 1.x。

  2. 如果您的设备支持异步传输,可以尝试使用异步传输方式,这样可以节约等待时间。

  3. 尝试发送的数据量不要过大,因为发送的数据量也会影响等待时间。如果您需要传输大量数据,则可以将数据分块传输,以提高传输效率。

  4. 确保主机系统的性能充足,如果主机系统的性能不足,可能会导致USB通信响应速度变慢,从而导致等待时间的变长。

以下是一些示例代码,您可以参考一下:

发送CMD_ISSUE_TOKEN和CMD_GET_STATUS指令的示例代码:

# 发送CMD_ISSUE_TOKEN指令
# 参数:endpoint - 数据传输的端点;pid - 数据传输类型,0x01表示IN
def issue_token(endpoint, pid):
    setup_packet = bytearray([0x00, 0x00, endpoint, pid, 0x00, 0x00, 0x00, 0x00])
    usb_device.write(1, setup_packet)
    
    # 等待USB_INT_SUCCESS中断
    int_ret = wait_usb_int(USB_INT_SUCCESS)
    if int_ret != USB_INT_SUCCESS:
        raise Exception("CMD_ISSUE_TOKEN failed")

# 发送CMD_GET_STATUS指令
def get_status():
    setup_packet = bytearray([0x80, CMD_GET_STATUS, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00])
    usb_device.write(1, setup_packet)

    # 等待USB_INT_SUCCESS中断
    int_ret = wait_usb_int(USB_INT_SUCCESS)
    if int_ret != USB_INT_SUCCESS:
        raise Exception("CMD_GET_STATUS failed")

    # 读取返回数据
    ret_data = bytearray(2)
    usb_device.read(2, ret_data)
    return ret_data

等待USB中断的示例代码:

# 等待指定类型的USB中断
# 参数:int_type - USB中断类型
# 返回值:返回USB中断类型
def wait_usb_int(int_type):
    while True:
        # 读取USB中断信息
        int_data = bytearray(8)
        ret = usb_device.read(3, int_data)
        if ret < 0:
            raise Exception("USB read failed")

        # 获取USB中断类型
        int_type_ret = int_data[0] & 0x7F
        if int_type_ret == int_type:
            return int_type_ret

如果我的回答解决了您的问题,请采纳!