一:概述
帶中文字庫(kù)的128X64 是一種具有4 位/8 位并行、2 線或3 線串行多種接口方式,內(nèi)部含有國(guó)標(biāo)一級(jí)、二級(jí)簡(jiǎn)體 中文字庫(kù)的點(diǎn)陣圖形液晶顯示模塊;其顯示分辨率為128×64, 內(nèi)置8192 個(gè)16*16 點(diǎn)漢字,和128 個(gè)16*8 點(diǎn)ASCII 字符 集。利用該模塊靈活的接口方式和簡(jiǎn)單、方便的操作指令,可構(gòu)成全中文人機(jī)交互圖形界面。可以顯示8×4 行16×16 點(diǎn) 陣的漢字。 也可完成圖形顯示。低電壓低功耗是其又一顯著特點(diǎn)。由該模塊構(gòu)成的液晶顯示方案與同類型的圖形點(diǎn)陣液晶 顯示模塊相比,不論硬件電路結(jié)構(gòu)或顯示程序都要簡(jiǎn)潔得多,且該模塊的價(jià)格也略低于相同點(diǎn)陣的圖形液晶模塊。
二:LCD12864液晶顯示程序
//12864接法:PB口為數(shù)據(jù)口(DB7~DB0),RS~PC0,RW~PC1,EN~PC2,PSB即CS1(CS2不用即不接)PC3,RST~PC5。
//PD2接外部中斷,PA0,PA1分別接一路可調(diào)電位器。
/*****************************************************
This program was produced by the
CodeWizardAVR V2.04.4a Advanced
Automatic Program Generator
?Copyright 1998-2009 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Chip type : ATmega16
Program type : Application
AVR Core Clock frequency: 4.000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 256
*****************************************************/
#include 《mega16.h》
#include 《delay.h》
//flash unsigned char dis_str2[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};//0~9的ASCII碼
flash unsigned char dis_str3[]={“0123456789”}; //0~9的ASCII碼
unsigned int counter=0;
unsigned char bita,bitb; //bita為ADC通道標(biāo)志,bitb為是否加小數(shù)點(diǎn)標(biāo)志
unsigned int adc_data,adc_v,adc_data2,adc_v2;
#define uchar unsigned char
#define uint unsigned int
#define LCD_RS 0 //寄存器選擇輸入PC0
#define LCD_RW 1 //液晶讀/寫(xiě)控制PC1
#define LCD_EN 2 //液晶使能控制PC2
#define LCD_PSB 3 //串/并方式控制PC3 即CS1(CS2不用)
#define LCD_RST 5 //液晶復(fù)位端口PC5
#define busy 7 //LCD_DB7,PA7
uchar const cdis1[] = {“碩飛科技電子 00”};
uchar const cdis2[] = {“ WWW.WILLAR.COM ”};
uchar const cdis3[] = {“ME850_開(kāi)發(fā)實(shí)驗(yàn)儀”};
uchar const cdis4[] = {“TEL:077584867757”};
uchar const cdis5[] = {“Counter:”};
/**********************************************************
圖形數(shù)據(jù)
**********************************************************/
/**********************************************************
* *
*檢查L(zhǎng)CD忙狀態(tài) *
*lcd_busy為1時(shí),忙,等待。lcd-busy為0時(shí),閑,可寫(xiě)指令與數(shù)據(jù)*
* *
**********************************************************/
void lcd_busy(void)
{
//DDRA &=~_BV(busy); //設(shè)置busy口為輸入
DDRB &=~(1《《busy); //設(shè)置busy口為輸入
//DDRA.7=0; //設(shè)置busy口為輸入
PORTC &=~(1《《LCD_RS);
PORTC |=(1《《LCD_RW);
PORTC |=(1《《LCD_EN);
while(PINB & (1《《busy)); //忙等待
PORTC &=~(1《《LCD_EN);
DDRB|=(1《《busy); //設(shè)置busy口為輸出
}
/**********************************************************
* *
*寫(xiě)指令數(shù)據(jù)到LCD *
*RS=L,RW=L,E=高脈沖,D0-D7=指令碼。 *
*command為指令,wait_en指定是否要檢測(cè)LCD忙信號(hào)
*
* *
**********************************************************/
void lcd_wcmd(uchar command,uchar wait_en)
{
if(wait_en) //若wait_en為1,則要檢測(cè)LCD忙信號(hào)
lcd_busy();
PORTC &=~(1《《LCD_RS);
PORTC &=~(1《《LCD_RW);
PORTC &=~(1《《LCD_EN);
PORTB =command; //送指令數(shù)據(jù)
PORTC |=(1《《LCD_EN);
//_NOP();
// _NOP();
PORTC &=~(1《《LCD_EN);
}
/**********************************************************
* *
*寫(xiě)顯示數(shù)據(jù)到LCD *
*RS=H,RW=L,E=高脈沖,D0-D7=數(shù)據(jù)。 *
* *
**********************************************************/
void lcd_wdat(uchar dat)
{
lcd_busy();
PORTC |=(1《《LCD_RS);
PORTC &=~(1《《LCD_RW);
PORTC &=~(1《《LCD_EN);
PORTB=dat; //送顯示數(shù)據(jù)
PORTC |=(1《《LCD_EN);
//_NOP();
//_NOP();
delay_us(2);
PORTC &=~(1《《LCD_EN);
}
/**********************************************************
* *
* LCD初始化設(shè)定 *
* *
**********************************************************/
void lcd_init(void)
{
DDRB=0XFF; //設(shè)置PA輸出
PORTB=0XFF; //全部加上上拉電阻
DDRC=0XFF; //設(shè)置PC為輸出
PORTC=0XFF; //全部加上上拉電阻
delay_ms(30); //等待上電穩(wěn)定
PORTC|=(1《《LCD_PSB); //并口方式
PORTC &=~(1《《LCD_RST); //液晶復(fù)位
delay_ms(5);
PORTC |=(1《《LCD_RST);
delay_ms(5);
lcd_wcmd(0x30,0);
delay_ms(5);
lcd_wcmd(0x0c,1); //顯示開(kāi),關(guān)光標(biāo)
delay_ms(5);
lcd_wcmd(0x06,1); //移動(dòng)光標(biāo)
delay_ms(5);
lcd_wcmd(0x01,1); //清除LCD的顯示內(nèi)容
delay_ms(5);
}
/**********************************************************
設(shè)定顯示位置子函數(shù)
**********************************************************/
void lcd_pos(uchar X,uchar Y)
{
uchar pos;
if (X==1) //第一行
{X=0x80;}
else if (X==2) //第二行
{X=0x90;}
else if (X==3) //第三行
{X=0x88;}
else if (X==4) //第四行
{X=0x98;}
pos = X+Y ; //確定具體顯示地址
lcd_wcmd(pos,1); //寫(xiě)顯示地址
}
void display(unsigned int temp,unsigned char gotoy,unsigned char gotox) //(要顯示的數(shù),行,列)
{
//unsigned int temp;
unsigned char disp_c[4],i;
if(temp==counter)bitb=0; //若是counter的值傳給temp,則
標(biāo)志bitb為0(顯示時(shí)不加小數(shù)點(diǎn))
else bitb=1; //若不是counter的值傳給temp,則標(biāo)志bitb為1(顯示時(shí)加小數(shù)點(diǎn))
//temp=counter;
for(i=0;i《4;i++)
{ //拆字程序
disp_c[i]=temp%10;
temp=temp/10;
}
//lcd_gotoxy(gotox,gotoy); ////定位要顯示所在的列、行
lcd_pos(gotoy,gotox);
//lcd_putchar(dis_str3[disp_c[3]]); //顯示一個(gè)字符,括號(hào)中為該字符的ASCII碼
lcd_wdat(dis_str3[disp_c[3]]);
//if(bitb==1)lcd_putsf(“。”); //判斷要不要加小數(shù)點(diǎn)
if(bitb==1)lcd_wdat(0x2e);
//lcd_putchar(dis_str3[disp_c[2]]); //顯示一個(gè)字符,括號(hào)中為該字符的ASCII碼
lcd_wdat(dis_str3[disp_c[2]]);
//lcd_putchar(dis_str3[disp_c[1]]); //顯示一個(gè)字符,括號(hào)中為該字符的ASCII碼
lcd_wdat(dis_str3[disp_c[1]]);
//lcd_putchar(dis_str3[disp_c[0]]); //顯示一個(gè)字符,括號(hào)中為該字符的ASCII碼
lcd_wdat(dis_str3[disp_c[0]]);
}
/**********************************************************
* *
* 圖形顯示子函數(shù) *
* *
**********************************************************/
/*void photodisplay(uchar flash *bmp)
{
uchar i,j,temp;
uint num=0;
lcd_wcmd(0x34,1); //寫(xiě)數(shù)據(jù)時(shí),關(guān)閉圖形顯示
for(i=0;i《32;i++) //32行(上半屏)
{
lcd_wcmd(0x80+i,1); //先寫(xiě)入Y坐標(biāo)值
lcd_wcmd(0x80,1); //寫(xiě)入X坐標(biāo)值
for(j=0;j《16;j++) //16*8列
{
temp=bmp[num++];
lcd_wdat(temp);
}
delay_ms(1);
}
for(i=0;i《32;i++) //32行(下半屏)
{
lcd_wcmd(0x80+i,1); //先寫(xiě)入Y坐標(biāo)值
lcd_wcmd(0x88,1); //寫(xiě)入X坐標(biāo)值
for(j=0;j《16;j++) //16*8列
{
temp=bmp[num++];
lcd_wdat(temp);
}
delay_ms(1);
}
lcd_wcmd(0x36,1); //寫(xiě)完數(shù)據(jù),開(kāi)圖形顯示
}*/
/**********************************************************
* *
* 清屏子函數(shù) *
* *
**********************************************************/
void clr_screen(void)
{
lcd_wcmd(0x34,1); //擴(kuò)充指令操作
delay_ms(5);
lcd_wcmd(0x30,1); //基本指令操作
delay_ms(5);
lcd_wcmd(0x01,1); //清屏
delay_ms(5);
}
/**********************************************************
閃爍函數(shù)
**********************************************************/
void lcdflag(void)
{
lcd_wcmd(0x08,1); //關(guān)閉顯示
delay_ms(1000);
lcd_wcmd(0x0c,1); //開(kāi)啟顯示
delay_ms(1000);
lcd_wcmd(0x08,1);
dela
y_ms(1000);
lcd_wcmd(0x0c,1);
delay_ms(1000);
lcd_wcmd(0x08,1);
delay_ms(1000);
lcd_wcmd(0x0c,1);
delay_ms(1000);
lcd_wcmd(0x01,1); //清屏
delay_ms(5);
}
/**********************************************************
* *
* 寫(xiě)字符串子函數(shù) *
* *
**********************************************************/
void wr_string(void)
{
uchar m;
lcd_pos(1,0); //設(shè)置顯示位置為第一行
for(m=0;m《16;m++)
{
lcd_wdat(cdis1[m]);
delay_ms(100);
}
lcd_pos(2,0); //設(shè)置顯示位置為第二行
for(m=0;m《16;m++)
{
lcd_wdat(cdis2[m]);
delay_ms(100);
}
lcd_pos(3,0); //設(shè)置顯示位置為第三行
for(m=0;m《16;m++)
{
lcd_wdat(cdis3[m]);
delay_ms(100);
}
lcd_pos(4,0); //設(shè)置顯示位置為第四行
for(m=0;m《16;m++)
{
lcd_wdat(cdis4[m]);
delay_ms(100);
}
}
/*void wr_string2(unsigned char string,unsigned char x,unsigned char y,unsigned char n)
{
uchar m;
lcd_pos(x,y); //設(shè)置顯示位置為第一行
for(m=0;m《n;m++)
{
lcd_wdat(cdis1[m]);
delay_ms(10);
}
}*/
//繪圖
/*====================================================
函數(shù)功能:清除GDROM的內(nèi)容,如果不清除會(huì)出現(xiàn)花屏現(xiàn)象
清除方法:向GDROM中寫(xiě)入0x00來(lái)清除內(nèi)容
========================================================*/
void clear_gcrom()
{
uchar i,j,k,lcd_x,lcd_y;
lcd_x=0x80;
lcd_y=0x80;
lcd_wcmd(0x34,1);//打開(kāi)擴(kuò)充指令關(guān)閉繪圖顯示(繪圖指令為擴(kuò)充指令,并且在繪圖期間必須關(guān)閉繪圖顯示功能)
for(i=0;i《2;i++)//分為上下兩半屏清除顯示
{
for(j=0;j《32;j++)
{
lcd_wcmd(lcd_y+j,1);
lcd_wcmd(lcd_x,1);
for(k=0;k《16;k++)
{
lcd_wdat(0x00);
}
}
lcd_x=0x88;//將x指向下半屏
}
lcd_wcmd(0x36,1);//打開(kāi)繪圖指令
lcd_wcmd(0x30,1);//操作恢復(fù)為常用指令
}
/**********************************************************
* *
*讀ST7920內(nèi)部RAM數(shù)據(jù)的函數(shù) *
*RS=H,RW=H,E=高脈沖,D0-D7=數(shù)據(jù)。 *
* *
**********************************************************/
uchar readbyte(void)
{
uchar returnvalue;
lcd_busy();
DDRA&=0x00; //PA口為輸入
//delay_ms(1);
PORTA=0Xff; //加上拉電阻
PORTC |=(1《《LCD_RW); //RW=1
//delay_us(1);
PORTC |=(1《《LCD_RS); //RS=1
//delay_us(1);
PORTC &=~(1《《LCD_EN); //EN=0
delay_us(1);
PORTC
|=(1《《LCD_EN); //EN=1
//delay_us(3);
delay_us(1);
//PORTC &=~(1《《LCD_EN); //EN=0
returnvalue=PINA; //讀PA口
delay_us(1);
PORTC &=~(1《《LCD_EN); //EN=0
//delay_us(1);
PORTC &=~(1《《LCD_RW); //RW=0
PORTC &=~(1《《LCD_RS); //RS=0
DDRA=0xff; //PA口為輸出
return (returnvalue);
}
/**********************************************************
* *
* 畫(huà)點(diǎn)子函數(shù) *
* *
**********************************************************/
void drawpoint(uchar X,uchar Y,uchar Color)
{
uchar row,tier,tier_bit;
uchar readold_h,readold_l;
lcd_wcmd(0x34,1);
//lcd_wcmd(0x36,1);
tier = X 》》 4 ; //用移位,速度快
tier_bit = X & 0x0f ;
if( Y 《 32 )
{
row = Y ;
}
else
{
row = Y - 32 ;
tier += 8 ;
}
lcd_wcmd(0x34,1);
lcd_wcmd( row + 0x80,1 ) ;
lcd_wcmd( tier + 0x80,1 ) ;
lcd_busy(); //
readbyte();
readold_h = readbyte() ;
readold_l = readbyte() ;
lcd_wcmd( row + 0x80,1 ) ;
lcd_wcmd( tier + 0x80,1 ) ;
if( tier_bit 《 8 )
{
switch( Color)
{
case 0 : readold_h &=( ~( 0x01 《《 ( 7 - tier_bit ))) ; break ;
case 1 : readold_h |= ( 0x01 《《 ( 7 - tier_bit )) ; break ;
case 2 : readold_h ^= ( 0x01 《《 ( 7 - tier_bit )) ; break ;
default : break ;
}
lcd_wdat( readold_h ) ;
lcd_wdat( readold_l ) ;
}
else
{
switch(Color)
{
case 0 : readold_l &= (~( 0x01 《《 ( 15 - tier_bit ))) ; break ;
case 1 : readold_l |= ( 0x01 《《 ( 15 - tier_bit )) ; break ;
case 2 : readold_l ^= ( 0x01 《《 ( 15 - tier_bit )) ; break ;
default : break ;
}
lcd_wdat( readold_h ) ;
lcd_wdat( readold_l ) ;
}
lcd_wcmd(0x36,1);
lcd_wcmd( 0x30,1 );
}
/**********************************************************
函數(shù)功能:畫(huà)水平直線
參數(shù)說(shuō)明:x0為水平線起始點(diǎn),x1為水平直線終止點(diǎn),y圖畫(huà)在第幾行
color為 0時(shí)為白線, 為1時(shí)為黑線,2時(shí)取反該直線上的點(diǎn)
**********************************************************/
void v_Lcd12864DrawLineX_f( unsigned char X0, unsigned char X1, unsigned char Y, unsigned char Color )
{ unsigned char Temp ;
if( X0 》 X1 ) //當(dāng)X0在X1后面時(shí)將X1作為起始點(diǎn)
{
Temp = X1 ;
X1 = X0 ;
X0 = Temp ;
}
for( ; X0 《= X1 ; X0++ )
drawpoint( X0, Y, Color ) ;
}
/**********************************************************
函數(shù)功能:畫(huà)垂線
參數(shù)說(shuō)明:y0 為
起始點(diǎn) y1為結(jié)束點(diǎn),x為所在第幾列 ,color同上為顏色選擇
**********************************************************/
void v_Lcd12864DrawLineY_f( unsigned char X, unsigned char Y0, unsigned char Y1, unsigned char Color )
{
unsigned char Temp ;
if( Y0 》 Y1 ) //當(dāng)y0在X1后面時(shí)將y1作為起始點(diǎn)
{
Temp = Y1 ;
Y1 = Y0 ;
Y0 = Temp ;
}
for(; Y0 《= Y1 ; Y0++)
drawpoint( X, Y0, Color) ;
}
/**********************************************************
函數(shù)功能:在任意兩點(diǎn)間畫(huà)一條直線,采用Bresenham畫(huà)線算法。
參數(shù)說(shuō)明:StartX為起始點(diǎn)橫坐標(biāo),StartY為起始點(diǎn)縱坐標(biāo),ENDX為終點(diǎn)橫坐標(biāo),ENDY為終點(diǎn)縱坐標(biāo),
**********************************************************/
void v_Lcd12864DrawLine_f( unsigned char StartX, unsigned char StartY, unsigned char EndX, unsigned char EndY, unsigned char Color )
{
int t, distance; /*根據(jù)屏幕大小改變變量類型(如改為int型)*/
int x = 0 , y = 0 , delta_x, delta_y ;
char incx, incy ;
delta_x = EndX - StartX ;
delta_y = EndY - StartY ;
if( delta_x 》 0 )
{
incx = 1;
}
else if( delta_x == 0 )
{
v_Lcd12864DrawLineY_f( StartX, StartY, EndY, Color ) ;
return ;
}
else
{
incx = -1 ;
}
if( delta_y 》 0 )
{
incy = 1 ;
}
else if(delta_y == 0 )
{
v_Lcd12864DrawLineX_f( StartX, EndX, StartY, Color ) ;
return ;
}
else
{
incy = -1 ;
}
// delta_x = ABS( delta_x ); //求絕對(duì)值(CVAVR的MATH.H中不包含該函數(shù))
if(delta_x《0)delta_x=-delta_x; //求絕對(duì)值
//delta_y = ABS( delta_y ); //求絕對(duì)值(CVAVR的MATH.H中不包含該函數(shù))
if(delta_y《0)delta_y=-delta_y; //求絕對(duì)值
if( delta_x 》 delta_y )
{
distance = delta_x ;
}
else
{
distance = delta_y ;
}
drawpoint( StartX, StartY, Color ) ;
/* Draw Line*/
for( t = 0 ; t 《= distance+1 ; t++ )
{
drawpoint( StartX, StartY, Color ) ;
x += delta_x ;
y += delta_y ;
if( x 》 distance )
{
x -= distance ;
StartX += incx ;
}
if( y 》 distance )
{
y -= distance ;
StartY += incy ;
}
}
}
interrupt [EXT_INT0] void aaa(void)
{
delay_ms(15);
if(PIND.2==0)
counter++;
// display(counter,8,1);
}
interrupt [ADC_INT] void bbb(void)
{
//unsigned int adc_data,adc_v;
if(bita==0) //輪流轉(zhuǎn)換
{
adc_data=ADCW; //讀ADC0轉(zhuǎn)換值
adc_v=(unsigned long)adc_data*5000/1024;
ADMUX=0X41; //選擇通道ADC1
ADCSRA.6=1; //重新開(kāi)
始轉(zhuǎn)換
PORTD.7=~PORTD.7; //測(cè)試用
bita=1; //做標(biāo)志
}
else
{
adc_data2=ADCW; //讀ADC1轉(zhuǎn)換值
adc_v2=(unsigned long)adc_data2*5000/1024;
ADMUX=0X40; //選擇通道ADC0
ADCSRA.6=1; //重新開(kāi)始轉(zhuǎn)換
PORTD.7=~PORTD.7; //測(cè)試用
bita=0; //做標(biāo)志
}
}
/**********************************************************
* *
* 主函數(shù) *
* *
**********************************************************/
void main(void)
{
uchar m;
//init_io(); //初始化端口
//DDRA=0xFF; //置PA口輸出
//PORTA=0xFF; //PA口設(shè)置內(nèi)部上拉電阻
DDRB=0xFF; //置PB口輸出
PORTB=0xFF; //PB口設(shè)置內(nèi)部上拉電阻
DDRC=0xFF; //置PC口輸出
PORTC=0xFF; //PC口設(shè)置內(nèi)部上拉電阻
//DDRD=0xFF; //置PD口輸出
//PORTD=0xFF; //PD口設(shè)置內(nèi)部上拉電阻
lcd_init(); //初始化LCD
DDRD.2=0; //外部中斷初始化
PORTD.2=1;
MCUCR=0X02;
GICR=0X40;
SREG.7=1; //開(kāi)總中斷開(kāi)關(guān)
bita=0; //選ADC0通道
ADMUX=0X40; //ADC初始化
ADCSRA=0B11001101;
//lcd_gotoxy(0,0); //顯示固定字符
lcd_pos(1,0); //(行,列)
//lcd_putsf(“A:”); // display the message
lcd_wdat(0x41); //顯示“A”
lcd_wdat(0x3A); //顯示“。“
delay_ms(10);
//lcd_gotoxy(9,0);
lcd_pos(1,4); //(行,列)
//lcd_putsf(”B:“); // display the message
lcd_wdat(0x42); //顯示“B”
lcd_wdat(0x3A); //顯示“。”
delay_ms(10);
//counter=0; //counter初值
// lcd_gotoxy(0,1); //第1行第0列
// lcd_putsf(“Counter:”);
// display(counter,8,1); //顯示初始值
lcd_pos(2,0); //(行,列)
for(m=0;m《8;m++)
{
lcd_wdat(cdis5[m]);
delay_ms(10);
}
while(1)
{
display(adc_v,1,1); //(數(shù)據(jù),行,列)
display(adc_v2,1,5); //(數(shù)據(jù),行,列)
display(counter,2,4);
//wr_string(); //寫(xiě)字符串
//lcd_pos(1,0); //顯示半寬字符
//lcd_wdat(0x01);
//lcd_wdat(0x02);
//lcd_wdat(0x03);
//lcd_wdat(0x33); //“3”ASCII 碼
//delay_ms(100);
//delay_ms(2000);
//lcdflag();
//delay_ms(2000);
/*
clear_gcrom(); //清除GDROM的內(nèi)容,否則當(dāng)前圖會(huì)在上一幅圖上疊加
delay_ms(100);
clr_screen(); //清
屏
delay_ms(100);
clr_screen(); //清屏
delay_ms(100);
//while(1);
v_Lcd12864DrawLineY_f( 0, 0 , 63, 1 ) ; //畫(huà)垂直線
delay_ms(100);
v_Lcd12864DrawLineX_f( 0, 127 , 31, 1 ) ;
drawpoint(69,10,1); //畫(huà)點(diǎn)
drawpoint(69,20,1); //畫(huà)點(diǎn)
while(1);
*/
}
}
/*********************************************************/
評(píng)論
查看更多