新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 設(shè)計(jì)二進(jìn)制時(shí)鐘: 理解多路復(fù)用約束

設(shè)計(jì)二進(jìn)制時(shí)鐘: 理解多路復(fù)用約束

作者: 時(shí)間:2024-03-25 來源:Digikey 收藏

設(shè)計(jì)一個(gè)是一個(gè)有吸引力的項(xiàng)目,它能讓您展示數(shù)字電子學(xué)、微控制器編程以及物理組裝和中等復(fù)雜電路的能力。關(guān)于這個(gè)主題,已經(jīng)有許多文章進(jìn)行了探討。然而,深入探討設(shè)計(jì)決策和必要的妥協(xié)的文章卻不多。這是一個(gè)遺憾,因?yàn)檫@個(gè)主題提供了一個(gè)極好的機(jī)會(huì)來探索微控制器的物理限制、歐姆定律的應(yīng)用、多路復(fù)用的遞減收益以及易于故障排除的組件布局。

本文引用地址:http://2s4d.com/article/202403/456771.htm

本文主要討論以形式呈現(xiàn)的六列四行 LED 矩陣,如圖1所示。為了最大的可訪問性,我們將把對(duì)話限制在 Arduino Nano Every 1上的I/O引腳和電源的物理功能上。請(qǐng)注意,本文中提出的想法直接適用于七段 LED 顯示器,或者更一般地說,適用于所有多路LED陣列。

現(xiàn)在是回顧操作的好時(shí)機(jī),因?yàn)槲覀儗⒅攸c(diǎn)關(guān)注底層硬件和多路復(fù)用方面。


image

image865×650 97.4 KB


圖 1 : Arduino Nano Every 在面包板上的圖片,背景是 LED 陣列和 Digilent Analog Discovery。

多路復(fù)用定義

多路復(fù)用是有限資源的一種時(shí)間共享形式。在我們的例子中,微控制器只有有限的I/O引腳。通過使用時(shí)分多路復(fù)用(TDM),我們能夠用循環(huán)序列連續(xù)激活LED或LED組。通過快速切換 LED 的激活狀態(tài),所有LED看起來都是一樣亮的。這種效果依賴于“閃爍融合”(flicker fusion),即人眼無法檢測到多路復(fù)用陣列中LED的快速切換。

LED通常以公共陽極或公共陰極的形式排列成組。圖2展示了一個(gè)具有6列4行 LED 矩陣和公共陽極配置的示例。

技術(shù)提示: 術(shù)語“時(shí)分多路復(fù)用”(TDM)通常與以太網(wǎng)等通信系統(tǒng)相關(guān)聯(lián)。在以太網(wǎng)中,許多電腦共享一個(gè)通信通道。由于信道是有限的資源,每臺(tái)計(jì)算機(jī)根據(jù)已建立的通信協(xié)議輪流使用。雖然我們將TDM這一術(shù)語應(yīng)用于LED多路復(fù)用是一種簡化,但它確實(shí)為我們理解復(fù)雜的通信系統(tǒng)提供了一個(gè)很好的起點(diǎn)。


image
image865×587 75.6 KB


圖 2 :采用Arduino Nano Every的6列4行復(fù)用LED矩陣示意圖。

公共陽極和公共陰極這兩個(gè)術(shù)語會(huì)引起混淆。例如,對(duì)圖2中的LED矩陣的檢查顯示,許多二極管按列共享陽極連接,按行共享陰極連接。只有當(dāng)我們檢查激活序列時(shí),才會(huì)發(fā)現(xiàn)共同的陽極配置。

圖3給出了多路復(fù)用器時(shí)序的邏輯分析儀視圖。關(guān)于公共二極管連接,我們注意到在任何給定時(shí)間有一個(gè)且只有一個(gè)列被激活。因此,共同連接是陽極。在本例中,關(guān)聯(lián)列晶體管將所有關(guān)聯(lián)led的陽極拉到5.0 VDC導(dǎo)軌上。單獨(dú)的行驅(qū)動(dòng)器然后應(yīng)用一個(gè)地來激活所需的LED(s)。

關(guān)于圖3,我們觀察到:

列驅(qū)動(dòng)信號(hào)呈現(xiàn)為Arduino D2到D7引腳對(duì)應(yīng)的前6個(gè)信號(hào)。為方便起見,已將信號(hào)名稱添加為紅色高亮文本。我們看到一個(gè),而且只有一個(gè),信號(hào)在任何時(shí)候都是活躍的。請(qǐng)注意,PNP晶體管被用作列驅(qū)動(dòng)器。另外,回想一下,這個(gè)晶體管將通過將其底座拉向地面來激活。

最低的4行是Arduino輸出引腳D19到D21對(duì)應(yīng)的行驅(qū)動(dòng)器。這些也是如圖2所示的低電平激活,其中二極管通過將其拉向地面打開。

Digilent Analog Discovery已配置為顯示與4行驅(qū)動(dòng)器相關(guān)的二進(jìn)制數(shù)。這是一些邏輯分析儀的一個(gè)功能,允許操作員將幾行“加入”成一個(gè)方便的ASCII, HEX或二進(jìn)制顯示。為了方便起見,我們用藍(lán)色突出顯示了這一點(diǎn)。

技術(shù)提示 :配置LED多路復(fù)用有兩種常用方法,包括公共陽極和公共陰極。本文的特點(diǎn)是PNP列驅(qū)動(dòng)器與共同陽極LED。在這里,PNP晶體管將公共陽極連接到正軌,然后將接地應(yīng)用到各個(gè)陰極。當(dāng)組件旋轉(zhuǎn)90度,將公共驅(qū)動(dòng)器應(yīng)用于行而不是列時(shí),需要仔細(xì)檢查。


image
image865×300 99.6 KB


圖 3 :邏輯分析儀屏幕截圖顯示了帶有測試和高光的LED定時(shí)。

技術(shù)提示 :關(guān)于多路復(fù)用和共陽極/陰極的討論適用于七段LED顯示器和LED陣列。

當(dāng)前的限制

本文受到Arduino Nano Every功能的限制。這既包括可用的電源,也包括Nano Every的板載電源、單個(gè)引腳和引腳組。

具有ATMega4809微控制器規(guī)格的相關(guān)Arduino Nano Every是:

ABX00028-datasheet.pdf (arduino.cc)

  • 5.0直流電源電流限制= 950毫安

  • 單個(gè)引腳(源或匯)= 40毫安

  • 電源軌引腳(在高溫下)= 100毫安

對(duì)于選用的SSL-LX2573GDLED燈:

  • 室溫穩(wěn)定電流= 25毫安

  • 10 us脈沖的峰值電流= 150毫安

這些數(shù)字中的大多數(shù)是絕對(duì)設(shè)計(jì)最大額定值。為了長壽命,我們必須保持較寬的安全裕度。作為起點(diǎn),我們把每一個(gè)電流值減半。我們將看到,這個(gè)決定對(duì)復(fù)用選項(xiàng)有嚴(yán)重的影響。它在圖2原理圖上投下陰影,對(duì)晶體管列驅(qū)動(dòng)器和多路復(fù)用led的數(shù)量產(chǎn)生影響。

技術(shù)提示 :微控制器的內(nèi)部芯片使用小鍵合線連接到I/O引腳。這些線與硅走線一起具有有限的載流能力。這反映在器件的設(shè)計(jì)最大規(guī)格上。在前面的例子中,我們看到單個(gè)I/O引腳具有40 mA的設(shè)計(jì)最大值。然而,三個(gè)這樣的引腳在最大電流下工作將壓倒模對(duì)電源或模對(duì)地的鍵合線或硅走線。這種累積電流是一個(gè)重要但經(jīng)常被忽視的設(shè)計(jì)考慮因素。這是一個(gè)會(huì)破壞微控制器的錯(cuò)誤,也許不會(huì)立即破壞,但會(huì)導(dǎo)致產(chǎn)品不可靠。

占空比vs亮度

在解釋晶體管列驅(qū)動(dòng)器和電阻選擇之前,我們需要理解閃爍與LED亮度之間的關(guān)系。請(qǐng)記住,LED矩陣是采用時(shí)分多路復(fù)用(TDM)的。每個(gè)LED都會(huì)“閃爍”,因?yàn)樗鼤?huì)依次打開和關(guān)閉,如圖3中的時(shí)序圖所示。您可能已經(jīng)進(jìn)行過相關(guān)的實(shí)驗(yàn),探索了LED的閃爍現(xiàn)象。

在您學(xué)習(xí) Arduino 的早期階段,您可能已經(jīng)使用 PWM 命令來調(diào)整 LED 的亮度,例如:

void loop() {
    static uint8_t val;             // Maintain contents across loop iterations
    analogWrite(LED_PIN, val++);    // About 5 seconds to reach 100% duty cycle
    delay(20);
}

這個(gè)PWM操作與TDM操作直接相關(guān),當(dāng)我們考慮對(duì)單個(gè)LED的影響時(shí)。在兩種情況下,LED都會(huì)以一定的時(shí)間開啟和關(guān)閉,并且這種開啟和關(guān)閉的時(shí)間比例決定了LED的亮度。

結(jié)果如圖4所示,LED分別以100%、50%、25%、12.5%和6.25%的占空比工作,這分別對(duì)應(yīng)于TDM槽的1、2、4、8和16個(gè)時(shí)間段。對(duì)于低占空比的LED,結(jié)果并不理想。事實(shí)上,很難看到占空比為1/16的LED。


image
image865×648 57.2 KB


圖 4 :不同占空比下led的相對(duì)亮度。

多路復(fù)用的方法

我們的多路復(fù)用目標(biāo)是獲得最大的LED亮度,同時(shí)保持在當(dāng)前的硬件限制內(nèi)?,F(xiàn)在我們對(duì)硬件的物理限制有了更好的了解,我們可以探索復(fù)用方法:

  • 一次一個(gè)LED:我們可以消除列驅(qū)動(dòng)器,并允許微控制器直接控制列和行。雖然這對(duì)于電路成本和簡單性來說是非常理想的,但我們很快就遇到了當(dāng)前的限制。如果沒有列驅(qū)動(dòng)器,相關(guān)的微控制器引腳必須提供必要的電流。這限制了我們一次只能使用一個(gè)或兩個(gè)LED,因?yàn)槔鄯e電流將超過微控制器設(shè)計(jì)的最大值。考慮到6 x 4陣列,這需要4%或8%的占空比。LED會(huì)很暗。

  • 每次一列,由微控制器控制列驅(qū)動(dòng)器和行:使用PNP晶體管向列提供電流,我們可以自由地打開所有行。給定6 × 4陣列,這導(dǎo)致每個(gè)LED的占空比為17%。本文中給出的結(jié)果對(duì)于光線昏暗的房間來說是最低限度可接受的。

  • 用列、行驅(qū)動(dòng)晶體管一次一列。這種方法允許LED以高于微控制器容量的電流驅(qū)動(dòng)。由于LED具有低占空比,因此可以通過增加電流來增加亮度。在LED數(shù)據(jù)表中有一定的模糊性,然而,電流肯定可以增加到設(shè)計(jì)最大值,也許是2倍以上,而不會(huì)損壞LED?;叵胍幌?,我們選擇的LED指定為連續(xù)25 mA和150 mA, 10 us脈沖。這種方法需要仔細(xì)考慮LED溫度,并可能導(dǎo)致LED壽命顯著縮短。使用風(fēng)險(xiǎn)自負(fù)。

  • 并行控制:對(duì)于這篇文章,我們假設(shè)微控制器引腳是有限的資源。有任何數(shù)量的端口擴(kuò)展選項(xiàng),將允許直接控制LED。一個(gè)例子是8位TLC6C598移位寄存器。它具有50mA開漏驅(qū)動(dòng)器,最大VDS為40 VDC。74HC595是另一種適用于面包板原型設(shè)計(jì)的常見選擇。

電阻的選擇

需要選擇合適的電阻來確定 LED 的工作電流。為柱驅(qū)動(dòng)晶體管的基極選擇合適的電阻也很重要。當(dāng)激活LED 的數(shù)量隨著顯示的數(shù)量變化時(shí),這個(gè)基極電阻對(duì)于保持一致的 LED 亮度很重要。

LED 的計(jì)算相對(duì)簡單。第一步是確定當(dāng)前的局限性。使用所選的多路復(fù)用方案,在任何給定時(shí)間最多可激活4個(gè)LED。我們遇到的第一個(gè)限制是微控制器的累積電流。對(duì)于保守的設(shè)計(jì),這是50mA。因此,每個(gè)LED被限制在約13 mA。電阻器計(jì)算為:

image

這里我們假設(shè)PNP列驅(qū)動(dòng)器VCE非常接近于零。
對(duì)于晶體管基極電阻的計(jì)算,我們將實(shí)現(xiàn)一個(gè)強(qiáng)制的beta條件。這個(gè)晶體管工作點(diǎn)確保晶體管深度飽和,這將確保所有LED具有相同的亮度。為了設(shè)置這個(gè)條件,我們選擇電阻器,使基極電流為集電極電流的1/10。給定4個(gè)有源LED,集電極電流約為50 mA。通過強(qiáng)制beta操作,我們將強(qiáng)制基極電流為5mA。

image

改進(jìn)空間

這篇文章的重點(diǎn)是多路LED的各個(gè)方面。很少甚至沒有考慮將設(shè)備作為可靠的計(jì)時(shí)器來操作。本說明所附的代碼使用了 Arduino millis() 函數(shù),該函數(shù)不被稱為可靠的實(shí)時(shí)計(jì)時(shí)器。所有這些設(shè)備都依賴于微控制器的高速振蕩器,它不像正確實(shí)現(xiàn)的32.768 kHz時(shí)鐘晶體那樣精確。

為了提高性能,你可能想要集成一個(gè)實(shí)時(shí)時(shí)鐘模塊。對(duì)于一個(gè)額外的挑戰(zhàn),可以嘗試一個(gè)基于 GPS 或 WWVB (原子鐘接收器)的帶天線的計(jì)時(shí)器。

#define C0_PIN 2

#define C1_PIN 3

#define C2_PIN 4

#define C3_PIN 5

#define C4_PIN 6

#define C5_PIN 7

#define R0_PIN 21

#define R1_PIN 20

#define R2_PIN 19

#define R3_PIN 18

void set_column(uint8_t c) {

  digitalWrite(C0_PIN, HIGH);

  digitalWrite(C1_PIN, HIGH);

  digitalWrite(C2_PIN, HIGH);

  digitalWrite(C3_PIN, HIGH);

  digitalWrite(C4_PIN, HIGH);

  digitalWrite(C5_PIN, HIGH);

  switch (c) {

    case 0: digitalWrite(C0_PIN, LOW); break;

    case 1: digitalWrite(C1_PIN, LOW); break;

    case 2: digitalWrite(C2_PIN, LOW); break;

    case 3: digitalWrite(C3_PIN, LOW); break;

    case 4: digitalWrite(C4_PIN, LOW); break;

    case 5: digitalWrite(C5_PIN, LOW); break;

    default: break;

  }

}

void set_row(uint8_t n) {

  bool D0 = ((n & 0x01) == 0);

  bool D1 = ((n & 0x02) == 0);

  bool D2 = ((n & 0x04) == 0);

  bool D3 = ((n & 0x08) == 0);

  digitalWrite(R0_PIN, D0);

  digitalWrite(R1_PIN, D1);

  digitalWrite(R2_PIN, D2);

  digitalWrite(R3_PIN, D3);

}

void set_LED(uint8_t c, uint8_t n) {

  set_column(c);

  set_row(n);

}

void setup() {

  pinMode(C5_PIN, OUTPUT);

  pinMode(C4_PIN, OUTPUT);

  pinMode(C3_PIN, OUTPUT);

  pinMode(C2_PIN, OUTPUT);

  pinMode(C1_PIN, OUTPUT);

  pinMode(C0_PIN, OUTPUT);


  pinMode(R3_PIN, OUTPUT);

  pinMode(R2_PIN, OUTPUT);

  pinMode(R1_PIN, OUTPUT);

  pinMode(R0_PIN, OUTPUT);

}

void loop() {

  uint8_t i;

  uint32_t now = millis() /1000;

  uint8_t seconds = now % 60;

  uint8_t minutes = (now / 60) % 60;

  uint8_t hours = (now / 3600) % 24;

  uint8_t hoursHigh = hours / 10;

  uint8_t hoursLow = hours % 10;

  uint8_t minutesHigh = minutes / 10;

  uint8_t minutesLow = minutes % 10;

  uint8_t secondsHigh = seconds / 10;

  uint8_t secondsLow = seconds % 10;

  for (i = 0; i < 6; i++) {

    switch (i) {

      case 0: set_LED(0, secondsLow); break;

      case 1: set_LED(1, secondsHigh); break;

      case 2: set_LED(2, minutesLow); break;

      case 3: set_LED(3, minutesHigh);break;

      case 4: set_LED(4, hoursLow); break;

      case 5: set_LED(5, hoursHigh); break;

      default: break;

    }

    delay(2);

  }

}



評(píng)論


技術(shù)專區(qū)

關(guān)閉