作者:Digi-Key 工程师Travis_Foss
查理复用算法(Charlieplexing ),具备控制多个LED的能力,即可以用较少数量的微控制器输出端来控制较多数量的 LED(微控制器输出端少于LED数量)。在1995年,Maxim 公司的 Charles Allen 首次提出这一想法,并命名为 Charlieplexing 。
查理复用算法使用微控制器的所有三种逻辑状态以及LED的单向导电性来控制矩阵。如果你试图显示不同进程的状态,并且不想占用多个微控制器引脚,那么这可能很有用。
以下是一组使用查理复用算法LED的最简单例子。
24052de5be7b9788f15f3ad5f0cbc884add2e718.png
注意,在上面的例子中,它使用了一组互补的 LED。基于 LED 如何允许电流在一个方向流动并阻止电流在另一个方向上流动,它允许我们根据输入/输出的设置来控制两个 LED。要使用此例子,可以通过更改引脚的输出类型来控制具有两个引脚的两个 LED。如果你将引脚2设置为高电平,引脚1设置为低电平,则L1 -LED将点亮。如果将引脚1设置成高电平,而引脚2设置成低电平,那么L2 -LED将会点亮。
以下是如何在 Arduino 设置。
  1. void setup() {
  2.   Serial.begin(9600);
  3.   
  4. }
  5. void loop() {
  6.    pinMode(1,OUTPUT);
  7.    pinMode(2,OUTPUT);
  8.   pinMode(3,INPUT);
  9. digitalWrite(2,HIGH);
  10.   digitalWrite(1,LOW);
  11.   delay(1000);
  12. Serial.println("1");
  13.     pinMode(1,OUTPUT);
  14.    pinMode(2,OUTPUT);
  15.    pinMode(3,INPUT);
  16. digitalWrite(1,HIGH);
  17.   digitalWrite(2,LOW);
  18.   delay(1000);
  19. Serial.println("2");
  20.   
  21. }
现在看这个示意图,你可能会想,“这怎么有用?我们只使用两个引脚控制两个LED。”让我们看看当我们添加第三个引脚时会发生什么。
以下是如何设置3个引脚的LED。
58b20ae352445041d1de88db8695ab314238073b.png
通过此设置可以看到,你可以使用3个引脚控制6个 LED。要在此设置中控制LED,你需要使用微控制器的所有三种状态。如果你想打开L1- LED而不打开其他LED,则必须将引脚2设置为高,将引脚1设置为低,将引脚3设置为输入。引脚3必须设置为输入的原因是将该引脚设置为高阻抗。这基本上从电路上断开了引脚。此外,如果我们将引脚3设置为LOW,LED L4也会亮起。
现在,如果你想打开L2-LED,用户可以将引脚1设置为高,将引脚2设置为低,将引脚3设置为输入。再次注意,如果我们没有将引脚3设置为输入,则L4-LED也将打开。
然后,用户可以完成此过程,直到他们按顺序成功点亮每个LED。
如果你想用 Arduino 编写代码, 下面是一个例子,
  1. void setup() {
  2.   Serial.begin(9600);
  3.   
  4. }
  5. void loop() {
  6.    pinMode(1,OUTPUT);
  7.    pinMode(2,OUTPUT);
  8.   pinMode(3,INPUT);
  9. digitalWrite(2,HIGH);
  10.   digitalWrite(1,LOW);
  11.   delay(1000);
  12. Serial.println("1");
  13.     pinMode(1,OUTPUT);
  14.    pinMode(2,OUTPUT);
  15.    pinMode(3,INPUT);
  16. digitalWrite(1,HIGH);
  17.   digitalWrite(2,LOW);
  18.   delay(1000);
  19. Serial.println("2");
  20.   
  21.    
  22. pinMode(3,OUTPUT);
  23.    pinMode(2,OUTPUT);
  24.      pinMode(1,INPUT);
  25. digitalWrite(3,HIGH);
  26.   digitalWrite(2,LOW);
  27.   delay(1000);
  28.     Serial.println("3");
  29.    
  30.       
  31. pinMode(3,OUTPUT);
  32.    pinMode(2,OUTPUT);
  33.    pinMode(1,INPUT);
  34. digitalWrite(2,HIGH);
  35.   digitalWrite(3,LOW);
  36.   delay(1000);
  37.    
  38. Serial.println("4");
  39.       
  40. pinMode(1,OUTPUT);
  41.    pinMode(3,OUTPUT);
  42.    pinMode(2,INPUT);
  43.   digitalWrite(3,HIGH);
  44.   digitalWrite(1,LOW);
  45.   delay(1000);
  46.    
  47. Serial.println("5");
  48.       
  49. pinMode(1,OUTPUT);
  50.    pinMode(3,OUTPUT);
  51.     pinMode(2,INPUT);
  52. digitalWrite(1,HIGH);
  53.   digitalWrite(3,LOW);
  54.   delay(1000);
  55.    
  56. Serial.println("6");
  57. }
现在我们已经探索了2个引脚和3个引脚,你可以看到查理复用算法如何成为一个有用的工具。让我们再为4个输入引脚进行一次设置。
在我们展示4个输入引脚的设置之前,你能猜出我们能够控制多少个 LED 吗?
通过将要使用的I/O数量乘以相同的I/O数量减1,可以计算出可以控制的LED数量。因此,例如,如果我们想使用4个I/O引脚,我们将该数字乘以3,这将让我们知道,我们可以用4个I/O控制多达12个LED。
以下是如何设置4个 I/O 的 LED。
94a7029a86f78b1834c60312184563ac15c9d717.png
注意,我对这一个连接进行了颜色编码,以使连接更清晰。如你所见,通过在原理图中再添加一个引脚,我们可以再添加 6个 LED。为了控制LED,此设置与3个引脚的工作方式相同,但是,在这种情况下,我们将设置2个引脚作为输入。下面是 Arduino 代码,用于控制所有 12个LED。
  1. void setup() {
  2.   Serial.begin(9600);
  3. }
  4. void loop() {
  5.   pinMode(1, OUTPUT);
  6.   pinMode(2, OUTPUT);
  7.   pinMode(3, INPUT);
  8.   pinMode(4, INPUT);
  9.   digitalWrite(2, HIGH);
  10.   digitalWrite(1, LOW);
  11.   delay(1000);
  12. Serial.println("1");
  13.   pinMode(1, OUTPUT);
  14.   pinMode(2, OUTPUT);
  15.   pinMode(3, INPUT);
  16.   pinMode(4, INPUT);
  17.   digitalWrite(1, HIGH);
  18.   digitalWrite(2, LOW);
  19.   delay(1000);
  20. Serial.println("2");
  21.   pinMode(3, OUTPUT);
  22.   pinMode(2, OUTPUT);
  23.   pinMode(1, INPUT);
  24.   pinMode(4, INPUT);
  25.   digitalWrite(3, HIGH);
  26.   digitalWrite(2, LOW);
  27.   delay(1000);
  28. Serial.println("3");
  29.   pinMode(3, OUTPUT);
  30.   pinMode(2, OUTPUT);
  31.   pinMode(1, INPUT);
  32.   pinMode(4, INPUT);
  33.   digitalWrite(2, HIGH);
  34.   digitalWrite(3, LOW);
  35.   delay(1000);
  36. Serial.println("4");
  37.   pinMode(1, OUTPUT);
  38.   pinMode(3, OUTPUT);
  39.   pinMode(2, INPUT);
  40.   pinMode(4, INPUT);
  41.   digitalWrite(3, HIGH);
  42.   digitalWrite(1, LOW);
  43.   delay(1000);
  44. Serial.println("5");
  45.   pinMode(1, OUTPUT);
  46.   pinMode(3, OUTPUT);
  47.   pinMode(2, INPUT);
  48.   pinMode(4, INPUT);
  49.   digitalWrite(1, HIGH);
  50.   digitalWrite(3, LOW);
  51.   delay(1000);
  52. Serial.println("6");
  53.   pinMode(3, OUTPUT);
  54.   pinMode(4, OUTPUT);
  55.   pinMode(2, INPUT);
  56.   pinMode(1, INPUT);
  57.   digitalWrite(3, HIGH);
  58.   digitalWrite(4, LOW);
  59.   delay(1000);
  60. Serial.println("7");
  61.   pinMode(3, OUTPUT);
  62.   pinMode(4, OUTPUT);
  63.   pinMode(1, INPUT);
  64.   pinMode(2, INPUT);
  65.   digitalWrite(4, HIGH);
  66.   digitalWrite(3, LOW);
  67.   delay(1000);
  68. Serial.println("8");
  69.   pinMode(2, OUTPUT);
  70.   pinMode(4, OUTPUT);
  71.   pinMode(1, INPUT);
  72.   pinMode(3, INPUT);
  73.   digitalWrite(4, HIGH);
  74.   digitalWrite(2, LOW);
  75.   delay(1000);
  76. Serial.println("9");
  77.   pinMode(2, OUTPUT);
  78.   pinMode(4, OUTPUT);
  79.   pinMode(1, INPUT);
  80.   pinMode(3, INPUT);
  81.   digitalWrite(2, HIGH);
  82.   digitalWrite(4, LOW);
  83.   delay(1000);
  84. Serial.println("10");
  85.   pinMode(1, OUTPUT);
  86.   pinMode(4, OUTPUT);
  87.   pinMode(2, INPUT);
  88.   pinMode(3, INPUT);
  89.   digitalWrite(4, HIGH);
  90.   digitalWrite(1, LOW);
  91.   delay(1000);
  92. Serial.println("11");
  93.   pinMode(1, OUTPUT);
  94.   pinMode(4, OUTPUT);
  95.   pinMode(2, INPUT);
  96.   pinMode(3, INPUT);
  97.   digitalWrite(1, HIGH);
  98.   digitalWrite(4, LOW);
  99.   delay(1000);
  100. Serial.println("12");
  101. }
正如你所看到的,如果你 I/O 引脚数量有限,这可能是一个有用的工具。
如果你想看到查理复用算法的其他选项,我看到的使用查理复用算法的最常见项目之一是 LED 立方体。如果你在网上搜索查理复用算法LED立方体,你会看到几个不同的版本。