加入星計劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴散
  • 作品版權(quán)保護
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
    • 段碼液晶分類
    • 段碼液晶重要參數(shù)
    • 段碼液晶如何驅(qū)動
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

STM8L052C6單片機驅(qū)動段碼屏實例

11/01 10:12
1937
閱讀需 28 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

不得不吐槽一下,現(xiàn)在找點兒技術(shù)資料真是挺難的!就拿段碼液晶屏來說,這是一種很成熟而古老的技術(shù)。但是當(dāng)你項目里要用,想找點而資料,就會發(fā)現(xiàn),似乎唾手可得,可偏偏又會浪費掉很多時間。

就拿某著名搜索引擎來說,輸入段碼液晶一搜,首先得欣賞洋洋灑灑的廣告,然后一個個鏈接點進去,一會兒是只言片語,一會兒提醒打開另一個APP,一會兒要注冊后繼續(xù)瀏覽,有的更直接,要從此處過,留下買路財!唉,都人工智能時代了,怎么感覺有點兒人工智障。

吐槽完畢,跟大家做一些分享。如果用到時希望能節(jié)省點兒時間。段碼屏是一種廣泛使用的低成本,低功耗顯示設(shè)備,我們留心看一下就會發(fā)現(xiàn)不少。比如遙控器,電表,電子時鐘,電動汽車儀表盤。特別是在電池供電,而又需要顯示的場合,段碼液晶屏可以說是不二之選。我們簡要介紹一下段碼液晶屏的顯示原理,并以STM8L052給出一個上手即用的參考實例。

段碼液晶分類

斷碼液晶的基本顯示原理很簡單,就是利用液晶這種物質(zhì)在電場作用下會扭曲的特性,讓光線通過或不通過,從而實現(xiàn)顯示。它的技術(shù)也在不斷地進步,性能越來越好。主要分為下面幾大類:

TN(Twisted Nematic):

- 特點:TN扭轉(zhuǎn)式向列場效應(yīng)是將入射光旋轉(zhuǎn)90度。

這是最為常見的一種液晶顯示器件,制造成本相對較低,液晶分子偏轉(zhuǎn)速度快,響應(yīng)時間較快;但視角表現(xiàn)相對較弱,一般視角范圍在50度左右。

- 應(yīng)用場景:廣泛應(yīng)用于計算器、遙控器、電子鬧鐘等對視角要求不是特別高、顯示內(nèi)容較為簡單的小型電子設(shè)備中。

HTN(High Twisted Nematic):

- 特點:在TN液晶屏的基礎(chǔ)上進行了改進,液晶分子的取向扭轉(zhuǎn)角度更大,通常在110至130度。它的對比度有所提高,視角范圍也比TN更寬,可達到70度左右,并且具有功耗低、驅(qū)動電壓低等特點,但動態(tài)驅(qū)動性能較差。

- 應(yīng)用場景:適用于對視角范圍有一定要求,但對顯示效果要求不是特別高的設(shè)備,比如一些簡單的儀器儀表等。

STN(Super Twisted Nematic):

- 特點:顯示原理與TN相類似,但扭轉(zhuǎn)角度更大,可以實現(xiàn)更高的對比度和更豐富的色彩顯示。普通的STN液晶屏,液晶分子可以旋轉(zhuǎn)180-270度。不過,其響應(yīng)時間相對較長,在快速變化的畫面顯示上可能會有一定的滯后。

- 應(yīng)用場景:能夠滿足需要顯示較為復(fù)雜圖形或文字的需求,常用于一些中低端的電子設(shè)備,如電子詞典、早期的手機顯示屏等。

FSTN(Film Compensated Super Twisted Nematic):

- 特點:在STN的基礎(chǔ)上進一步優(yōu)化,通過在偏光片上增加補償膜來消除色散,實現(xiàn)更清晰的黑白顯示。其視角更寬,顯示效果更佳,對比度也較高。

- 應(yīng)用場景:適用于對顯示效果有較高要求的設(shè)備,如多功能電表、電力檢測儀器等。

VATN(Vertical Alignment Twisted Nematic):

- 特點:也稱為VA(BTN)液晶屏,具有更高的對比度和更寬廣的可視角度,顯示效果較為出色。

- 應(yīng)用場景:常用于一些高端顯示設(shè)備,不過由于其成本相對較高,應(yīng)用范圍相對較窄。

段碼液晶重要參數(shù)

視角

何為視角呢?以一掛時鐘來作為參考說明視角的方向,6 點為仰視,3點為左側(cè)視,9點為右側(cè)視,12點為俯視。行業(yè)內(nèi)的名詞參數(shù):6H,9H,3H,12H.也就是我們所說的6點鐘方向、9點鐘方向、3點 鐘方向、12點鐘方向的意思了。下圖為一個6點鐘視角的液晶示意圖。

視角范圍

視角范圍是指在某個特定視角內(nèi),圖像保持清晰的最大范圍。例如,TN材質(zhì)的段碼液晶屏視角范圍是50度,意味著在上下50度以內(nèi)圖像清晰?。

Segment

是組成液晶顯示圖案的基本單元。比如要顯示一個數(shù)字“8”,它是由多個段組成的,這些段通過組合可以形成不同的數(shù)字、字母或者簡單的圖形符號??梢园阉胂蟪善磮D的小碎片,通過點亮不同的片段組合出想要的形狀。

Common

公共電極。液晶顯示器的工作原理是通過在段電極SEG和公共電極COM之間施加電壓,來控制液晶分子的排列,從而實現(xiàn)顯示。多個segment會共享一個common電極,通過控制每個“segment”與“common”之間的電壓,就能控制各個“segment”是否顯示,以此來構(gòu)成完整的顯示內(nèi)容。

Duty

每個COM端掃描時間占一次完整掃描的比例,比如有4個COM,Duty就是1/4。

Bias

表明電極的驅(qū)動電壓有幾個電平。如1/3bias表明有VSS,1/3Vlcd,2/3Vlcd,Vlcd這4個電平。兩個相鄰電平之間的差是1/3Vlcd。這里Vlcd是段碼屏的工作電壓。

還要注意屏的工作電壓,和工作溫度范圍。

段碼液晶如何驅(qū)動

有的段碼屏自身集成驅(qū)動芯片,對外接口常用IIC,SPI等串行總線,這種屏成本稍高一些。有的屏不帶驅(qū)動芯片,對外接口為COM,和SEG引腳。驅(qū)動這種屏,需要用驅(qū)動芯片,如HT1621,CNV1792S等。段碼屏的每個段,點亮的條件是在COM和SEG引腳之間施加一個壓差,壓差超過一定門限就會點亮。但是要注意給液晶不能施加直流信號,比如COM加0V,SEG加3.3V,雖然這樣能顯示,但時間長了后會由于電泳現(xiàn)象導(dǎo)致液晶損壞,顯示模糊。正確的做法是,隔一小段時間就把電壓翻轉(zhuǎn)一次,COM加3.3V,SEG變?yōu)?V,這樣交替進行。

如果想更深入的了解原理和驅(qū)動方法,可以參考ST的一篇官方文檔:

AN3114 How to use the STM8AL3Lxx, STM8L152xx and STM8L162xx LCD controllers

寫的非常好。

    斷碼液晶實例

STM8L052C6是一款帶段碼液晶驅(qū)動模塊的單片機,提供了驅(qū)動庫,可以通過調(diào)用庫函數(shù),設(shè)置DUTY和BIAS,段碼顯示與否,調(diào)節(jié)對比度,閃爍頻率等。

我們用的這個段碼屏,是大連奇耘的QYT13264S(T)P10V3T,TN型,1/4Duty,1/3Bias,工作電壓3V。淘寶上可以買到,5塊錢左右。管腳圖,1-4管腳是COM0-COM3,5-13管腳是SEG0-SEG8。

下圖是屏和單片機的接線圖,stm8L052和stm8L152管腳兼容。注意VLCD這個引腳,如果配置段碼屏使用內(nèi)部電壓時,斷碼屏的工作電壓VLCD由內(nèi)部的升壓電路MCU電源VDD產(chǎn)生,VLCD外接一個0.1-2uF的小電容,可以使電壓更穩(wěn)定。此引腳的電壓可以在一定范圍內(nèi)通過程序調(diào)節(jié),從而改變屏的對比度。

下面是初始化的子程序

void LCD_GLASS_Init(void)

{

/* Enable LCD/RTC clock */

CLK_PeripheralClockConfig(CLK_Peripheral_RTC, ENABLE);

CLK_PeripheralClockConfig(CLK_Peripheral_LCD, ENABLE);

#ifdef USE_LSE

CLK_RTCClockConfig(CLK_RTCCLKSource_LSE, CLK_RTCCLKDiv_1);

#else

CLK_RTCClockConfig(CLK_RTCCLKSource_LSI, CLK_RTCCLKDiv_1);

#endif

/* Initialize the LCD */

LCD_Init(LCD_Prescaler_1, LCD_Divider_31, LCD_Duty_1_4,

LCD_Bias_1_3, LCD_VoltageSource_Internal);

/* Mask register

For declare the segements used.

in the Discovery we use 0 to 8 segments. */

// 使用0-8 segments

LCD_PortMaskConfig(LCD_PortMaskRegister_0, 0xFF);

LCD_PortMaskConfig(LCD_PortMaskRegister_1, 0x01);

LCD_PortMaskConfig(LCD_PortMaskRegister_2, 0x00);

/* To set contrast to mean value */

LCD_ContrastConfig(LCD_Contrast_3V0);

LCD_DeadTimeConfig(LCD_DeadTime_0);

LCD_PulseOnDurationConfig(LCD_PulseOnDuration_1);

/* Enable LCD peripheral */

LCD_Cmd(ENABLE);

}

//設(shè)置實例使用LCD_Duty_1_4, LCD_Bias_1_3代表1/4DUTY,1/3BIAS

//LCD_PortMaskRegister_0 設(shè)置LCD_PM0寄存器,啟用的SEG對應(yīng)位置1。

如何點亮一個液晶的段?比如小數(shù)點P。下面是實現(xiàn)的子程序

void LCD_GLASS_SetP(bool P ) // P "." 小數(shù)點

{

if(P)

LCD->RAM[LCD_RAMRegister_0] |= 0x10; // 亮 (7:0) LCD_RAM0第4位

else

LCD->RAM[LCD_RAMRegister_0] &= 0xEF; // 滅 (7:0) LCD_RAM0第4位

}

下圖LCD_RAM0寄存器 S0[7:0] (COM0 or COM4) 內(nèi)容的每一位的值對應(yīng)著圖5 COM0和SEG0-SEG7交叉位置的元素被點亮還是熄滅。

小數(shù)點P是COM0和PIN9交叉位置。PIN9 對應(yīng)的SEG為SEG4

LCD_RAM0=0x10;代表P(小數(shù)點) 元素被點亮。

其它元素的點亮原理與此相同

下面是電池電量顯示部分的子程序

void LCD_GLASS_SetT(uint8_t T) //電池電量顯示

{

switch (T)

{

case 0: //PD2_LCDSEG8

LCD->RAM[LCD_RAMRegister_1] &= 0xFE; //S9清零 S0(15:8) 外框

LCD->RAM[LCD_RAMRegister_4] &= 0xEF; //S10清零 S1(11:4)

LCD->RAM[LCD_RAMRegister_8] &= 0xFE; //S12清零 S2(15:8)

LCD->RAM[LCD_RAMRegister_11] &= 0xEF; //S11清零 S3(11:4)

break;

case 1: //PD2_LCDSEG8

LCD->RAM[LCD_RAMRegister_1] |= 0x01; //S9亮 S0(15:8) 外框

LCD->RAM[LCD_RAMRegister_4] |= 0x10; //S10亮 S1(11:4)

LCD->RAM[LCD_RAMRegister_8] &= 0xFE; //S12清零 S2(15:8)

LCD->RAM[LCD_RAMRegister_11] &= 0xEF; //S11清零 S3(11:4)

break;

case 2: //PD2_LCDSEG8

LCD->RAM[LCD_RAMRegister_1] |= 0x01; //S9亮 S0(15:8) 外框

LCD->RAM[LCD_RAMRegister_4] |= 0x10; //S10亮 S1(11:4)

LCD->RAM[LCD_RAMRegister_8] &= 0xFE; //S12清零 S2(15:8)

LCD->RAM[LCD_RAMRegister_11] |= 0x10; //S11亮 S3(11:4)

break;

case 3: //PD2_LCDSEG8

LCD->RAM[LCD_RAMRegister_1] |= 0x01; //S9亮 S0(15:8) 外框

LCD->RAM[LCD_RAMRegister_4] |= 0x10; //S10亮 S1(11:4)

LCD->RAM[LCD_RAMRegister_8] |= 0x01; //S12亮 S2(15:8)

LCD->RAM[LCD_RAMRegister_11] |= 0x10; //S11亮 S3(11:4)

break;

}

}

下面是字段S1 S2 S3 S4 顯示的子程序

void LCD_GLASS_SetS(bool S1,bool S2,bool S3,bool S4) // S1 S2 S3 "%"S4 " ℃"

{

if(S1)

LCD->RAM[LCD_RAMRegister_0] |= 0x04; // 亮 (7:0) 第2位

else

LCD->RAM[LCD_RAMRegister_0] &= 0xfB; // 滅 (7:0) 第2位

if(S2)

LCD->RAM[LCD_RAMRegister_0] |= 0x01; // 亮 S0(7:0) 第1位

else

LCD->RAM[LCD_RAMRegister_0] &= 0xfE; // 滅 S0(7:0) 第1位

if(S3)

LCD->RAM[LCD_RAMRegister_11] |= 0x04; // 亮 S3(11:4) 第1位

else

LCD->RAM[LCD_RAMRegister_11] &= 0xFB; // 滅 S3(11:4) 第1位

if(S4)

LCD->RAM[LCD_RAMRegister_7] |= 0x40; // 亮 S2(7:0) 第6位

else

LCD->RAM[LCD_RAMRegister_7] &= 0xBF; // 滅 S2(7:0) 第6位

}

3個數(shù)字的顯示需要一些技巧,下面是數(shù)字部分顯示的子程序

/* =========================================================================

LCD MAPPING

A



D

An LCD character coding is based on the following matrix:

{ S , G }

{ D , B }

{ E , F }

{ C , A }

The character '9' for example is:


LSB { 0 , 1 }

{ 1 , 1 }

{ 0 , 1 }

MSB { 1 , 1 }


The character '8' for example is:


LSB { 0 , 1 }

{ 1 , 1 }

{ 1 , 1 }

MSB { 1 , 1 }


The character '7' for example is:


LSB { 0 , 0 }

{ 0 , 1 }

{ 0 , 0 }

MSB { 1 , 1 }


The character '6' for example is:


LSB { 1 , 1 }

{ 0 , 0 }

{ 1 , 1 }

MSB { 1 , 1 }


The character '5' for example is:


LSB { 0 , 1 }

{ 1 , 0 }

{ 0 , 1 }

MSB { 1 , 1 }


The character '4' for example is:


LSB { 0 , 1 }

{ 0 , 1 }

{ 0 , 1 }

MSB { 1 , 0 }


The character '3' for example is:


LSB { 0 , 1 }

{ 1 , 1 }

{ 0 , 0 }

MSB { 1 , 1 }


The character '2' for example is:


LSB { 0 , 1 }

{ 1 , 1 }

{ 1 , 0 }

MSB { 0 , 1 }


The character '1' for example is:


LSB { 0 , 0 }

{ 0 , 0}

{ 1, 1 }

MSB { 0, 0 }


The character '0' for example is:


LSB { 0 , 0 }

{ 1 , 1}

{ 1 , 1 }

MSB { 1 , 1 }


*/

const uint8_t NumberMap[10]=

{

0xEE ,0x44 ,0xB6, 0xBA, 0x78, 0xDA, 0xDD, 0xA8, 0xFE, 0xFA

};

static void LCD_Conv_Char_Seg(uint8_t* c, uint8_t* digit)

{

uint16_t ch = 0 ;

uint8_t i,j;

switch (*c)

{

case 0:

case 1:

case 2:

case 3:

case 4:

case 5:

case 6:

case 7:

case 8:

case 9:

ch = NumberMap[*c];

break;

default:

break;

}

//下面是大連奇耘段碼屏的順序

digit[0] = (ch ) & 0x03;//D S 每個digit[ ]用最低兩位

digit[1] = (ch >> 2) & 0x03;//C E

digit[2] = (ch >> 4) & 0x03;//B G

digit[3] = (ch >> 6 ) & 0x03;//A F

}

//在第position位置 顯示1個* ch 字符

void LCD_GLASS_WriteChar(uint8_t* ch, uint8_t position) {

uint8_t digit[4]; /* Digit frame buffer */

LCD_Conv_Char_Seg(ch, digit);

switch (position)

{

case 1: //十位數(shù)字

LCD->RAM[LCD_RAMRegister_0] &= 0x0fd;

LCD->RAM[LCD_RAMRegister_0] |= (uint8_t)(digit[0]& 0x02); // 1D

LCD->RAM[LCD_RAMRegister_3] &= 0x0cf;

LCD->RAM[LCD_RAMRegister_3] |= (uint8_t)(digit[1]<<4 & 0x30); // 1C 1E

LCD->RAM[LCD_RAMRegister_7] &= 0x0fc;

LCD->RAM[LCD_RAMRegister_7] |= (uint8_t)(digit[2]&0x03); // 1B 1G

LCD->RAM[LCD_RAMRegister_10] &= 0xcf;

LCD->RAM[LCD_RAMRegister_10] |= (uint8_t)((digit[3]<<4)& 0x30); // 1A 1F

break;

/* Position 2 on LCD (Digit2)*/

case 2: //個位數(shù)字

LCD->RAM[LCD_RAMRegister_0] &= 0x0f7;

LCD->RAM[LCD_RAMRegister_0] |= (uint8_t)((digit[0]<<2)&0x08); // 2D

LCD->RAM[LCD_RAMRegister_3] &= 0x3f;

LCD->RAM[LCD_RAMRegister_3] |= (uint8_t)((digit[1]<<6) & 0xc0); // 2C 2E

LCD->RAM[LCD_RAMRegister_7] &= 0xf3;

LCD->RAM[LCD_RAMRegister_7] |= (uint8_t)((digit[2]<<2)& 0x0c); // 2B 2G

LCD->RAM[LCD_RAMRegister_10] &= 0x3f;

LCD->RAM[LCD_RAMRegister_10] |= (uint8_t)((digit[3]<<6)& 0xC0); // 2A 2F

break;

/* Position 3 on LCD (Digit3)*/

case 3: //小數(shù)點后1位數(shù)字

LCD->RAM[LCD_RAMRegister_0] &= 0xdf;

LCD->RAM[LCD_RAMRegister_0] |= (uint8_t)(digit[0]<<4) & 0x20; // 3D

LCD->RAM[LCD_RAMRegister_4] &= 0xfc;

LCD->RAM[LCD_RAMRegister_4] |= (uint8_t)(digit[1]) & 0x03; // 3C 3E

LCD->RAM[LCD_RAMRegister_7] &= 0xcf;

LCD->RAM[LCD_RAMRegister_7] |= (uint8_t)(digit[2]<<4)&0x30; // 3B 3G

LCD->RAM[LCD_RAMRegister_11] &= 0xfc;

LCD->RAM[LCD_RAMRegister_11] |= (uint8_t)(digit[3]) & 0x03 ; // 3A 3F

break;

default:

break;

}

}

//在主函數(shù)里調(diào)用上面子函數(shù)測試一下效果

void main(void)

{

uint8_tchar_tmp;

char_tmp = 1;

LCD_GLASS_WriteChar(&char_tmp, 1);

char_tmp = 2;

LCD_GLASS_WriteChar(&char_tmp, 2);

char_tmp = 3;

LCD_GLASS_WriteChar(&char_tmp, 3);

LCD_GLASS_SetT(2);

LCD_GLASS_SetS(1,1,1,1);

//LCD_GLASS_SetS(0,0,1,1);

LCD_GLASS_SetP(1) ;

}

下面是實際效果


參考:

記一次段碼屏調(diào)試總結(jié)

AN3114 How to use the STM8AL3Lxx, STM8L152xx and STM8L162xx LCD controllers(ST官方資料)

AN1447 SOFTWARE DRIVER FOR 4-MULTIPLEXED LCD WITH A STANDARD ST62(ST官方資料)

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

TopSemic,讓芯片使用更簡單。 專注分享:嵌入式,單片機,STM32,ARM,RTOS,Linux, 軟硬件,半導(dǎo)體,電子技術(shù)等相關(guān)內(nèi)容。