求助:CH376通过STM32串口查询U盘插入与否,造成芯片死掉。

MarkdownPad Document

用的是stm32的串口与ch376通讯。

  1. 因为需要设备自动判断U盘插入, 所以根据例程写了个查询函数: u8 Ch376_disk_connect_query(void) (代码在下面)

  2. 发现先设置CH376为模式6后,再插入U盘。会造成CH376芯片死掉。(插入U盘进入模式6,可以检测到U盘插入,拔掉U盘后也可以检测到拔出。但是再次插入就会造成芯片死掉,串口无响应。)

     main
    {
         Ch376_uart2_test();
         Ch376_set_usb_mode();    
         delay_ms(20);
        while(1)
         {
             printf("\r\n-----------------------------------\r\n");
             delay_ms(1500);
             //Ch376_set_usb_mode();
             Ch376_disk_connect_query();
         }
     }
  3. 如果把Ch376_set_usb_mode(); 函数也放到循环中,则会测试通过。

     Ch376_uart2_test();
     Ch376_set_usb_mode();    
     delay_ms(20);
    while(1)
     {
         printf("\r\n-----------------------------------\r\n");
         delay_ms(1500);
         Ch376_set_usb_mode();
         Ch376_disk_connect_query();
     }
//---------------------------Ch376_disk_connect_query()函数-------------------------------------------------------------

u8 Ch376_disk_connect_query(void)
{
    u8 temp;
    //如果先前产生中断(串口接收到数据),查询并清除
    if(USART_GetFlagStatus(USART2,USART_FLAG_RXNE) == SET)
    { 
        temp = USART_ReceiveData(USART2);
        printf("\r\nCh376_disk_connect_query()函数 查询到上次中断接收到串口数据为:%#X\r\n",temp);
        Ch376_Send_Cmd(CMD01_GET_STATUS);
        temp = Ch376_Read_Data();
    }

    USART_ClearFlag(USART2,USART_FLAG_RXNE);
    USART_ClearFlag(USART2,USART_FLAG_TC);

    //发送查询U盘连接的 DISK_CONNECT 命令,会产生中断。
    Ch376_Send_Cmd(0x30);
    temp = Ch376_Read_Data();
    printf("\r\nCh376_disk_connect_query()函数 第一次接收到串口数据为:%#X\r\n",temp);
    //查询中断状态并取消中断
    Ch376_Send_Cmd(CMD01_GET_STATUS);
    temp = Ch376_Read_Data();
    if(temp == 0x14)
    {
        printf("\r\nCh376_disk_connect_query()函数 查询到U盘插入。第二次接收到串口数据为:%#X\r\n",temp);
        return 1;
    }
    else 
        printf("Ch376_disk_connect_query()函数 未查询到U盘插入。返回值为:%#X\r\n",temp);
        return 0;
}


串口尽量用中断方式收数据。


RTX截图未命名.png

Ch376_Read_Data()必须应该实现串口超时等待接收一个字节的功能。用以判断中断到来的标志。如果有这个中断标志,才可以去执行“Ch376_Send_Cmd(CMD01_GET_STATUS)”。

上电前,插上U盘,设置模式6,然后从串口超时接收一个字节,是否是0x51,这个值要先读出来。然后查看一下执行Ch376_disk_connect_query的刚开始,串口接收的一个字节数据是否是0x15。这个0x15代表U盘插入,如果设置模式6之前U盘没有插入,此时返回的应该是0x16,你实际操作验证一下。


 一、 插上U盘设置模式6后,的确会有一个字节的中断数据产生,数据就是0x15。(这个我看手册,很早就留意到了。)
此时,拔下U盘,发送查询U盘连接命令 **Ch376_Send_Cmd(0x30)**得到中断,返回数据为: 0x82, 到现在为止,一切正常。再次插入U盘,发送查询U盘连接命令 **Ch376_Send_Cmd(0x30)**,芯片会死掉,对命令无响应。

二、 不插入U盘设置模式6,并没有产生中断,也没数据通过串口返回。 
此时发送查询U盘连接命令 **Ch376_Send_Cmd(0x30)**得到中断,返回数据为: 0x82. 到现在为止,一切正常。
但是如果这时候 插入U盘,发送 **Ch376_Send_Cmd(0x30) **U盘查询命令,则会造成死机,芯片无响应。

三、 再问下,如果在CH376模块产生中断,通过产口返回中断状态后,并没有发送中断取消指令。**Ch376_Send_Cmd(CMD01_GET_STATUS)**,会怎样?当然,我还是每次都发送了该命令,取消了中断。

四、 芯片产生中断后,在INT引脚产生低电平,发送命令Ch376_Send_Cmd(CMD01_GET_STATUS) 后,是不是会恢复到高电平?


另,

    1. Ch376_Read_Data() 指令我是通过循环查询的,不会造成主芯片 STM32死机。 

      2. 我同样写了 Ch376_Query_Inetrrupt() 函数(循环查询一定次数的串口状态)。

           用来进行测试。还是同样的问题。(参照着51的例程源码进行的。)


对于“芯片会死掉,对命令无响应”,是不是芯片无响应,可以用串口调试助手连接376发命令来验证一下。

我看你的代码是通过串口接收数据来作中断检测的,所以INT引脚根本就没用到,所以是否清除INT引脚电平状态也就不重要了。清除INT引脚电平是通过执行CMD01_GET_STATUS来完成的。

Ch376_Read_Data() 指令我是通过循环查询的,不会造成主芯片 STM32死机”一般我们都是串口超时接收,正确的操作一般也不会接收超时。

对于函数

UINT8 Query376Interrupt( void )
{
 UINT8 TEMP;
#ifdef CH376_INT_WIRE
 if( CH376_INT_WIRE )    /* 如果连接了CH376的中断引脚则直接查询中断引脚 */
  return FALSE;
 else
 {
  RI = 0;              //清除中断标志,丢弃这个数据
  return TRUE;
 } 
#else
 if ( RI ) {  /* 如果未连接CH376的中断引脚则查询串口中断状态码 */
  RI = 0;        //清除中断标志,丢弃这个数据
  return( TRUE );
 }
 else return( FALSE );
#endif
}

其他文件系统应用层操作部分完全使用FILE_SYS.C文件


1. 是的,我是通过串口接收数据的标志位来检测中断状态的。具体函数如下。

        u8 Ch376_Query_Inetrrupt(void)  //整个函数我测试了一下,若没有检测到数据,用时 330ms+。这个时间应该足够CH376芯片处理了。

        {

             u32 i= 0;

            for(i = 0; i <500000; i++)

            {    if(USART_GetFlagStatus(USART2,USART_FLAG_RXNE) == SET)

                {

                    return 1;

                }

            }

            return 0;

        }

2. 我也 单纯用串口助手试了。就是会出现CH376芯片未响应。

3.” 清除INT引脚电平是通过执行CMD01_GET_STATUS来完成的。  “    这个是不是说如果没用到 INT 引脚,是不是就不用执行CMD01_GET_STATUS来清除中断了。 直接接受中断数据或者查询中断数据就行?


4. 有没有技术支持的邮件?或者电话,这样联系速度好慢。


1、Ch376_Query_Inetrrupt()里面如果串口收到数据,需要先清除串口接收标志,然后返回1。

2、这个你用ch376.exe调试工具测,没有的话,到官网CH376EVT下载。

3、是的。

4、电话:025-52638376,邮件:gj@wch.cn


OK,问题已找到。不是软件的问题。 是个硬件的BUG。感谢 jie 的支持。

1. 在用ch376.exe调试工具,测试后,发现不存在我的问题,拔插U盘都能正常检测。这就证明CH376芯片本身没有问题。后来偶然间想到了。

2. 我是直接用的STM32Mini板驱动CH376的转接板,可能电流驱动不够。偶然间外接了个电源给板子供电(充电宝........),芯片一下正常了(代码一点没改)。去掉外接电源,,之前的bug又复现了。

3. 弱弱的问下,要是给376芯片的驱动电流不够,会不会造成芯片的休眠之类的。

按道理说,电压电流不够,芯片就不会正常工作的,但是明明可以接收到串口的数据(通讯正常,设置模式也正常)。 拔插U盘后,再测试连接状态,芯片就 gg 了。

真是迷一样的bug。折腾了我整整一周!!我一直以为是我的我写了bug代码。。。。在代码里面找问题。so,这次提醒了我,我的代码还是可疑的。



那如果是电压电流的问题,为什么之前用串口调试助手芯片会未响应?

测试命令、模式设置的时候还没有和U盘有任何通讯呢,插上U盘之后也有可能是U盘电流比较大导致376供电电压过低产生复位或工作不稳定的情况。


之前的串口调不通,可能是因为我串口插在了,一拖四的USB-HUB上(笔记本USB口少的可怜). 后面用CH376DEBUG测试,直接插得USB口。。。。。


只有登录才能回复,可以选择微信账号登录