使用 8 位 MCU、小型 BOM 和本文提供的可下載代碼來驅動多路復用 4 段 LCD 是一件簡單的事情。
無需微控制器上的專用 LCD 驅動器即可直接驅動 LCD,并且需要很少的額外資源。LCD 有兩種類型——靜態和多路復用。本文討論了多路復用 LCD 與 Zilog 的 Z8 Encore!? 微控制器的編程。
Z8 安可!閃存微控制器概述
Zilog 的 Z8 安可!產品基于 eZ8? CPU,并將閃存引入 Zilog 廣泛的 8 位微控制器系列。閃存在線編程能力允許更快的開發時間和現場程序更改。eZ8 內核的高性能、基于寄存器到寄存器的架構保持與 Zilog 流行的 Z8 MCU 的向后兼容性。
Z8 安可!MCU 將 20 MHz 內核與閃存、線性寄存器 SRAM 和大量片上外設組合在一起。這些外圍設備造就了 Z8 Encore!MCU 適用于各種應用,包括電機控制、安全系統、家用電器、個人電子設備和傳感器。
驅動液晶顯示器
靜態 LCD 具有用于 LCD 的每個段的單獨引腳和一個公共背板引腳。照亮分段的要求是使分段偏向背板。另一個要求是 LCD 不能讓直流電 (DC) 出現在段上。
為了防止段上出現直流,背板用低頻方波驅動,段相對于背板進行切換。
多路 LCD 具有多個背板,并且多個段之間共享一個段引腳。為了照亮特定的段,段引腳與背板相反驅動,未使用的背板保持空閑狀態。背板再次使用低頻方波驅動,以防止分段上的直流偏置。
挑戰
由于段的多路復用排列,對多路復用 LCD 進行編程可能是一項艱巨的任務。多路復用 LED 通常為每個 LED 數字配備一個單獨的背板。然而,多路復用 LCD 將其背板布置在數字的頂部、中間和底部。這種安排會使解碼過程變得非常復雜,但重要的是,即使具有專用 LCD 驅動器的微控制器仍然需要一個困難的解碼過程(見圖 1)。
圖 1:分段排列。
下一個工程任務與照亮一段所需的電壓有關。多路復用段的 ON 驅動電平降低了,因為該段大部分時間都處于空閑狀態,并且只有 25% 的時間被斷言。實際上,這句話意味著在較低的工作電壓下,一個段可能不會發光。
更復雜的情況是,當共享段引腳由當前活動的背板斷言時,段可以在其關閉狀態下感知電壓電位。隨著更多的背板被添加到顯示器,這些對比問題可能會變得更糟,因為每增加一個背板,可用的導通電壓就會降低,而剩余的關斷電壓會增加。
圖 2 顯示了每個背板的對比度如何降低,因為 ON 段和 OFF 段之間的差異較小。在圖 2 中,帶有一個背板的靜態顯示器在開啟電壓時接收其可用 Vcc 的 100%,在關閉電壓時接收 0%。在三平面示例中,V cc的一半可用于 ON 電壓,OFF 段接收 V cc的四分之一。LCD 因制造商而異,但典型閾值電壓為 2.3 V RMS。
圖 2:驅動電平。
由于只有一半的 V cc可用于導通電壓,因此很容易看出 3.3 V 微控制器如何無法直接驅動多路復用 LCD。本文的目的是展示您可以在 3 V Z8 Encore 上驅動多路復用 LCD!單片機。
硬件架構
要使用 3 V MCU 驅動多路復用 LCD,必須提高驅動電平。為了減少門數和復雜性,只對背板進行了提升。段驅動電壓擺動高于和低于 Vcc 的二分之一;因此,增強的背板信號必須使用 Z8 Encore 以相同的方式執行!MCU 的端口引腳作為兩個電荷泵,參考電壓為 V cc的二分之一。IC1,4050緩沖器用于提供電平轉換功能。
每個背板被驅動為高電平,并在其他平面被驅動時處于空閑狀態。該過程被反轉以去除任何直流分量,如圖 3 所示。
圖 3:背板波形。
通過在有源背板的相反方向上驅動段引腳來打開段,通過在有源背板的方向上驅動引腳來關閉段。在背板的空閑狀態期間,任何段上的電壓都低于閾值電壓。結果,這些段保持不亮。
軟件實施
由于 Z8 Encore 的額外速度和內存!家庭,假設開發發生在 C 編程語言中。如果軟件被編寫為易于移植,則用 C 編寫的應用程序可以輕松移植到不同的環境。
考慮到這一點,宏用于特定于 I/O 的操作,以便在將代碼移植到另一個設備時,大部分軟件將保持不變。
以下代碼段維護電荷泵。
/*電荷泵定義
電荷泵提升段驅動電壓并在每個定時器中斷時提供服務。正泵被拉低以充電并浮動到輸入狀態。充電時負泵懸空。電容以 1/2 VCC 為參考,電容器上的電荷似乎是 VCC +/- 參考。該宏還初始化端口的端口模式,因此它總是被刷新。
*/
#define ChargePumpsPDADDR=PxHD;
PDCTL|= B3|B4; PDOD&=~B3;
PDOD|=B4;PDADDR=PxOC;
PDCTL&=~(B3|B4); PDADDR=PxDDR;
PDCTL&=~(B3|B4)
#define FloatPumpsPDADDR=PxDDR; PDCTL|=B4|B3
以下宏管理背板驅動器。這些宏很復雜,因為每個背板只需要一個引腳,但每個背板需要兩個引腳狀態。
/*背板驅動器需要三種狀態:ON、OFF 和 IDLE。通過將 BP1 與 BP2、BP2 與 BP3 以及 BP3 與 BP1 混合,可以在每個平面上獲得所有三種狀態,而無需額外的引腳。
PlaneX123
_______________
BP11101
BP20110
BP31011
`BP10010
`BP21001
`BP30100
*/
#define SetUpBackplanePDADDR=PxOC;
PDCTL&=~(B0|B5|B6);
PDADDR=PxDDR;PDCTL&=~(B0|B5|B6)
#define BP1PDOD&=~B6; PDOD|=B0|B5
#define BP2PDOD&=~B5; PDOD|=B0|B6
#define BP3PDOD&=~B0; PDOD|=B6|B5
#define NotBP1PDOD&=~(B0|B5); PDOD|=B6
#define NotBP2PDOD&=~(B0|B6); PDOD|=B5
#define NotBP3PDOD&=~(B5|B6); PDOD|=B0
最后,用于驅動段的宏。
/*下一個宏獲取存儲在顯示緩沖區中的各個段并將它們放在端口上。它可以在沒有宏的情況下完成,但這使它更通用。將有六個平面和兩個緩沖區,因為有超過 8 個段*/
#define DisplaySegmentsPAOD&=~0xF8;
PAOD|=(緩沖區[平面]&0x00F8); PCOD=0;
PCOD|=((緩沖區[平面]&0x7F00)》》8)
如前所述,多路 LCD 中涉及的困難編程是一種相當不尋常的多路復用方案。前面的宏只是將先前解碼的段從緩沖區放到端口上。由于解碼過程如此復雜,它不在中斷服務程序 (ISR) 中執行。ISR 必須盡可能短;ISR 中所需的只是設置背板和驅動段。緩沖區是一個整數數組,其中包含我們顯示中使用的 12 個段。該數組中的一維是平面。此維度中有六個平面,每個背板狀態一個:A、B、C、A‘、B’ 和 C‘。解碼過程完成后,緩沖區必須加載跨越六個平面的 12 段數據。
解碼的第一步是定義字符的顯示方式。此定義適用于所有七段顯示器。因此,可以重用以下代碼段。
#define Dig_0Seg_a | 段_b | 段_c | 段_d | 賽段 | Seg_f
#define Dig_1Seg_b | Seg_c
#define Dig_2Seg_a | 段_b | 段_g | 賽段 | Seg_d
#define Dig_3Seg_a | 段_b | 段_g | 段_c | Seg_d
#define Dig_4Seg_f | 段_g | 段_b | Seg_c
#define Dig_5Seg_a | 段_f | 段_g | 段_c | Seg_d
#define Dig_6Seg_a | 段_f | 段_g | 段_c | 段_d | Seg_e
#define Dig_7Seg_a | Dig_1
#define Dig_8Seg_g | Dig_0
#define Dig_9Seg_a | 段_f | 段_g | 段_b | Seg_c
#define Dig_ASeg_a | 段_b | 段_c | 段_g | 賽段 | Seg_f
#define Dig_bSeg_f | 賽段 | 段_g | 段_d | Seg_c
#define Dig_CSeg_a | 段_f | 賽段 | Seg_d
#define Dig_dSeg_b | 段_c | 段_d | 賽段 | 說_g
#define Dig_ESeg_a | 段_f | 賽段 | 段_d | Seg_g
#define Dig_FSeg_a | 段_f | 賽段 | Seg_g
#define Dig_gSeg_a | 段_f | 段_g | 段_b | 段_c | Seg_d
#define Dig_hSeg_g | 段_c | 賽段 | Seg_f
#define Dig_IDig_1
#define Dig_JDig_1 | Seg_d
#define Dig_LSeg_d | 賽段 | Seg_f
#define Dig_nSeg_c | 賽段 | Seg_g
#define Dig_ODig_0
#define Dig_PSeg_g | 段_a | 段_b | 賽段 | Seg_f
#define Dig_rSeg_g | 賽段 | Seg_f
#define Dig_SSeg_g | 段_a | 段_c | 段_d | Seg_f
#define Dig_tSeg_g | 賽段 | 段_f | Seg_d
#define Dig_USeg_b | 段_c | 段_d | 賽段 | Seg_f
這些段分散在三個獨立的背板上,并且必須以三個比特的三個數據包的形式排列在一個字節中。最后一位未使用。這種排列反映了顯示數字的物理布局(見表 1)
表 1:段分配。
#define Seg_a1
#define Seg_g2
#define Seg_d4
#define Seg_b8
#define Seg_c16
#define Seg_dp32
#define Seg_f64
#define Seg_e128
我們的目標是將分段數據放入三個整數中——每個顯示背板一個。軟件必須將代表七段字符的單個字節分成三個平面的三個段。表 2 指示整數數組如何存儲各個段位。
由于 LCD 的每個數字都需要三個段,因此尋址正確的段引腳需要將每個數字的數據移位三位。最后,必須尋址微控制器的正確物理引腳。以下代碼段中的分配可以根據電路板布局和其他資源進行更改。
#define Seg_1AGD8//PAOD|=B3
#define Seg_1BCDP16//PAOD|=B4
#define Seg_1FE32//PAOD|=B5
#define Seg_2AGD64//PAOD|=B6
#define Seg_2BCDP128//PAOD|=B7
#define Seg_2FE256// PCOD |=B0
#define Seg_3AGD512//PCOD|=B1
#define Seg_3B??CDP1024//PCOD|=B2
#define Seg_3FE2048//PCOD|=B3
#define Seg_4AGD4096//PCOD|=B4
#define Seg_4BCDP8192//PCOD|=B5
#定義 Seg_4FE16384//PCOD|=B6
以下代碼段確定哪些段為特定字符打開。
for (digit=0, shift=9; digit《4; digit++,shift-=3)
{
段[0]|=(0x07 &
CharTbl[que[digit]])《
段[1]|=((0x38 & CharTbl[que[dig
它]])》》3)《
段[2]|=((0x1C0 & CharTbl[que[di
混帳]])》》6)《
}
存儲正確的段以打開需要測試每個單獨的位。優點是代碼變得非常可移植,如下所示:
對于(平面=0;平面《3;平面++)
{
如果(段[平面]&B0)
緩沖區[平面]|=Seg_1AGD;
如果(段[平面]&B1)
緩沖區[平面]|=Seg_1BCDP;
如果(段[平面]&B2)
緩沖區[平面]|=Seg_1FE;
如果(段[平面]&B3)
緩沖區[平面]|=Seg_2AGD;
等等
}
/*我們在這里有一個賦值,而不是在上面的語句中設置單個變量,因為在收集段時會發生計時器 IRQ,這將導致顯示閃爍。最后三個緩沖區只是前三個緩沖區的補充。*/
緩沖區[0]=臨時緩沖區[0];
緩沖區[1]=臨時緩沖區[1];
緩沖區[2]=臨時緩沖區[2];
緩沖區[3]=~緩沖區[0];
緩沖區[4]=~緩沖區[1];
緩沖區[5]=~緩沖區[2];
總結
直接驅動 LCD 所需的實際代碼并不是很復雜。在這個 C 示例中,解碼各個分段平面所需的時間僅為 141 μs。優點是無需額外的 LCD 驅動器或使用帶有專用驅動器的微控制器即可直接驅動超大顯示器。唯一的缺點是電荷泵和背板驅動需要額外的引腳,但在大多數情況下,額外的引腳比專用驅動器便宜。
圖 4 顯示了使用 Z8 Encore 的 LCD 驅動器的示意圖!單片機。
圖 4:使用 Z8 Encore 的 LCD 驅動器示意圖!單片機。
評論
查看更多