lcd12864液晶显示程序

显示光电

95人已加入

描述

  一:概述

  带中文字库的128X64 是一种具有4 位/8 位并行、2 线或3 线串行多种接口方式,内部含有国标一级、二级简体 中文字库的点阵图形液晶显示模块;其显示分辨率为128×64, 内置8192 个16*16 点汉字,和128 个16*8 点ASCII 字符 集。利用该模块灵活的接口方式和简单、方便的操作指令,可构成全中文人机交互图形界面。可以显示8×4 行16×16 点 阵的汉字。 也可完成图形显示。低电压低功耗是其又一显著特点。由该模块构成的液晶显示方案与同类型的图形点阵液晶 显示模块相比,不论硬件电路结构或显示程序都要简洁得多,且该模块的价格也略低于相同点阵的图形液晶模块。

  二:LCD12864液晶显示程序

  //12864接法:PB口为数据口(DB7~DB0),RS~PC0,RW~PC1,EN~PC2,PSB即CS1(CS2不用即不接)PC3,RST~PC5。

  //PD2接外部中断,PA0,PA1分别接一路可调电位器。

  /*****************************************************

  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通道标志,bitb为是否加小数点标志

  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 //液晶读/写控制PC1

  #define LCD_EN 2 //液晶使能控制PC2

  #define LCD_PSB 3 //串/并方式控制PC3 即CS1(CS2不用)

  #define LCD_RST 5 //液晶复位端口PC5

  #define busy 7 //LCD_DB7,PA7

  uchar const cdis1[] = {“硕飞科技电子 00”};

  uchar const cdis2[] = {“ WWW.WILLAR.COM ”};

  uchar const cdis3[] = {“ME850_开发实验仪”};

  uchar const cdis4[] = {“TEL:077584867757”};

  uchar const cdis5[] = {“Counter:”};

  /**********************************************************

  图形数据

  **********************************************************/

  /**********************************************************

  * *

  *检查LCD忙状态 *

  *lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据*

  * *

  **********************************************************/

  void lcd_busy(void)

  {

  //DDRA &=~_BV(busy); //设置busy口为输入

  DDRB &=~(1《《busy); //设置busy口为输入

  //DDRA.7=0; //设置busy口为输入

  PORTC &=~(1《《LCD_RS);

  PORTC |=(1《《LCD_RW);

  PORTC |=(1《《LCD_EN);

  while(PINB & (1《《busy)); //忙等待

  PORTC &=~(1《《LCD_EN);

  DDRB|=(1《《busy); //设置busy口为输出

  }

  /**********************************************************

  * *

  *写指令数据到LCD *

  *RS=L,RW=L,E=高脉冲,D0-D7=指令码。 *

  *command为指令,wait_en指定是否要检测LCD忙信号

  *

  * *

  **********************************************************/

  void lcd_wcmd(uchar command,uchar wait_en)

  {

  if(wait_en) //若wait_en为1,则要检测LCD忙信号

  lcd_busy();

  PORTC &=~(1《《LCD_RS);

  PORTC &=~(1《《LCD_RW);

  PORTC &=~(1《《LCD_EN);

  PORTB =command; //送指令数据

  PORTC |=(1《《LCD_EN);

  //_NOP();

  // _NOP();

  PORTC &=~(1《《LCD_EN);

  }

  /**********************************************************

  * *

  *写显示数据到LCD *

  *RS=H,RW=L,E=高脉冲,D0-D7=数据。 *

  * *

  **********************************************************/

  void lcd_wdat(uchar dat)

  {

  lcd_busy();

  PORTC |=(1《《LCD_RS);

  PORTC &=~(1《《LCD_RW);

  PORTC &=~(1《《LCD_EN);

  PORTB=dat; //送显示数据

  PORTC |=(1《《LCD_EN);

  //_NOP();

  //_NOP();

  delay_us(2);

  PORTC &=~(1《《LCD_EN);

  }

  /**********************************************************

  * *

  * LCD初始化设定 *

  * *

  **********************************************************/

  void lcd_init(void)

  {

  DDRB=0XFF; //设置PA输出

  PORTB=0XFF; //全部加上上拉电阻

  DDRC=0XFF; //设置PC为输出

  PORTC=0XFF; //全部加上上拉电阻

  delay_ms(30); //等待上电稳定

  PORTC|=(1《《LCD_PSB); //并口方式

  PORTC &=~(1《《LCD_RST); //液晶复位

  delay_ms(5);

  PORTC |=(1《《LCD_RST);

  delay_ms(5);

  lcd_wcmd(0x30,0);

  delay_ms(5);

  lcd_wcmd(0x0c,1); //显示开,关光标

  delay_ms(5);

  lcd_wcmd(0x06,1); //移动光标

  delay_ms(5);

  lcd_wcmd(0x01,1); //清除LCD的显示内容

  delay_ms(5);

  }

  /**********************************************************

  设定显示位置子函数

  **********************************************************/

  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); //写显示地址

  }

  void display(unsigned int temp,unsigned char gotoy,unsigned char gotox) //(要显示的数,行,列)

  {

  //unsigned int temp;

  unsigned char disp_c[4],i;

  if(temp==counter)bitb=0; //若是counter的值传给temp,则

  标志bitb为0(显示时不加小数点)

  else bitb=1; //若不是counter的值传给temp,则标志bitb为1(显示时加小数点)

  //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]]); //显示一个字符,括号中为该字符的ASCII码

  lcd_wdat(dis_str3[disp_c[3]]);

  //if(bitb==1)lcd_putsf(“。”); //判断要不要加小数点

  if(bitb==1)lcd_wdat(0x2e);

  //lcd_putchar(dis_str3[disp_c[2]]); //显示一个字符,括号中为该字符的ASCII码

  lcd_wdat(dis_str3[disp_c[2]]);

  //lcd_putchar(dis_str3[disp_c[1]]); //显示一个字符,括号中为该字符的ASCII码

  lcd_wdat(dis_str3[disp_c[1]]);

  //lcd_putchar(dis_str3[disp_c[0]]); //显示一个字符,括号中为该字符的ASCII码

  lcd_wdat(dis_str3[disp_c[0]]);

  }

  /**********************************************************

  * *

  * 图形显示子函数 *

  * *

  **********************************************************/

  /*void photodisplay(uchar flash *bmp)

  {

  uchar i,j,temp;

  uint num=0;

  lcd_wcmd(0x34,1); //写数据时,关闭图形显示

  for(i=0;i《32;i++) //32行(上半屏)

  {

  lcd_wcmd(0x80+i,1); //先写入Y坐标值

  lcd_wcmd(0x80,1); //写入X坐标值

  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); //先写入Y坐标值

  lcd_wcmd(0x88,1); //写入X坐标值

  for(j=0;j《16;j++) //16*8列

  {

  temp=bmp[num++];

  lcd_wdat(temp);

  }

  delay_ms(1);

  }

  lcd_wcmd(0x36,1); //写完数据,开图形显示

  }*/

  /**********************************************************

  * *

  * 清屏子函数 *

  * *

  **********************************************************/

  void clr_screen(void)

  {

  lcd_wcmd(0x34,1); //扩充指令操作

  delay_ms(5);

  lcd_wcmd(0x30,1); //基本指令操作

  delay_ms(5);

  lcd_wcmd(0x01,1); //清屏

  delay_ms(5);

  }

  /**********************************************************

  闪烁函数

  **********************************************************/

  void lcdflag(void)

  {

  lcd_wcmd(0x08,1); //关闭显示

  delay_ms(1000);

  lcd_wcmd(0x0c,1); //开启显示

  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);

  }

  /**********************************************************

  * *

  * 写字符串子函数 *

  * *

  **********************************************************/

  void wr_string(void)

  {

  uchar m;

  lcd_pos(1,0); //设置显示位置为第一行

  for(m=0;m《16;m++)

  {

  lcd_wdat(cdis1[m]);

  delay_ms(100);

  }

  lcd_pos(2,0); //设置显示位置为第二行

  for(m=0;m《16;m++)

  {

  lcd_wdat(cdis2[m]);

  delay_ms(100);

  }

  lcd_pos(3,0); //设置显示位置为第三行

  for(m=0;m《16;m++)

  {

  lcd_wdat(cdis3[m]);

  delay_ms(100);

  }

  lcd_pos(4,0); //设置显示位置为第四行

  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); //设置显示位置为第一行

  for(m=0;m《n;m++)

  {

  lcd_wdat(cdis1[m]);

  delay_ms(10);

  }

  }*/

  //绘图

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

  函数功能:清除GDROM的内容,如果不清除会出现花屏现象

  清除方法:向GDROM中写入0x00来清除内容

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

  void clear_gcrom()

  {

  uchar i,j,k,lcd_x,lcd_y;

  lcd_x=0x80;

  lcd_y=0x80;

  lcd_wcmd(0x34,1);//打开扩充指令关闭绘图显示(绘图指令为扩充指令,并且在绘图期间必须关闭绘图显示功能)

  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);//打开绘图指令

  lcd_wcmd(0x30,1);//操作恢复为常用指令

  }

  /**********************************************************

  * *

  *读ST7920内部RAM数据的函数 *

  *RS=H,RW=H,E=高脉冲,D0-D7=数据。 *

  * *

  **********************************************************/

  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);

  }

  /**********************************************************

  * *

  * 画点子函数 *

  * *

  **********************************************************/

  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 );

  }

  /**********************************************************

  函数功能:画水平直线

  参数说明:x0为水平线起始点,x1为水平直线终止点,y图画在第几行

  color为 0时为白线, 为1时为黑线,2时取反该直线上的点

  **********************************************************/

  void v_Lcd12864DrawLineX_f( unsigned char X0, unsigned char X1, unsigned char Y, unsigned char Color )

  { unsigned char Temp ;

  if( X0 》 X1 ) //当X0在X1后面时将X1作为起始点

  {

  Temp = X1 ;

  X1 = X0 ;

  X0 = Temp ;

  }

  for( ; X0 《= X1 ; X0++ )

  drawpoint( X0, Y, Color ) ;

  }

  /**********************************************************

  函数功能:画垂线

  参数说明:y0 为

  起始点 y1为结束点,x为所在第几列 ,color同上为颜色选择

  **********************************************************/

  void v_Lcd12864DrawLineY_f( unsigned char X, unsigned char Y0, unsigned char Y1, unsigned char Color )

  {

  unsigned char Temp ;

  if( Y0 》 Y1 ) //当y0在X1后面时将y1作为起始点

  {

  Temp = Y1 ;

  Y1 = Y0 ;

  Y0 = Temp ;

  }

  for(; Y0 《= Y1 ; Y0++)

  drawpoint( X, Y0, Color) ;

  }

  /**********************************************************

  函数功能:在任意两点间画一条直线,采用Bresenham画线算法。

  参数说明:StartX为起始点横坐标,StartY为起始点纵坐标,ENDX为终点横坐标,ENDY为终点纵坐标,

  **********************************************************/

  void v_Lcd12864DrawLine_f( unsigned char StartX, unsigned char StartY, unsigned char EndX, unsigned char EndY, unsigned char Color )

  {

  int t, distance; /*根据屏幕大小改变变量类型(如改为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 ); //求绝对值(CVAVR的MATH.H中不包含该函数)

  if(delta_x《0)delta_x=-delta_x; //求绝对值

  //delta_y = ABS( delta_y ); //求绝对值(CVAVR的MATH.H中不包含该函数)

  if(delta_y《0)delta_y=-delta_y; //求绝对值

  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) //轮流转换

  {

  adc_data=ADCW; //读ADC0转换值

  adc_v=(unsigned long)adc_data*5000/1024;

  ADMUX=0X41; //选择通道ADC1

  ADCSRA.6=1; //重新开

  始转换

  PORTD.7=~PORTD.7; //测试用

  bita=1; //做标志

  }

  else

  {

  adc_data2=ADCW; //读ADC1转换值

  adc_v2=(unsigned long)adc_data2*5000/1024;

  ADMUX=0X40; //选择通道ADC0

  ADCSRA.6=1; //重新开始转换

  PORTD.7=~PORTD.7; //测试用

  bita=0; //做标志

  }

  }

  /**********************************************************

  * *

  * 主函数 *

  * *

  **********************************************************/

  void main(void)

  {

  uchar m;

  //init_io(); //初始化端口

  //DDRA=0xFF; //置PA口输出

  //PORTA=0xFF; //PA口设置内部上拉电阻

  DDRB=0xFF; //置PB口输出

  PORTB=0xFF; //PB口设置内部上拉电阻

  DDRC=0xFF; //置PC口输出

  PORTC=0xFF; //PC口设置内部上拉电阻

  //DDRD=0xFF; //置PD口输出

  //PORTD=0xFF; //PD口设置内部上拉电阻

  lcd_init(); //初始化LCD

  DDRD.2=0; //外部中断初始化

  PORTD.2=1;

  MCUCR=0X02;

  GICR=0X40;

  SREG.7=1; //开总中断开关

  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); //(数据,行,列)

  display(adc_v2,1,5); //(数据,行,列)

  display(counter,2,4);

  //wr_string(); //写字符串

  //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的内容,否则当前图会在上一幅图上叠加

  delay_ms(100);

  clr_screen(); //清

  屏

  delay_ms(100);

  clr_screen(); //清屏

  delay_ms(100);

  //while(1);

  v_Lcd12864DrawLineY_f( 0, 0 , 63, 1 ) ; //画垂直线

  delay_ms(100);

  v_Lcd12864DrawLineX_f( 0, 127 , 31, 1 ) ;

  drawpoint(69,10,1); //画点

  drawpoint(69,20,1); //画点

  while(1);

  */

  }

  }

  /*********************************************************/

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分