电子说
步骤1:晶体管背景
晶体管起着多种作用,但它们基本上是电子开关。这正是我们将如何使用它们进行多路复用的方法。
我实际上并不会研究它们的工作原理或其他任何东西,而只是将其视为电子开关。我将使用NPN晶体管,这是最常用的晶体管。有一个发射极,一个基极和一个集电极,确保将电路组合在一起时知道哪个引脚。电流从集电极流向发射极,而基极则启用/禁用该电流。实际上,这就是使它成为开关的原因。如果您要使用两个不同的电源或需要大量电流,这也很有用。由于底座与收集器和发射器是分开的,因此可以单独供电。这有什么用?那么,所有微控制器都有一个数字引脚(GPIO)最大输出电流,通常不会超过200mA。如果一次有多个LED亮起,则可能超过200mA,这对微控制器不利。因此,使用晶体管,微控制器无需向实际组件(例如LED)提供电流。与复用无关,但您也可以使用晶体管让微控制器控制不同的电源以及继电器的使用方法。上面的第二幅图是使用晶体管的阳极和阴极原理图的基本原理图。 (注意:不需要阳极电路上的电容器)。该电路实际上不是阳极或阴极,但是我这样称呼它们是因为阳极电路的输出连接到LED的阳极。而阴极电路连接到LED的阴极。 LED的阳极是电流进入组件的地方,阴极是电流离开组件的地方。因此,当然,阳极晶体管电路为VCC提供电源,阴极晶体管电路为地提供电源。
我正在使用的晶体管:http://www.taydaelectronics.com/2n3904-npn-general-propose-transistor.html
步骤2:多路复用
多路复用时,将其视为行和列,具体取决于您的处理方式(在本例中为LEDs)您总是会有行和列。在最后一步,您看到了阳极和阴极的示意图,一个是行,另一个是列。
此步骤中的图片显示了一组9个LED,共有3行和3列。行和列无关紧要,它们的顺序是什么,或者阳极/阴极是哪一个,但是硬件必须与软件匹配!对于图片,该行是该列上的“主要”。我的意思是,如果您查看这些步骤,则将一行设置为亮,而将某些列设置为为LED供电。怎么做?好吧,根据代码的不同,您需要做一个“显性的”,我这样做是通过让行函数每次行更改时都调用列函数来实现的。
由于有3个步骤,最终图像显示“您看到的内容” , 这是如何运作的?好吧,如果发生这种变化,每隔1毫秒说一次,那么人眼就无法分辨出差异,这与电视上的刷新率或每秒帧数非常相似。因此,实际上一次只能打开一排LED,但在眼睛上它们似乎一次都亮着。
当您添加更多的行和列时,多路复用率会进一步提高!假设您想要一个16 x 16的显示屏,即256个LED。使用16行,16列的多路复用,因此32个引脚可控制256个LED! 32仍然是很多数字引脚(Arduino只有12 。..),但是您可以在其中使用移位寄存器使用更少的引脚。
现在,这确实带来了一个问题,以便不断查看此图像。代码必须每隔几毫秒不断更改行,以便所有行都处于打开状态。因此,延迟等功能无法与多路复用一起使用。不幸的是,Arduino代码似乎严重依赖于延迟。..解决方案?使用最后一个示例中的Atmega328s计时器/计数器,您可以看到实现计时器之一的代码。
步骤3:制作多路复用原理图
您需要确定要作为阳极或阴极的行/列,但实际上并不重要。在示意图中,我选择了行作为阳极,列选择了阴极。
在示意图中,由于行是阳极,所以LED阳极的每一行都连接到阳极彼此。列的情况相同,LED的所有阴极都已连接。
多路复用与将LED直接连接至引脚的真正不同之处在于控制接地的方式。如果仅将LED连接到引脚,则LED的阴极通常连接到公共接地。通过多路复用电路,微控制器控制接地的可用性。这使您可以禁用整个行或列,因为该电路由于没有接地而无法完成。
在任何情况下,这都是理想的电路,但是对于阳极,您不一定需要一个晶体管。如果您想使用微控制器并从中汲取电流,则可以直接将引脚连接到LED的阳极。但是,这并不理想,因为您从微控制器汲取电流,就像我在步骤1中所说的那样,微控制器具有最大的电流供应。阳极不一定需要一个晶体管,但阴极必须有一个。您仍然需要启用/禁用地面才能使多路复用工作。
第二张图片显示的原理图与我在示例中使用的物理电路几乎相同。下一步将显示如何编写用于复用的程序。
步骤4:复用代码
要实现复用,您将需要编写代码以某种方式。实际上并没有那么复杂,可以说行在列上是“主要的”。这意味着单行晶体管导通,而该行的列运行一次。之后,您移至下一行并一次又一次地执行相同操作,直到重复为止!
刷新LED的速度不够快而无法注意到的问题是您无法拥有同步系统。这意味着您不能有长时间持续的延迟。因此,如果您有1秒的延迟,那么行和列所在的位置将只在整个整秒钟显示一次。
最简单的方法是使用两个函数,其中一个函数重复调用另一个函数。由于在这种情况下行是列的“主要”,我们将有两个函数可以调用它们:
-Display_LED()
-Column_Load()
所以这是一些sudo代码:
无效Display_LED(char a,char b,char c)
{
Column_Load(a);
digitalWrite(transistor_pin1,HIGH);
delay(1);
digitalWrite(transistor_pin1,LOW);
//根据行数重复
}
因此,上面的Display_LED函数是行的“显性”函数。同样,您可以使用行或列作为主导,这并不重要。首先,您调用列函数来设置这些晶体管的开或关。然后将某个行晶体管设置为高电平。我的延迟很短,所以LED亮了1ms。如果将其更改为1000毫秒,您实际上可以看到每个更改。这就是为什么您不能在程序的其余部分中使用延迟的原因。从那里关闭晶体管,并重复从a到b的代码,然后切换到第二行。
void Column_Load(char LEDs)
{
如果(LEDs_on == 0x07)
{
digitalWrite(colum1_transistor,HIGH)
digitalWrite(colum2_transistor,HIGH)
digitalWrite(colum3_transistor,HIGH)
}
}
此函数非常简单,具体取决于值参数是否已按照需要设置LED。如果您使用PORT_和DDR_,那么编写代码实际上比使用digitalWrites简单。在大多数情况下,我将vale设置为十六进制值,因此,如果我输入0x03,这意味着LED 1和3在2处于关闭状态时都打开。
下一步是使用上述以下功能的3x3 LED阵列示例。唯一的区别是行和列是相反的。
步骤5:3 x 3 LED显示示例
示例代码:
您可以使用以下代码查看带有LED指示灯的图片。该代码也作为.ino文件附加。点亮的LED由0x02,0x05,0x02设置。这些十六进制值的十进制表示形式是00000010,00000101,00000010。您可以查看这些值如何与显示匹配。
如果您想自己尝试一下,下面提供了代码,只需复制第3步中的电路即可!
/*晶体管多路复用3x3 LEDs
通过: Marty Peltz
日期:2013年7月19日
目的:使用多路复用以3x3模式控制9个LED。
用于Martin Peltz的Instructiable
*/
/****变量* ***/ char col1_cathode = 0;
char col2_cathode = 1; char col3_cathode = 2;
char row1_anode = 3;
char row2_anode = 4;
char row3_anode = 5;
void setup()
{
//将引脚设置为输出
pinMode(col1_cathode,OUTPUT);
pinMode(col2_cathode,OUTPUT);
pinMode(col3_cathode,OUTPUT) );
pinMode(row1_anode,OUTPUT);
pinMode(row2_anode,OUTPUT);
pinMode(row3_anode,OUTPUT);
//关闭所有GPIO引脚
digitalWrite(col1_cathode,LOW) );
digitalWrite(col2_cathode,LOW);
digitalWrite(col3_cathode,LOW);
digitalWrite(row1_anode,LOW);
digitalWrite(row2_anode,LOW);
digitalW rite(row3_anode,LOW);
}
无效循环()
{
display_LED(0x02,0x05,0x02);
}
/****显示LED功能* ***/
/*用途:使用要显示的十六进制参数调用此函数
*注意:此函数控制阴极,在我的情况下控制列
*/
void display_LED (字符c1,字符c2,字符c3)
{
row_anode(c1);//用第一个十六进制值调用row_anode
digitalWrite(col1_cathode,HIGH);//显示第一列
delay(1);//等待一小段延迟,以便LED亮起1ms
digitalWrite(col1_cathode,LOW);//禁用第一列,然后继续
row_anode(c2);//用第二个十六进制值调用row_anode
digitalWrite(col2_cathode,HIGH);//显示第二列
delay(1);//等待一小段延迟,以便LED点亮1ms。
digitalWrite(col2_cathode,LOW);//禁用第二列,然后继续
row_anode(c3);//用第二个十六进制值调用row_anode
digitalWrite(col3_cathode,HIGH);//显示第三列
delay(1);//等待一小段延迟,以便LED亮起1ms
digitalWrite(col3_cathode,LOW);//禁用第三列,然后继续操作
//(请注意,尝试将1ms更改为100ms-1s,您会看到不同)
}
/****阴极(列)功能** **/
/*目的:取参数值并打开相关的引脚
*注意:由于使用Arduinos digitalWrite,必须设置引脚,
*但是,如果使用DDRx/PORTx,则可以仅应用十六进制值,用于设置端口上的引脚。
*/ void row_anode(char LEDs_on)
{
if(LEDs_on == 0x00)
{
digitalWrite(row1_anode,LOW );
digitalWrite(row2_anode,LOW);
digitalWrite(row3_anode,LOW);
}
else if(LEDs_on == 0x01)
{
digitalWrite(row1_anode,HIGH) ;
digitalWrite(row2_anode,LOW);
digitalWrite(row3_anode,LOW);
}
否则if(LEDs_on == 0x02)
{
digitalWrite(row1_anode,LOW);
digitalWrite(row2_anode,HIGH);
digitalWrite(row3_anode,LOW);
}
否则if(LEDs_on == 0x03)
{
digitalWrite(row1_anode,HIGH);
digitalWrite(row2_anode,HIGH);
digitalWrite(row3 _anode,LOW);
}
否则if(LEDs_on == 0x04)
{
digitalWrite(row1_anode,LOW);
digitalWrite(row2_anode,LOW);
digitalWrite(row3_anode ,HIGH);
}
else if(LEDs_on == 0x05)
{
digitalWrite(row1_anode,HIGH);
digitalWrite(row2_anode,LOW);
digitalWrite(row3_anode, HIGH);
}
否则if(LEDs_on == 0x06)
{
digitalWrite(row1_anode,LOW);
digitalWrite(row2_anode,HIGH);
digitalWrite(row3_anode,HIGH );
}
否则if(LEDs_on == 0x07)
{
digitalWrite(row1_anode,HIGH);
digitalWrite(row2_anode,HIGH);
digitalWrite(row3_anode,HIGH) ;
}
}
步骤6:3 x 3 LED示例-多个显示器
扩展示例代码:
在此情况下,我通过设置Atmega328的寄存器实现了一个Timer。这允许1秒的计时器是异步的,因此不会造成显示延迟。要设置寄存器,您确实需要查看Atmega328的数据表。
当定时器中断每1秒关闭一次时,我将计数器增加3,以显示数组中的下一组值。数组具有要用于显示的值。
要查看示例,请查看附件。
步骤7:结论
我希望一旦您了解了复用的概念实际上非常简单,该指令就很有帮助。
我计划使另一个指令与移位寄存器进行复用。除了一些额外的编码,电路之外,它的复杂程度也没有太多,而且您可以使用更少的引脚!
责任编辑:wv
全部0条评论
快来发表一下你的评论吧 !