找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5154|回复: 4
收起左侧

[原创]请教大家一个关于12864程序的问题

[复制链接]
ID:22739 发表于 2010-3-31 20:52 | 显示全部楼层 |阅读模式

仿真时液晶的点来回跳动,请问是什么原因

#include <reg51.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define DATA P0 //LCD12864数据线
sbit RS=P2^2; // 数据\指令 选择
sbit RW=P2^1; // 读\写 选择
sbit EN=P2^0; // 读\写使能
sbit cs1=P2^4; // 片选1
sbit cs2=P2^3; // 片选2

 

 

/*状态检查,LCD是否忙*/
void CheckState()  
{
   uchar dat;//状态信息(判断是否忙)
   RS=0; // 数据\指令选择,D/I(RS)=“L” ,表示 DB7∽DB0 为显示指令数据
   RW=1; //R/W=“H” ,E=“H”数据被读到DB7∽DB0
   do{
      DATA=0x00;
      EN=1; //EN下降源
   _nop_(); //一个时钟延时
   dat=DATA;
      EN=0;
      dat=0x80 & dat; //仅当第7位为0时才可操作(判别busy信号)
      }while(!(dat==0x00));
}


 /*写命令到LCD中*/
void SendCommandToLCD(uchar com)
{
   CheckState();//状态检查,LCD是否忙
   RS=0;  //向LCD发送命令。RS=0写指令,RS=1写数据
   RW=0;//R/W=“L” ,E=“H→L”数据被写到 IR 或 DR
   DATA=com;  //com :命令
   EN=1;//EN下降源
   _nop_();
   _nop_();
   EN=0;
}

 /*设置页 0xb8是页的首地址*/
void SetLine(uchar page) 
{
  page=0xb8|page; //1011 1xxx 0<=page<=7 设定页地址--X 0-7,8行为一页64/8=8,共8页
  SendCommandToLCD(page);
}

 /*设定显示开始行,0xc0是行的首地址*/
void SetStartLine(uchar startline)    
{
  startline=0xc0|startline; //1100 0000
  SendCommandToLCD(startline); //设置从哪行开始:0--63,一般从0 行开始显示
}

 /*设定列地址--Y 0-63 ,0x40是列的首地址*/
void SetColumn(uchar column) 
{
  column=column &0x3f; //column最大值为64,越出 0=<column<=63
  column= 0x40|column; //01xx xxxx
  SendCommandToLCD(column);
}

 
 /*开关显示,0x3f是开显示,0x3e是关显示*/
void SetOnOff(uchar onoff)   
{
 onoff=0x3e|onoff; //0011 111x,onoff只能为0或者1
 SendCommandToLCD(onoff);
}

/*写显示数据 */
void WriteByte(uchar dat) 
{
   CheckState();//状态检查,LCD是否忙
   RS=1; //RS=0写指令,RS=1写数据
   RW=0;////R/W=“L” ,E=“H→L”数据被写到 IR 或 DR
   DATA=dat;//dat:显示数据
   EN=1; //EN下降源
   _nop_();
   _nop_();
   EN=0;
}

 

/*选择屏幕screen: 0-全屏,1-左屏,2-右屏*/
void SelectScreen(uchar screen)  
{       
   switch(screen)
   { case 0: cs1=0;//全屏
             _nop_(); _nop_(); _nop_();
             cs2=0;
             _nop_(); _nop_(); _nop_();
             break;
     case 1: cs1=0;//左屏
             _nop_(); _nop_(); _nop_();
             cs2=1;
             _nop_(); _nop_(); _nop_();
             break;
     case 2: cs1=1;//右屏
             _nop_(); _nop_(); _nop_();
             cs2=0;
             _nop_(); _nop_(); _nop_();
             break;
   }
}

 /*清屏screen: 0-全屏,1-左屏,2-右*/
void ClearScreen(uchar screen)  
{  
     uchar i,j;
     SelectScreen(screen);
    
  for(i=0;i<8;i++)  //控制页数0-7,共8页
  {
         SetLine(i);
   SetColumn(0);
              for(j=0;j<64;j++)    //控制列数0-63,共64列
     {
                  WriteByte(0x00); //写点内容,列地址自动加1
              }
     }
     
}

/*延时程序*/
void delay(uint z)  
{
 uint i,j;
 for(i=0; i<z; i++)
  for(j = 0; j < 110; j++);
}

/*初始化LCD*/
void InitLCD()   
{

 CheckState();

 SelectScreen(0);
 SetOnOff(0); //关显示

 SelectScreen(0);
 SetOnOff(1); //开显示

 SelectScreen(0);
 ClearScreen(0);//清屏

 SetStartLine(0); //开始行:0

}

 


void GUI_Point(uchar x,uchar y,uchar flag)
{    
  uchar x_Dyte,x_byte;               //定义列地址的字节位,及在字节中的哪1位
  uchar y_Dyte,y_byte;               //定义为上下两个屏(取值为0,1),行地址(取值为0~31)
  uchar GDRAM_hbit;
  uchar GDRAM_lbit;
  uchar shuju;
  /***X,Y坐标互换,即普通的X,Y坐标***/
  x_Dyte=y/16;                     //计算在16个字节中的哪一个
  x_byte=y&0x0f;                   //计算在该字节中的哪一位
  y_Dyte=x/32;                     //0为上半屏,1为下半屏
  y_byte=x&0x1f;                   //计算在0~31当中的哪一行
 
 
             
  GDRAM_hbit=shuju&0xF0;             //读取当前显示高8位数据
  GDRAM_lbit=shuju&0x0F;             //读取当前显示低8位数据
   _nop_();
    _nop_();
  _nop_();
  

 
  if(flag==1)
  {
  SetStartLine(0x80+y_byte);           //设定行地址(y坐标)
   SetColumn(0x80+x_Dyte);     //设定列地址(x坐标)
  if(y_Dyte<32)
  {
   SelectScreen(2);
   }
   else
   {
   SelectScreen(0);
   }
 
    if(x_byte<8)                       //判断其在高8位,还是在低8位
  {
    WriteByte(GDRAM_hbit|(0X01<<(7-x_byte)));   //显示GDRAM区高8位数据
    WriteByte(GDRAM_lbit);               //显示GDRAM区低8位数据
    }
    else
    {
    WriteByte(GDRAM_hbit);
   WriteByte(GDRAM_lbit|(0x01<<(15-x_byte)));
    }
  }
  else
  {
  WriteByte(0x00);                   //清除GDRAM区高8位数据
  WriteByte(0x00);                   //清除GDRAM区低8位数据
  }   
}


/**********读取当前地址的LCD显示数据**********/
void Read_data()
{
uchar shuju;
RS=1;                          // D/I=1,代表数据
RW=1;                           // R/W=1.读取
delay(10);
EN=1;
delay(100);
shuju=DATA; //读取当前显示的数据
_nop_();
EN=0;
return;
}

void hualinex(uchar x0,uchar x1,uchar y,uchar flag)
{
uchar temp;
if(x0>x1)
{
temp=x1;
x1=x0;
x0=temp;
}
for(;x0<=x1;x0++)
GUI_Point(x0, y,flag);
}


/*主函数*/
void main()

    InitLCD();//初始12864
    
    ClearScreen(0);
    SetStartLine(0);//显示开始行
  
    while(1)
    { 
      hualinex(0,127,0,1);
  
  
}
}

 

 

回复

使用道具 举报

ID:22657 发表于 2010-4-1 10:46 | 显示全部楼层

大虾,请问有没有Proteus中的硬件电路图,

 

回复

使用道具 举报

ID:22657 发表于 2010-4-1 10:47 | 显示全部楼层

LCD_DATA  EQU  P0     ;液晶并行数据口

LCD_RS    EQU  P2.0   ;液晶指令数据选择:H=数据  L=指令

LCD_RW    EQU  P2.1   ;液晶读写信号控制: H=读    L=写

LCD_E     EQU  P2.2   ;液晶数据锁存信号: 下降沿锁存

LCD_SPB   EQU  P2.3   ;液晶通信格式: H=并行   L=串行

LCD_RES   EQU  P2.4   ;液晶复位信号: 低电平复位

POW_EN  EQU  P2.6

TX_EN   EQU  P2.5


DISP_ON   EQU  20H.0

SCAN_BIT  EQU  20H.1


;液晶显示区首地址:第一行:30H~3FH,第二行:40H~4FH,第三行:50H~5FH,第四行:60H~6FH

ORG 0000H

JMP MAIN


ORG 0023H

JMP RS_232


主程序:

MAIN:CLR DISP_ON

     CLR SCAN_BIT

     SETB POW_EN

     CLR TX_EN

     MOV R1,#30H     ;指向存储区首地址

     MOV R5,#0

     MOV R4,#0

     CALL LCD_INIT

     CALL RS232_INIT

     CALL DELY2

     CALL DELY2

      CALL DELY2

MAIN_LOOP:JNB DISP_ON,$

          CALL DISP_RAM

          CLR DISP_ON

          JMP MAIN_LOOP

          RET


串口初始化程序:

RS232_INIT:MOV TMOD,#20H

           MOV SCON,#50H

           MOV TL1,#0FAH

           MOV TH1,#0FAH

           SETB TR1

           SETB ES

           SETB EA

           RET


显示RAM区程序:

DISP_RAM:MOV A,#80H

         CALL WRITE_COM

         MOV R0,#30H               

DISP_RAM_JMP1:MOV A,@R0

         CALL WRITE_DATA

         INC R0

         CJNE R0,#40H,DISP_RAM_JMP1

         MOV A,#90H

         CALL WRITE_COM

DISP_RAM_JMP2:MOV A,@R0

         CALL WRITE_DATA

         INC R0

         CJNE R0,#50H,DISP_RAM_JMP2

         MOV A,#88H

         CALL WRITE_COM

DISP_RAM_JMP3:MOV A,@R0

         CALL WRITE_DATA

         INC R0

         CJNE R0,#60H,DISP_RAM_JMP3

         MOV A,#98H

         CALL WRITE_COM

DISP_RAM_JMP4:MOV A,@R0

         CALL WRITE_DATA

         INC R0

         CJNE R0,#70H,DISP_RAM_JMP4

         RET


液晶初始化程序:

LCD_INIT: CLR LCD_RES    ;复位

          CALL DELY2     ;复位延时

          CALL DELY2     ;复位延时

          SETB LCD_RES   ;复位结束

          CALL DELY2     ;复位延时

          CALL DELY2     ;复位延时

          SETB LCD_SPB   ;并行通信方式

          MOV  A,#30H

          CALL WRITE_COM

          CALL DELY1

          MOV  A,#03H

          CALL WRITE_COM

          CALL DELY1

          MOV  A,#0CH

          CALL WRITE_COM

          CALL DELY1

          MOV  A,#01H

          CALL WRITE_COM

          CALL DELY1

          MOV  A,#06H

          CALL WRITE_COM

          CALL DELY1

          RET

液晶写指令,入口地址A

WRITE_COM:CLR LCD_RS

          CLR LCD_RW

          SETB LCD_E

          MOV LCD_DATA,A

          NOP

          NOP

          CLR LCD_E

          CALL DELY1

          RET

液晶写数据,入口地址A

WRITE_DATA:SETB LCD_RS

           CLR LCD_RW

           SETB LCD_E

           MOV LCD_DATA,A

           NOP

           NOP

           CLR LCD_E

           CALL DELY1

           RET

延时程序1

DELY1:MOV R7,#255

      DJNZ R7,$

      RET

延时程序2

DELY2:MOV R6,#255

DELY2_JMP1:CALL DELY1

           DJNZ R6,DELY2_JMP1

           RET


串口中断程序

RS_232:PUSH A

     MOV A,SBUF

JB SCAN_BIT,RS_232_JMP1

     CJNE A,#99H,RS_232_JMP0

     INC R5

     CJNE R5,#2,RS_232_EXIT

     MOV R1,#30H

MOV R4,#0

     SETB SCAN_BIT

     RS_232_JMP0:MOV R5,#0

     JMP RS_232_EXIT

RS_232_JMP1:CJNE A,#0AAH,RS_232_JMP2

     INC R4

     CJNE R4,#3,RS_232_JMP3

     MOV R5,#0

     CLR SCAN_BIT

     SETB DISP_ON

     JMP RS_232_EXIT

RS_232_JMP2:MOV R4,#0

RS_232_JMP3:CJNE R1,#70H,RS_232_JMP4

    JMP RS_232_EXIT

RS_232_JMP4:MOV @R1,A

INC RRS_232_EXIT:POP A

    CLR RI

    RETI


回复

使用道具 举报

ID:22739 发表于 2010-4-1 16:23 | 显示全部楼层
snap1.jpg
回复

使用道具 举报

ID:22657 发表于 2010-4-5 08:35 | 显示全部楼层

要么就是电压不稳,要么就是CS1、CS2问题,因为它们两个不能够联在一起一个是显示左半,一个是显示右半的吗

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表