|
LCD.C:
#include "gpio.h"
unsigned short int LcdDispBuf[4]; //用來(lái)保存顯示的段碼緩沖
void LcdInit(void)
{
//4個(gè)COM口都設(shè)置為高阻輸入狀態(tài)
//COM4
//GPIOC_MODE8=0; //輸入模式
//GPIOC_CNF8=1; //高阻(浮空輸入)輸入模式
//COM3
//GPIOC_MODE9=0; //輸入模式
//GPIOC_CNF9=1; //高阻(浮空輸入)輸入模式
//COM2
//GPIOC_MODE10=0; //輸入模式
//GPIOC_CNF10=1; //高阻(浮空輸入)輸入模式
//COM1
//GPIOC_MODE11=0; //輸入模式
//GPIOC_CNF11=1; //高阻(浮空輸入)輸入模式
//PE口設(shè)置為50MHz推挽輸出
GPIOE_CRL=0x33333333;
GPIOE_CRH=0x33333333;
//先初始化為無(wú)顯示
LcdDispBuf[0]=0;
LcdDispBuf[1]=0;
LcdDispBuf[2]=0;
LcdDispBuf[3]=0;
}
//像萬(wàn)利的板子上使用的這種LCD,有4個(gè)COM,還有有16個(gè)SEG。
//要想某一SEG顯示時(shí),需要在對(duì)應(yīng)的SEG和COM之間加上足夠的電壓,
//但是LCD它不像LED那樣,有電壓就一直亮的,它只能維持一段
//時(shí)間,然后內(nèi)容就消失了。此時(shí)需要將電壓反轉(zhuǎn)再加到相應(yīng)的
//SEG和COM之間。在萬(wàn)利的板子上,COM驅(qū)動(dòng)使用了兩個(gè)電阻分壓,
//輸出電壓為1/2VCC,當(dāng)不想讓某位顯示時(shí),就將它的電壓設(shè)置
//為1/2VCC(通過(guò)設(shè)置IO口為高阻態(tài)來(lái)完成),這樣加在對(duì)應(yīng)的
//SEG和COM之間的電壓只有1/2VCC,不足以點(diǎn)亮對(duì)應(yīng)的SEG。需要顯示
//的,就將COM電壓設(shè)置為0或者1,這樣SEG電壓跟COM電壓相反的
//段就被點(diǎn)亮了(變黑)。通過(guò)定期掃描每個(gè)COM,即可穩(wěn)定的在LCD
//上顯示需要的圖形了。需要顯示字符或者數(shù)字時(shí),需要自己將
//對(duì)應(yīng)的圖案設(shè)計(jì)好,需要顯示時(shí),發(fā)送到相應(yīng)的SEG和COM上即可。
/*the varitronix LCD digit is:
A
-- ----------
X \/ |\ |I /|
F| H | J |B
| \ | / |
--G-- --K--
| /| \ |
E | L | N |C
| / |M \| _
----------- | |DP
D -
PE0 PE1 PE2 PE3 ...................................................... PE15
----------------------------------------------------------------------------------------
| | S0 | S1 | S2 | S3 | S4 | S5 | S6 | S7 | S8 | S9 | S10| S11| S12| S13| S14| S15|
----------------------------------------------------------------------------------------
| COM1 | 1X | 1I | 1A | 1DP| 2X | 2I | 2A | 2DP| 3X | 3I | 3A | 3DP| 4X | 4I | 4A | 4DP|
----------------------------------------------------------------------------------------
| COM2 | 1F | 1H | 1J | 1B | 2F | 2H | 2J | 2B | 3F | 3H | 3J | 3B | 4F | 4H | 4J | 4B |
----------------------------------------------------------------------------------------
| COM3 | 1E | 1G | 1K | 1C | 2E | 2G | 2K | 2C | 3E | 3G | 3K | 3C | 4E | 4G | 4K | 4C |
----------------------------------------------------------------------------------------
| COM4 | 1L | 1M | 1N | 1D | 2L | 2M | 2N | 2D | 3L | 3M | 3N | 3D | 4L | 4M | 4N | 4D |
----------------------------------------------------------------------------------------
A LCD character coding is based on the following matrix:
{ X , F , E , L }
{ I , H , G , M }
{ A , J , K , N }
{ DP, B , C , D }
The characher A for example is:
{ 0 , 1 , 1 , 0 }
{ 0 , 0 , 1 , 0 }
{ 1 , 0 , 1 , 0 }
{ 0 , 1 , 1 , 0 }
-------------------
= 4 9 F 0 hex
=> 'A' = 0x49F0 */
const unsigned short int Letter[26]={0x49F0,0x01F8,0x4118,0x08F8,0x4178,0x4170,0x41D8,0x09F0,0x600A,
0x0888,0x0534,0x0118,0x0F90,0x0B94,0x4998,0x4970,0x499C,0x4974,
0x41E8,0x6002,0x0998,0x0511,0x299A,0x0605,0x0601,0x4409};
const unsigned short int Number[10]={0x4998,0x0880,0x4878,0x48E8,0x09E0,0x41E8,0x41F8,0x4880,0x49F8,0x49E8};
const unsigned short int Arrow[2]={0x0005,0x0600}; // {Upstair,Downstair}
//根據(jù)LCD需要顯示的字符設(shè)置緩沖區(qū)的內(nèi)容。
//入口參數(shù)c為需要顯示的字符。
//入口參數(shù)p為需要顯示的位置,從左往右依次為0,1,2,3。
//入口參數(shù)dot為是否需要顯示小數(shù)點(diǎn)和單引號(hào),1只顯示小數(shù)點(diǎn),
//2只顯示單引號(hào),3為小數(shù)點(diǎn)和單引號(hào)同時(shí)顯示
void LcdSetChar(unsigned char c, unsigned char p, unsigned char dot)
{
//定義一個(gè)Temp變量來(lái)保存查表的結(jié)果
unsigned short int Temp;
if(p>3)return;
if((c>='A')&&(c<='Z')) //A~Z之間的字符
{
Temp=Letter[c-'A'];
}
else if((c>='0')&&(c<='9')) //0~9之間的數(shù)
{
Temp=Number[c-'0'];
}
else if(c=='\'') //單引號(hào)
{
Temp=0x1000;
}
else if(c=='.') //小數(shù)點(diǎn)
{
Temp=0x8000;
}
else //暫時(shí)不支持其它字符顯示
{
Temp=0;
}
//如果需要顯示小數(shù)點(diǎn)
if(dot==1)Temp|=0x8000;
if(dot==2)Temp|=0x1000;
if(dot==3)Temp|=0x9000;
//根據(jù)不同的位置,設(shè)置顯示緩沖區(qū)中的值
//在這里,并不是每個(gè)COM都剛好對(duì)應(yīng)著LCD
//上的一個(gè)字符位置,而是每個(gè)COM都同時(shí)
//控制著4個(gè)字符中的4個(gè)SEG,因此需要修改
//某個(gè)字符位置的顯示,就必須將顯示緩沖
//區(qū)中的每個(gè)變量中對(duì)應(yīng)的4位進(jìn)行修改。
//將COM1選中時(shí)顯示的SEG中的對(duì)應(yīng)4位先清0
LcdDispBuf[0]&=~((0xF)<<(p*4));
//然后再將需要顯示的內(nèi)容寫入
LcdDispBuf[0]|=(((Temp>>12)&0xF)<<(p*4));
//將COM1選中時(shí)顯示的SEG中的對(duì)應(yīng)4位先清0
LcdDispBuf[1]&=~((0xF)<<(p*4));
//然后再將需要顯示的內(nèi)容寫入
LcdDispBuf[1]|=(((Temp>>8)&0xF)<<(p*4));
//將COM1選中時(shí)顯示的SEG中的對(duì)應(yīng)4位先清0
LcdDispBuf[2]&=~((0xF)<<(p*4));
//然后再將需要顯示的內(nèi)容寫入
LcdDispBuf[2]|=(((Temp>>4)&0xF)<<(p*4));
//將COM1選中時(shí)顯示的SEG中的對(duì)應(yīng)4位先清0
LcdDispBuf[3]&=~((0xF)<<(p*4));
//然后再將需要顯示的內(nèi)容寫入
LcdDispBuf[3]|=(((Temp)&0xF)<<(p*4));
}
//每隔一段時(shí)間要調(diào)用一次該函數(shù),例如2ms
//可以在一個(gè)定時(shí)器中調(diào)用該函數(shù)來(lái)定期刷新
//這里為了演示程序,使用軟件延時(shí)的方法
void LcdScan(void)
{
static unsigned int i=1;
static unsigned int Off=0;
if(Off==1)
{
Off=0;
//先將4個(gè)COM都設(shè)置為高阻狀態(tài)
GPIOC_MODE8=0; //輸入模式
GPIOC_CNF8=1; //高阻輸入模式
GPIOC_MODE9=0; //輸入模式
GPIOC_CNF9=1; //高阻輸入模式
GPIOC_MODE10=0; //輸入模式
GPIOC_CNF10=1; //高阻輸入模式
GPIOC_MODE11=0; //輸入模式
GPIOC_CNF11=1; //高阻輸入模式
//然后將所有SEG設(shè)置為低電平
GPIOE_ODR=0;
//再將所有COM設(shè)置為低電平
GPIOC_CLR=(1<<8)|(1<<9)|(1<<10)|(1<<11);
GPIOC_MODE8=3; //50M輸出模式
GPIOC_CNF8=0; //推挽模式
GPIOC_MODE9=3; //50M輸出模式
GPIOC_CNF9=0; //推挽模式
GPIOC_MODE10=3; //50M輸出模式
GPIOC_CNF10=0; //推挽模式
GPIOC_MODE11=3; //50M輸出模式
GPIOC_CNF11=0; //推挽模式
return;
}
else
{
Off=1;
//先將4個(gè)COM都設(shè)置為高阻狀態(tài)
GPIOC_MODE8=0; //輸入模式
GPIOC_CNF8=1; //高阻輸入模式
GPIOC_MODE9=0; //輸入模式
GPIOC_CNF9=1; //高阻輸入模式
GPIOC_MODE10=0; //輸入模式
GPIOC_CNF10=1; //高阻輸入模式
GPIOC_MODE11=0; //輸入模式
GPIOC_CNF11=1; //高阻輸入模式
}
switch(i)
{
case 1:
//COM4的前半個(gè)周期
GPIOE_ODR=LcdDispBuf[3]; //將SEG碼輸出
GPIOC_CLR=1<<8; //COM4輸出低電平
GPIOC_CNF8=0; //推挽輸出
GPIOC_MODE8=3; //50MHz輸出模式
break;
case 2:
//COM4的后半個(gè)周期
GPIOE_ODR=~LcdDispBuf[3]; //將SEG碼取反
GPIOC_SET=1<<8; //COM4輸出高電平
GPIOC_CNF8=0; //推挽輸出
GPIOC_MODE8=3; //50MHz輸出模式
break;
case 3:
//COM3的前半個(gè)周期
GPIOE_ODR=LcdDispBuf[2]; //將SEG碼輸出
GPIOC_CLR=1<<9; //COM3輸出低電平
GPIOC_CNF9=0; //推挽輸出
GPIOC_MODE9=3; //50MHz輸出模式
break;
case 4:
//COM3的后半個(gè)周期
GPIOE_ODR=~LcdDispBuf[2]; //將SEG碼取反
GPIOC_SET=1<<9; //COM3輸出高電平
GPIOC_CNF9=0; //推挽輸出
GPIOC_MODE9=3; //50MHz輸出模式
break;
case 5:
//COM2的前半個(gè)周期
GPIOE_ODR=LcdDispBuf[1]; //將SEG碼輸出
GPIOC_CLR=1<<10; //COM2輸出低電平
GPIOC_CNF10=0; //推挽輸出
GPIOC_MODE10=3; //50MHz輸出模式
break;
case 6:
//COM2的后半個(gè)周期
GPIOE_ODR=~LcdDispBuf[1]; //將SEG碼取反
GPIOC_SET=1<<10; //COM2輸出高電平
GPIOC_CNF10=0; //推挽輸出
GPIOC_MODE10=3; //50MHz輸出模式
break;
case 7:
//COM1的前半個(gè)周期
GPIOE_ODR=LcdDispBuf[0]; //將SEG碼輸出
GPIOC_CLR=1<<11; //COM1輸出低電平
GPIOC_CNF11=0; //推挽輸出
GPIOC_MODE11=3; //50MHz輸出模式
break;
case 8:
//COM1的后半個(gè)周期
GPIOE_ODR=~LcdDispBuf[0]; //將SEG碼取反
GPIOC_SET=1<<11; //COM1輸出高電平
GPIOC_CNF11=0; //推挽輸出
GPIOC_MODE11=3; //50MHz輸出模式
i=0;
break;
default :
i=0;
}
//切換到下一狀態(tài)
i++;
}
LCD.h:
#ifndef __LCD_H__
#define __LCD_H__
void LcdScan(void);
void LcdInit(void);
void LcdSetChar(unsigned char c, unsigned char p, unsigned char dot);
extern unsigned short int LcdDispBuf[4]; //用來(lái)保存顯示的段碼緩沖
#endif
|
|