一键USB通断器

在一些特别情况下,我们会碰到 USB 兼容性问题。比如,我正在使用的 DELL C2722DE 显示器,通过 TypeC 连接主机,除了能够显示之外,还内置了 USB Hub ,但是它和我的微软鼠标存在兼容性问题,如果插着显示器休眠,或者开机的话,进入 Windows之后鼠标是无法直接使用,必须插拔一次才能正常工作。

针对这种情况,这次设计了一个 USB 插拔装置,遇到问题的时候无需做插拔动作,而是通过按键一次自行完成一个插拔的模拟,这样可以方便使用。USB插拔动作可以分解为2步,插入时是先接通5V供电,然后接通D+/D-信号。如果仔细观察USB接头,可以发现USB D+/D- 引脚会比5V和GND 短一点,这样就能保证插入的时候是先接通供电,然后再接入信号的。这样可以避免插入时信号先于供电接通,电流直接倒灌到芯片中。类似的,拔出时,是先断开信号,然后再切断供电。

硬件方面使用了3个芯片:CH554 /CH442/SY6280AAC。CH554是一个单片机,这里作用是获得按钮状态,然后根据状态控制USB信号的切换和USB母头上的5V输出; CH442进行信号切换, SY6280AAC 是功率电子开关芯片,这里我们用用它控制USB供电输出。

CH442是一款低阻宽带双向模拟开关芯片,包含2路单刀双掷二选一开关。这里用作 USB 信号二选一。

CH442

PCB 设计如下:

焊接后的成品,刚好能装在外壳中:

CH554 外围只需要1个10K电阻,2个0.1uf 电容即可让它工作起来。然后通过P1 Header 4 下载数据非常方便。此外,CH_IN 适用于控制CH442信号切换,CTRL1用于控制SY6280AAC。

代码部分非常简单:

#define CH_IN 14
#define LED   15
#define CTRL1 16
#define KEY   17
void setup() {
  pinMode(CH_IN,OUTPUT);
  pinMode(LED,OUTPUT);
  pinMode(CTRL1,OUTPUT);
  pinMode(KEY,INPUT_PULLUP);
    
  digitalWrite(CH_IN,LOW); // Switch to 1
  digitalWrite(LED,LOW); // 不亮
  digitalWrite(CTRL1,HIGH); // 供电    
}
unsigned long int Elsp=0;

void loop() {
  if (digitalRead(KEY)==LOW) {
      digitalWrite(LED,HIGH); // 点亮 LED
      digitalWrite(CH_IN,HIGH); // 断开数据线
      delay(100);
      digitalWrite(CTRL1,LOW); // 断开USB供电
      Elsp=millis();
  } else {
      // Key 抬起
      if ((Elsp!=0)&&(millis()-Elsp>500)) {
          Elsp=0;
          digitalWrite(LED,LOW); // 关闭 LED          
          digitalWrite(CTRL1,HIGH); // 开始USB供电
          delay(100);
          digitalWrite(CH_IN,LOW); // 接通数据线
        }
    }
}

适用范围:如果你遇到的问题通过插拔一次可以解决,并且出现问题的时候USB端口能够正常供电,那么可以尝试本次的设计。运气好的话,因为引入了切换元件使得USB信号发生变化,每次都可以直接用;稍微差一些的话,出现问题的时候按下按钮即可模拟插拔让设备工作起来。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注