新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 單片機引腳直接驅(qū)動LCD

單片機引腳直接驅(qū)動LCD

作者: 時間:2016-11-18 來源:網(wǎng)絡(luò) 收藏

LED數(shù)碼管的驅(qū)動是比較簡單也容易理解的,多位數(shù)碼管一般是LED陣列的形式,每個數(shù)字使用一個公共端,不同數(shù)字的對應(yīng)同筆段使用一個控制端;驅(qū)動采用分時掃描沒個數(shù)字位,動態(tài)顯示。但是LED比較費電,我想做一個用電池供電的鐘,用發(fā)光管電池就撐不了多久了。于是我考慮用液晶。
在這邊的電子市場我買到一個4位筆段式液晶屏,4個數(shù)字最中間有冒號,邊上還有幾個箭頭符號,一共有15個引腳,正合適用AVR來驅(qū)動做一個鐘。
筆段式LCD屏的結(jié)構(gòu)與LED數(shù)碼管很相似,但是由于是液晶,工作機理上不同,驅(qū)動方式也有很大差異:
(1) LED有正負之分,液晶筆劃沒有。
(2) LED在直流電壓下工作,液晶需要交流電壓,防止電解效應(yīng)。
(3) LED需要電流提供發(fā)光的能量,液晶筆劃顯示狀態(tài)下電流非常微弱。
(4) LED對微小電流不反應(yīng),液晶則很敏感。
不難看出,用LED的驅(qū)動方式來對待LCD屏是行不通的。我在買回來測試這塊屏之前沒有意識到,于是走了不少的彎路。與LED驅(qū)動不同的是需要給每個筆劃加上一個交流電壓。一般用30-60Hz的方波就可以了,頻率再低顯示會有所波動,頻率高了功耗也會增加,因為LCD對電路呈現(xiàn)容性。而且,正負電壓都可以“點亮”液晶。
好在AVR的I/O口可以三態(tài)輸出,也就是除了高/低電平,還可以呈現(xiàn)高阻抗,相當(dāng)于斷開連接。于是我想到了這樣的辦法:不需要顯示的那一組筆劃對應(yīng)的公共端懸空(I/O口選擇三態(tài)),那么就不會加上電壓了。照這個思路,我的實驗電路焊好,出來的顯示卻是一團糟:筆劃都黑了看不清。我這才考慮到液晶本身的問題:阻抗高,而且有電容,是不可一邊懸空的!這個道理也許跟CMOS輸入端差不多。查找了一些關(guān)于液晶的資料,大致知道LCD屏不是那么簡單的,驅(qū)動方式通常是1/N, 也就是電壓不止高低兩檔??墒?strong>單片機I/O沒有那么多輸出狀態(tài)可以選擇。
1/2 Bias驅(qū)動
不顯示的液晶筆劃兩端電壓相等,顯示的不等。這樣一個要求在掃描方式
下不能滿足,于是改為電壓等級不同。1/2 Bias驅(qū)動就是這樣的,如下:
COM1 V+ ---- ----
1/2 ---- ---- ---- ----
GND ---- ----
COM2 V+ ---- ----
1/2 ---- ---- ---- ----
GND ---- ----
SEG1 V+ -------- --------
1/2
GND -------- --------
SEG2 V+ ---- -------- ----
1/2
GND -------- --------
如此,在 COM1,SEG1 選擇的筆劃上,加上的電壓為 -1/2, -1, +1/2, +1 ... 在 COM1,SEG2 選擇的筆劃上,加上的電壓為 +1/2, -1, -1/2, +1 ... 在 COM2,SEG1 選擇的筆劃上,加上的電壓為 -1, -1/2, +1, +1/2 ...在 COM2,SEG2 選擇的筆劃上,加上的電壓為 0, -1/2, 0, +1/2 ...
計算一下大致的平均功率(如果液晶灰度與電壓平方成正比,實際不是這樣)前三者是一樣的,都是 1+(1/2)^2=5/4, 對于最后一個 0+(1/2)^2=1/4 因此顯示的功率比為 5:1, 顯示狀態(tài)會是這樣:
SEG1 SEG2
: :
COM1 - - - O - - - O
: :
COM2 - - - O - - - x
AVR I/O沒有能力輸出 1/2 Vcc 的電壓(ADC在這里就不要考慮了, 浪費I/O還不如用靜態(tài)液晶屏), 因此沒有辦法實現(xiàn)真正的 1/2 Bias驅(qū)動。但是注意到要提供一個一半電源電壓也不是難事,既然AVR I/O口可以三態(tài),我們用兩個電阻分壓將端口“拉”到1/2 Vcc就好了,于是,1/2 Bias驅(qū)動的做法可以這樣:
Vcc
|
[ ]
[ ] 1Meg
[ ]
|
Port pin-----+------------ to LCD COMx
|
[ ]
[ ] 1Meg
[ ]
|
GND

取電阻 1Meg 是綜合耗電與分壓效果考慮的。這樣在 COMx 就可以產(chǎn)生三種電壓值,就達到了1/2 Bias動態(tài)驅(qū)動的目的。實現(xiàn)起來在前面的基礎(chǔ)上增加電阻即可,我的屏有4個公共端,因此用了8個電阻,數(shù)字就能夠顯示出來了。
雖然顯示的確做到了,然而效果卻不能讓我滿意。具體表現(xiàn)就是需要正對著LCD屏看才是很清晰的;如果斜著看,就可能一片混濁了,沒有達到實用。用2節(jié)Ni-MH供電時候正著看沒問題,用2節(jié)干電池(電壓提高一點)就不是很清晰了。如前面的分析,那些沒有被選擇的筆段其實也加上了變化的電壓,只不過與選擇的比段相比電壓平均有效值低一些。這兩個的差異足夠顯著,才能保證顯示效果。
再分析 1/2 Bais 驅(qū)動在我的LCD屏上 1/4 分時掃描的結(jié)果:一個周期內(nèi),“點亮”的筆段平均功率=1^2+(1/2)^2+(1/2)^2+(1/2)^2=7/4, 而沒有被“點亮”的筆段為=0+(1/2)^2+(1/2)^2+(1/2)^2=3/4, 兩者之比 7:3
跟前面的例子分析對比看出,從 1/2 分時掃描變到 1/4 分時掃描,顯出來的筆段和不顯的筆段上,電壓產(chǎn)生平均功率的對比從 5:1 變到 7:3 了。我嘗試從軟件上改變掃描時序,也不能改進顯示效果,看來 1/2 Bias 不夠用的了。
我查了Nokia 3310液晶手冊其中對于LCD電壓輸出時序的描述。恰好里面有一個圖,繪出了行和列控制線上的波形。從坐標(biāo)軸上看出Vlcd和Vss之間另外還有4個電壓等級。這么多種電壓用AVR I/O實現(xiàn)已經(jīng)不現(xiàn)實了。
我再考慮選用帶有LCD驅(qū)動功能的MCU, AVR只有一款A(yù)Tmega169, 封裝形式不適合DIY。Microchip有一款PIC16F913, 有28DIP的封裝,看上去正合適。暫時不知道價格,我先找來它的手冊看看。詳細看了LCD驅(qū)動模塊的部分,我發(fā)現(xiàn)PIC16F913也只有1/2 Bias驅(qū)動和1/3 Bias驅(qū)動兩種選項,分時最多為1/4分時驅(qū)動,對于我的屏正好。
1/3 Bias 驅(qū)動需要將Vcc--GND之間的電壓三等分,一個周期驅(qū)動波形示例如下:
COM1: V+ --------
2/3 --------
1/3 --------
GND --------
COM2: V+ --------
2/3 --------
1/3 --------
GND --------
SEG1: V+ --------
2/3 --------
1/3 --------
GND --------
SEG2: V+ --------
2/3 --------
1/3 --------
GND --------
在 (COM1,SEG1) 筆段上,電壓為 +1, -1/3, -1, +1/3 ... 在(COM1,SEG2)上為 +1/3, +1/3, -1/3, -1/3 ... 在(COM2,SEG1)上:+1/3, +1/3, -1/3, -1/3 ... 在(COM2,SEG2)上:-1/3, +1, +1/3, -1 ...
于是計算平均功率,在 (COM1,SEG1)和(COM2,SEG2)上面是 2*1^2+2*(1/3)^2=20/9 在(COM1,SEG2)和(COM2,SEG1)上面是 4*(1/3)^2=4/9, 兩者之比 5:1
假如不是上圖的 1/2 分時驅(qū)動而是 1/4 分時驅(qū)動,這個比例將變?yōu)?br />2*1^2+6*(1/3)^2 vs 8*(1/3)^2 = 3:1
若將原來的 1/2 Bias 改用 1/3 Bias 驅(qū)動,對于我的LCD屏這個比值從 7:3 改善為 3:1 了。既然PIC16F913只設(shè)計了 1/2 Bias與1/3 Bias,用起來應(yīng)該問題不大。
AVR單個I/O口要實現(xiàn)4種電壓輸出——不可能吧,我是想不出來了。AVR最多只有三種電壓輸出,能不能對這個電壓再做等分呢?一番思索之后我想這樣行不行:就4等分吧.
COM1: V+ --------
3/4
1/2 -------- --------
1/4
GND --------
COM2: V+ --------
3/4
1/2 -------- --------
1/4
GND --------
SEG1: V+
3/4 -------- ---------
1/2
1/4 ----------------
GND
SEG2: V+
3/4 ----------------
1/2
1/4 -------- ---------
GND
我的做法就是 SEGx 輸出有兩種:3/4*Vcc 和 1/4*Vcc, 而 COMy 輸出有三種:Vcc, GND, 1/2*Vcc. 對于每個I/O口,并不需要4種電壓輸出。當(dāng)然這樣跟1/3 Bias驅(qū)動是不一樣的,但是卻達到了 1/3 Bias 驅(qū)動的效果,只不過加在液晶筆段上的電壓絕對值最大不是 Vcc 而是 3/4*Vcc 了,因此電源電壓也需要提高。這里計算省略。
這種驅(qū)動方式我稱之為 "偽1/3 Bias驅(qū)動". 對于 COMy 的處理和前面一樣,對于 SEGx, 將I/O輸出電壓改變一下,高電平3/4*Vcc, 低電平1/4*Vcc就好了。我的做法是:
/-------------- I/O Port pin
|
[ ]
[ ] 1Meg
[ ]
|
to LCD SEGx --------------+
|
[ ]
[ ] 1Meg
[ ]
|
|
1/2 Vcc
這里的 1/2 Vcc 可以將電源電壓用電阻分壓得到,我想的辦法是直接接個幾uF電容到GND, 實驗是成功的。因為隨著掃描的進行,這個地方的平均電壓是輸出高電平和低電平的一半。
目前我做了一個Mega48V的秒計數(shù)器,再改改就能把鐘做出來了。

本文引用地址:http://butianyuan.cn/article/201611/315606.htm

 
這是我的程序:(因為剛剛開始用AVR,從最簡單的開始,就直接用匯編了)
Timer2用外接32768晶振提供時鐘,整個系統(tǒng)耗電大約30微安。
; lcddisplay.asm
; Test raw LCD display
.include "m48def.inc"
.org 0x0000
rjmp start
.org OC2Aaddr
rjmp isr_timer2
.org 0x0020
table:
.DB 0b11101101, 0b00101000, 0b10110101, 0b10111001
.DB 0b01111000, 0b11011001, 0b11011101, 0b10101000
.DB 0b11111101, 0b11111001
start:
ldi r16, 1<out MCUCR, r16 ; disable all I/O pull-up
ldi r16, 1 ldi r16, 1<sts TCCR2A, r16 ; CTC mode
ldi r16, 31
sts OCR2A, r16 ; preset compare A
ldi r16,1<; ldi r16,1<sts TCCR2B, r16
ldi r16, 1<out TIFR2, r16 ; clear flag
ldi r16, 1<sts TIMSK2, r16 ; enable interrupt on compare match A
ser r16
out DDRD, r16 ; Port D output -- LCD segment control
clr r5
ldi r16, 0x55
mov r6, r16
clr r7
clr r8
ldi r16, 9
mov r10, r16
mov r11, r16
mov r12, r16
mov r13, r16
dec r10
sei ; enable global interrupt
ldi r16, (1<out SMCR, r16 ; use Idle mode here, waiting 1 second
clr r2
iniw:sleep
dec r2
brne iniw
ldi r16, (1<out SMCR, r16 ; use power-save mode
nop
nop
clr r2
loop:
nop
nop
sleep
nop
nop
dec r2
dec r2
breq adjtime
rjmp loop
adjtime:
ldi r17, 10
inc r10
cp r10, r17
brne updcount
clr r10
inc r11
cp r11, r17
brne updcount
clr r11
inc r12
cp r12, r17
brne updcount
clr r12
inc r13
cp r13, r17
brne updcount
clr r13
updcount:
rcall calcor
rjmp loop
isr_timer2:
clr r16
out DDRC, r16 ; float all COMx pins
bst r4, 1
brts show34
bst r4, 0
brts show2
mov r0, r5
ldi r18, 1
rjmp sel
show2:
mov r0, r6
ldi r18, 1<<1
rjmp sel
show34:
bst r4, 0
brts show4
mov r0, r7
ldi r18, 1<<2
rjmp sel
show4:
mov r0, r8
ldi r18, 1<<3
sel:
bst r4, 2
brtc lcden
com r0
com r16
lcden:
out PORTC, r16
out PORTD, r0
out DDRC, r18
iext:inc r4
reti
calcor: ; translate R10~~R13 to R5~~R8
clr r5
clr r6
clr r7
clr r8
ldi ZH, high(table<<1)
ldi ZL, low(table<<1)
add ZL, r10
lpm ; load table data to R0
rcall filler
ldi ZL, low(table<<1)
add ZL, r11
lpm
rcall filler
ldi ZL, low(table<<1)
add ZL, r12
lpm
rcall filler
ldi ZL, low(table<<1)
add ZL, r13
lpm
rcall filler
ret
filler:
rol r0
rol r5
rol r0
rol r5
rol r0
rol r6
rol r0
rol r6
rol r0
rol r7
rol r0
rol r7
rol r0
rol r8
rol r0
rol r8
ret
 
補充一下, 液晶屏的引腳與筆劃的對應(yīng)跟LED數(shù)碼管可能不一樣, 我這個屏是這樣的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
< 1f 1a 2f 2a 3f 3a 4f 4a > -- ---- COM1
< 1g 1b 2g 2b 2g 3b 4g 4b > -- ---- COM2
< 1e 1c 2e 2c : 3e 3c 4e 4c > -- ---- COM3
1d 1h 2d 2h 3d 3h 4d -- ---- COM4
其中 12,13,14,15 是4個公共端; 2,3控制第一個數(shù)字; 4,5第二個; 7,8第三個; 9,10第四個。

############################################################

前年,有一個家用熱水器控制項目,硬件與軟件是分開搞的.為了省成本,硬件工程師不用專用液晶驅(qū)動IC,把我搞得夠嗆.整個項目20天時間,光液晶驅(qū)動程序用去了10多天.
I/O端口SEG與COM口分別串接一只電阻,再并聯(lián)一只電阻到地,

這樣,對液晶來講,I/O口是電源/地,定時改變SEG/COM的H/L電平,相當(dāng)于1/2VCC的交流信號.
當(dāng)SEG/COM同時為H或L電平時,對液晶來講,都是關(guān),SEG/COM電平不等時,段碼就能顯示出來.
明白了這個道理,用C語言寫出來不難.



評論


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

關(guān)閉