熱門關鍵詞: 蘇州控制板生產廠家 液晶模塊種類 LCD液晶屏工作原理 什么是LED背光源
________________________________________
用IO口驅動段式LED(數碼管)的方法相信大家比較清楚,但用IO口直接驅動段式LCD的方法相對復雜一些。
1. LCD和LED的顯示原理不一樣:LED是加正向電壓發光,而LCD得交替加正、反向電壓才會持續顯示(可以做個實驗,如果把恒定電壓加到LCD的一段上,該段會顯示一下,但馬上不能顯示,而且長時間加恒定電壓,會加速LCD的老化和損壞)
2. 常聽說1/2bias,1/3bias LCD,是什么意思呢?對于1/2bias LCD,假如LCD的顯示電壓是3V,則1/2bias是1.5V,也就是說在±3V電壓作用時,LCD有顯示;±1.5V及以下的電壓作用時沒有顯示
3. 普通單片機IO口不能直接輸出半高電平(1.5V),但可以用相等的上下拉電阻實現,當IO口設置為輸入(高阻)時,由于上下拉電阻的分壓作用,則產生一個半高電平(1.5V)
知道了以上3點后,動態驅動LCD就不是難事了,對于4*8段的LCD(4個COM,8個SEG,顯示電壓為3V,1/2bias),驅動方法如下:
1、 四個COM采用交替掃描的方式,每個COM在相鄰兩次掃描時又進行電壓交變的方式。
2、 若掃描到某一個COM時,該COM輸出3V(0V):
與該COM相連的SEG輸出與COM相反,ΔV=±3V,則該相連點亮;
與該COM相連的SEG輸出與COM相同,ΔV=0,則該相連點不亮。
3、其他沒有掃描到的COM,單片機IO口為輸入,從而產生1/2 bias(1.5V),不管SEG為何值,ΔV<±1.5V,故該點不亮。
用4*8段的LCD自制了一個數字鐘表,驗證了以上方法的可行性,現把制作過程羅列如下
1. 原理圖
說明:由于管腳不夠用,所以時鐘芯片DS1302的RST和LCD的一個SEG是復用的,只要在這個SEG無效的時候去讀取時間就可以了,另外,3PIN串口是ISP下載程序用的。
2. 備料
3. 焊接
4. 實驗結果
5. 不足之處
通過實驗結果可以發現,不顯示的SEG也有陰影
原因分析:紐扣電池電壓3.7V,1/2bias是1.85V,大于1.5V,所以會出現陰影。
解決辦法:選擇工作電壓小于3V的單片機和電壓等于3V的電池(如2節干電池)
6. 程序源代碼
點擊http://www.dzsj.net/dpjzhyy/clock.c下載
代碼
/******************************************************************
段式LCD驅動實驗
外部晶體:12MHz
日期:2011.08.26
*****************************************************************/
#include
#include
//管腳定義
sbit COM0=P3^5;
sbit COM1=P3^4;
sbit COM2=P3^3;
sbit COM3=P3^2;
sbit BI_4=P3^7;
sbit RTC_CLK=P3^0;
sbit RTC_IO=P3^1;
sbit RTC_RST=P3^7;
//復用
//P3口模式寄存器
sfr P3M1=0xb1;
sfr P3M0=0xb2;
//當前時間(BCD碼):秒、分、時、日、月、星期、年
unsigned char ClockBuffer[8]={0x34,0x12,0x08,0x20,0x03,0x05,0x09};
//0~9的段碼查詢表
//位序 D7 D6 D5 D4 D3 D2 D1 D0
//段
A B C D E F G DOT
code unsigned char seg_code[10]={~0x03,~0x9f,~0x25,~0x0d,~0x99,~0x49,~0x41,~0x1f,~0x01,~0x09};
unsigned char ScanCoun=0;
//動態掃描顯示位數計數器
unsigned char DisplayBuf[4]={1,2,3,4}; //4位數字對應的顯示暫存
//段碼緩沖區
unsigned char SegBuf[4]={0x00,0x00,0x00,0x00};//COM1、COM2、COM3、COM4的段碼
bit bi_4a=0;
//COM0對應的4a
bit bi_4b=0; //COM1對應的4a
bit bi_4c=0; //COM2對應的4a
//延時
void dly(unsigned char x)
{unsigned char i;
for (i=0; i
}
//ds1302寫1字節
void
rtc_wt_byte(unsigned char sent_buf)
{unsigned char i;
for (i=0; i<8; i++)
{RTC_CLK=0;
if (sent_buf&0x01) RTC_IO=1;
else RTC_IO=0;
RTC_CLK=1;
dly(5);
sent_buf=sent_buf>>1;
}
RTC_CLK=0;
dly(5);
}
//ds1302讀1字節
unsigned char rtc_rd_byte(void)
{unsigned char i,read_buf;
RTC_IO=1; //RTC_IO置1,保證為輸入狀態
for (i=0; i<8; i++)
{read_buf=read_buf>>1;
RTC_CLK=0;
dly(5);
if (RTC_IO) read_buf=read_buf|0x80;
else read_buf=read_buf&0x7f;
RTC_CLK=1;
dly(5);
}
RTC_CLK=0;
dly(5);
return read_buf;
}
//ds1302寫入時間
void rtc_wr_time(unsigned
char *p_wt_time)
{unsigned char i;
unsigned char tmp1;
dly(30);
RTC_RST=1;
rtc_wt_byte(0xbe); //burst寫入時間
for (i=0; i<8; i++)
{tmp1=*p_wt_time++;
rtc_wt_byte(tmp1);
}
RTC_CLK=0;
RTC_RST=0;
}
//ds1302讀出時間
void rtc_rd_time(unsigned char *p_rd_time)
{unsigned char i;
unsigned char tmp1;
dly(30);
RTC_RST=1;
rtc_wt_byte(0xbf); //burst讀取時間
RTC_IO=1;
for (i=0; i<8; i++)
{tmp1=rtc_rd_byte();
*p_rd_time++=tmp1;
}
RTC_CLK=0;
RTC_RST=0;
}
//ds1302初始化
void ini_rtc()
{RTC_CLK=0;
RTC_RST=0;
dly(30);
RTC_RST=1;
rtc_wt_byte(0x8e); //寫CONTROL寄存器
rtc_wt_byte(0x00); //值:去掉寫保護
RTC_RST=0; //復位
RTC_RST=1;
//正常工作
rtc_wt_byte(0x90); //寫TRICKLE CHARGER寄存器
rtc_wt_byte(0xa9); //值:使能充電,串聯2個二極管,串聯2k歐姆的電阻
RTC_CLK=0;
RTC_RST=0;
}
//把4位數字的SEG放到COM1、COM2、COM3、COM4對應的段碼
//LCD的管腳定義與LED不同,它不是一個COM對應一位數字,而是對應每個數字的一部分SEG
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// < 1f 1a 2f 2a 3f 3a 4f 4a >
-- ---- COM0
// < 1g 1b 2g 2b 2g 3b 4g 4b > -- ---- COM1
// < 1e 1c 2e 2c : 3e 3c 4e 4c > -- ---- COM2
// 1d 1h 2d 2h 3d
3h 4d -- ---- COM3
void Seg2Seg()
{unsigned char SegXX;
SegBuf[0]=0;
SegBuf[1]=0;
SegBuf[2]=0x08;
SegBuf[3]=0;
bi_4a=0;
bi_4b=0;
bi_4c=0;
SegXX=seg_code[DisplayBuf[0]]; //第1位數字
if (SegXX&0x80) SegBuf[0]|=0x40;
if (SegXX&0x40) SegBuf[1]|=0x40;
if (SegXX&0x20)
SegBuf[2]|=0x40;
if (SegXX&0x10) SegBuf[3]|=0x80;
if (SegXX&0x08) SegBuf[2]|=0x80;
if (SegXX&0x04) SegBuf[0]|=0x80;
if (SegXX&0x02) SegBuf[1]|=0x80;
if (SegXX&0x01) SegBuf[3]|=0x40;
SegXX=seg_code[DisplayBuf[1]]; //第2位數字
if (SegXX&0x80) SegBuf[0]|=0x10;
if (SegXX&0x40) SegBuf[1]|=0x10;
if (SegXX&0x20) SegBuf[2]|=0x10;
if (SegXX&0x10) SegBuf[3]|=0x20;
if (SegXX&0x08) SegBuf[2]|=0x20;
if (SegXX&0x04) SegBuf[0]|=0x20;
if (SegXX&0x02) SegBuf[1]|=0x20;
if (SegXX&0x01) SegBuf[3]|=0x10;
SegXX=seg_code[DisplayBuf[2]];
//第3位數字
if (SegXX&0x80) SegBuf[0]|=0x02;
if (SegXX&0x40) SegBuf[1]|=0x02;
if (SegXX&0x20) SegBuf[2]|=0x02;
if (SegXX&0x10) SegBuf[3]|=0x04;
if (SegXX&0x08) SegBuf[2]|=0x04;
if (SegXX&0x04) SegBuf[0]|=0x04;
if (SegXX&0x02) SegBuf[1]|=0x04;
if (SegXX&0x01) SegBuf[3]|=0x02;
SegXX=seg_code[DisplayBuf[3]]; //第4位數字
if (SegXX&0x80) bi_4a=1;
if (SegXX&0x40) bi_4b=1;
if (SegXX&0x20) bi_4c=1;
if (SegXX&0x10) SegBuf[3]|=0x01;
if (SegXX&0x08) SegBuf[2]|=0x01;
if (SegXX&0x04) SegBuf[0]|=0x01;
if (SegXX&0x02)
SegBuf[1]|=0x01;
}
/*一個BCD碼轉化成兩個十進制數(如:0x79轉化成0x07和0x09)*/
BcdToDec(unsigned char BcdValue,unsigned char *pDecValue)
{//if (BcdValue>=0x9a||(BcdValue&0x0f)>=0x0a) return 0;
*pDecValue++=(BcdValue&0xf0)>>4;
*pDecValue=BcdValue&0x0f;
//return 1;
}
//初始化MCS51內部資源
InitInterResource()
{IE=0; //關全部中斷
TCON=0; //清全部中斷請求
IP=0; //清中斷優先級
TMOD=0x01; //T0工作方式1(16位定時器)
TH0=0x00; //T0定時器輔初值
TL0=0x00;
TR0=1; //允許T0定時
ET0=1;
//允許T0中斷
EA=0; //關全局中斷
RTC_RST=0;
}
void main()
{
InitInterResource();
ini_rtc(); //初始化DS1302
rtc_wr_time(ClockBuffer); //寫入時間初始值
EA=1; //開全局中斷
while(1)
{
}
}
//定時器0中斷服務程序,5ms定時器,4位數碼管動態顯示驅動
void tmr0_p(void) interrupt 1
{
TL0=0x78; //重新定時5ms
TH0=0xec;
Seg2Seg();
P3M1=0x3c;
P3M0=0x00;
switch(ScanCoun) //動態掃描顯示
{
case 0: //COM0正向驅動
P1= SegBuf[0];
BI_4= bi_4a;
COM0=0;
P3M1=0x1c; //除COM0輸出外,其余COM設為輸入
P3M0=0x00;
break;
case 1: //COM0反向驅動
P1= ~SegBuf[0];
BI_4= ~bi_4a;
COM0=1;
P3M1=0x1c;
P3M0=0x00;
break;
case 2:
//COM1正向驅動
P1= SegBuf[1];
BI_4= bi_4b;
COM1=0;
P3M1=0x2c;
P3M0=0x00;
break;
case 3: //COM1反向驅動
P1= ~SegBuf[1];
BI_4= ~bi_4b;
COM1=1;
P3M1=0x2c;
P3M0=0x00;
break;
case 4: //COM2正向驅動
P1= SegBuf[2];
BI_4= bi_4c;
COM2=0;
P3M1=0x34;
P3M0=0x00;
break;
case 5: //COM2反向驅動
P1= ~SegBuf[2];
BI_4= ~bi_4c;
COM2=1;
P3M1=0x34;
P3M0=0x00;
break;
case 6:
//COM3正向驅動
P1= SegBuf[3];
COM3=0;
P3M1=0x38;
P3M0=0x00;
RTC_RST=0;
rtc_rd_time(ClockBuffer); //讀時間
BcdToDec(ClockBuffer[0],DisplayBuf+2); //秒送入顯示緩沖
BcdToDec(ClockBuffer[1],DisplayBuf); //分送入顯示緩沖
BI_4= ~bi_4c;
break;
case 7: //COM3反向驅動
P1= ~SegBuf[3];
COM3=1;
P3M1=0x38;
P3M0=0x00;
break;
}
ScanCoun++; //下一位
if (ScanCoun>7) ScanCoun=0;
}
【責任編輯】: 晶拓液晶
版權所有:http:// www.anthonydavid.net轉載請注明出處,違者本網將依法追究責任。
咨詢熱線
13862038982