色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

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

          單片機(jī)引腳直接驅(qū)動(dòng)LCD

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

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

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

          本文引用地址:http://cafeforensic.com/article/201611/315606.htm

           
          這是我的程序:(因?yàn)閯倓傞_始用AVR,從最簡(jiǎn)單的開始,就直接用匯編了)
          Timer2用外接32768晶振提供時(shí)鐘,整個(gè)系統(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
           
          補(bǔ)充一下, 液晶屏的引腳與筆劃的對(duì)應(yīng)跟LED數(shù)碼管可能不一樣, 我這個(gè)屏是這樣的:
          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個(gè)公共端; 2,3控制第一個(gè)數(shù)字; 4,5第二個(gè); 7,8第三個(gè); 9,10第四個(gè)。

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

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

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



          評(píng)論


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

          關(guān)閉