winnie 发表于 2009-4-25 15:04:37

一个picc编的192x64液晶显示问题

我用的是pic16f877,液晶模块是LM19264D-4 (三星s6b0108),192x64的。可是当我用icd2调试时,
发现该程序总是跳不出wtcom()里面这个循环:
   do{
       RA2=0;
       RA2=1;      
   }while(PORTD&0x80);   //判断最高位状态,如果是1,则反复送E时续,直到LCD空闲
也就是说液晶一直忙? 按理说不应该啊,找了好久,没有发现原因,恳请大虾给予指点,感激不尽。
整个程序是这样的:
#include<pic.h>

#define Uchar unsigned char
//***********操作命令和参数定义***************
#defineDISPON0x3f //*显示on*/
#defineDISPOFF 0x3e //*显示off*/
#defineDISPFIRST 0xc0 //*显示起始行定义*/
#defineSETX0xb8 //*X定位设定指令(页)*/
#defineSETY0x40 //*Y定位设定指令(列)*/
#defineLcdbusy 0x80 //*LCM忙判断位*/
//**************显示分区边界位置*****************/
#defineMODL0x00 //*左区*/
#defineMODM0x40 //*左区和中区分界*/
#defineMODR0x80 //*中区和右区分界*/
#define LCMLIMIT 0xC0 //*显示区的右边界*/
//****************全局变量定义*******************/
Uchar col,row,cbyte;//*列x,行(页)y,输出数据 */
//*****************函数列表**********************/
void INITIAL(void);   //*系统各口的输入输出状态初始化子程序*/
void Lcminit(void);//*液晶模块初始化 */
void Delay(Uchar);//*延时,入口数为Ms */
void lcdbusyL(void);//*busy判断、等待(左区) */
void lcdbusyM(void);//*busy判断、等待(中区) */
void lcdbusyR(void);//*busy判断、等待(右区) */
void Putcdot(Uchar);//*全角(汉字)输出 */
void Wrdata(Uchar);//*数据输出给LCM*/
void Lcmcls(void);//*LCM全屏幕清零(填充0) */
void wtcom(void);//*公用busy等待*/
void Locatexy(void);//*光标定位*/
void WrcmdL(Uchar);//*左区命令输出*/
void WrcmdM(Uchar);//*中区命令输出*/
void WrcmdR(Uchar);//*右区命令输出*/
//******************数组列表*********************/
UcharHzk[];//*自用汉字点阵码表 */


//********************************************************/
//*      系统各口的输入输出状态初始化子程序            */
//********************************************************/
void INITIAL(void)
{
   ADCON1=0x87;      //设置PORTA口和PORTE口为数字I/O口
   PORTA=0;
   PORTE=0;                              
   PORTD=0;                                     //先清零A、E、D口,避免干扰
   TRISA0=0;
   TRISA1=0;
   TRISA2=0;
   TRISA4=0;
   TRISA5=0;
   TRISE=0x00;      //设置液晶的控制脚为输出
   TRISD=0xff;      //D口输入
   RA5=1;         // RST=1,使normal running
   RE2=1;         //LCD_BLA=1,点亮背景灯
}
//液晶屏初始化
void Lcminit(void)
{
   cbyte = DISPOFF; //*关闭显示屏(注:DISPOFF=0x3e) */
   WrcmdL(cbyte);   //*命令输出到左区控制口*/
   WrcmdM(cbyte);
   WrcmdR(cbyte);
   cbyte = DISPON; //*打开显示屏(注:DISPOFF=0x3f)*/
   WrcmdL(cbyte);//*命令输出到左区控制口*/
   WrcmdM(cbyte);
   WrcmdR(cbyte);
   cbyte = DISPFIRST; //*定义显示起始行为零(注:DISPFIRST=0xc0)*/
   WrcmdL(cbyte);   //*命令输出到左区控制口*/
   WrcmdM(cbyte);
   WrcmdR(cbyte);
   Lcmcls();
   col=0; //*清屏 */
   row=0;
   Locatexy();
}
//********************************/
//* 延时子程序   */
//********************************/
void Delay(Uchar MS)
{
Uchar us,usn;
while(MS!=0)
   { usn = 4;
    while(usn!=0)
   {
      us=0xf0;
      while (us!=0){us--;};
      usn--;
   }
    MS--;
   }
}

//********************************/
//* 命令输出到左区控制口 */
//********************************/
void WrcmdL(Uchar X)
{
lcdbusyL(); //*确定分区,返回时保留分区状态不变*/
TRISD=0x00;   //D口为输出
RA0= 0; //* LCD_RS=0,为命令操作*/
RA1 = 0; //*LCD_WR=0,为写输出 */
RA2 = 1;
PORTD = X; //*数据输出到数据口 */
asm("nop") ;
RA2 = 0; //*E:1->0,写入到LCM*/
TRISD=0xff;            //写完数据,立即把IO口设定成高阻,提高可靠性。
}
//********************************/
//* 命令输出到中区控制口*/
//********************************/
void WrcmdM(Uchar X)
{
   lcdbusyM();//*确定分区,返回时保留分区状态不变*/
   TRISD=0x00;   //D口为输出
   RA0= 0; //* LCD_RS=0,为命令操作*/
   RA1 = 0; //*LCD_WR=0,为写输出 */
   RA2 = 1;
   PORTD = X; //*数据输出到数据口 */
   asm("nop");
   RA2 = 0; //*E:1->0,写入到LCM*/
   TRISD=0xff;            //写完数据,立即把IO口设定成高阻,提高可靠性。
}
//********************************/
//* 命令输出到右区控制口*/
//********************************/
void WrcmdR(Uchar X)
{
   lcdbusyR(); //*确定分区,返回时保留分区状态不变 */
   TRISD=0x00;   //D口为输出
   RA0= 0; //* LCD_RS=0,为命令操作*/
   RA1 = 0; //*LCD_WR=0,为写输出 */
   RA2 = 1;
   PORTD = X; //*数据输出到数据口 */
   asm("nop") ;
   RA2 = 0; //*E:1->0,写入到LCM*/
   TRISD=0xff;            //写完数据,立即把IO口设定成高阻,提高可靠性。
}
//********************************************************/
//* 分区操作允许等待,返回时保留分区选择状态 */
//********************************************************/
void lcdbusyL(void)
{
RA4 = 0; //*CLR CS1 */
RE0 = 1; //*SETB CS2 */
RE1 = 1; //*SETB CS3 */
wtcom(); //* waiting for enable */
}
void lcdbusyM(void)
{
   RA4= 1;//*SETB CS1*/
   RE0= 0;//*CLR CS2*/
   RE1= 1;//*SETB CS3*/
   wtcom();//* waiting for enable */
}
void lcdbusyR(void)
{
    RA4= 1;//*SETB CS1*/
    RE0 = 1;//*SETB CS2*/
    RE1 = 0;//*CLR CS3*/
    wtcom();//* waiting for enable */
}
//*公用busy等待 */
void wtcom(void)
{
TRISD=0xff;      //D口输入
RA0 = 0; //*RS=0/
RA1= 1; //*WR=1*/

   do{
       RA2=0;
       RA2=1;      
   }while(PORTD&0x80);   //判断最高位状态,如果是1,则反复送E时续,直到LCD空闲
   RA2= 0;               //及时拉低E,使DB口处于高阻状态,提高可靠性
}
//****************************************/
//* 清屏,全屏幕清零*/
//****************************************/
void Lcmcls( void )
{
    for(row=0;row<8;row++)
      for(col=0;col<LCMLIMIT;col++) Wrdata(0);
}
//****************************************/
//* 数据写输出   */
//****************************************/
void Wrdata(Uchar X)
{
Locatexy();//*坐标定位,返回时保留分区状态不变*/
wtcom();
TRISD=0x00;
RA0 = 1; //*数据输出*/
RA1= 0; //*写输出*/
RA2= 1;
PORTD = X; //*数据输出到数据口 */
asm("nop") ;
RA2 = 0;
}
//********************************************************/
//*根据设定的坐标数据,定位LCM上的下一个操作单元位置 */
//********************************************************/
void Locatexy(void)
{
   unsigned charx,y;
   switch (col&0xc0)//*col.and.0xC0 */
{   //*条件分支执行*/
   case 0:   {lcdbusyL();break;} //*左区 */
   case 0x40:   {lcdbusyM();break;} //*中区 */
   case 0x80:   {lcdbusyR();break;} //*右区 */
}
x = (col&0x3F|SETX);//*col.and.0x3f.or.setx */
y = (row&0x07|SETY);//*row.and.0x07.or.sety */
wtcom();//*waiting for enable*/
      TRISD=0x00;
RA0= 0;   //*CLR DI */
RA1= 0;   //*CLR RW */
                RA2= 1;
PORTD= y;   //*MOV P0,Y */
asm("nop");
                RA2= 0;
wtcom();//*waiting for enable*/
      TRISD=0x00;
RA0= 0;   //*CLR DI */
RA1 = 0;   //*CLR RW */
                RA2 = 1;
PORTD = x;   //*MOV P0,X */
asm("nop") ;
                RA2= 0;
}
//****************************************/
//*全角字符点阵码(汉字)数据输出      */
//****************************************/
void Putcdot(Uchar Order)
{
Uchar i,bakerx,bakery;//*共定义3个局部变量*/
int x;    //*偏移量,字符量少的可以定义为UCHAR */
bakerx = col;   //*暂存x,y坐标,已备下半个字符使用 */
bakery = row;
x=Order * 0x20;//*每个字符32字节 */

//*上半个字符输出,16列 */
for(i=0;i<16;i++)
{
Wrdata(Hzk);   //*写输出一字节*/
x++;
col++;
if (col==LCMLIMIT){ col=0;row++;} //*下一列,如果列越界换行*/
   if (row>6) row=0;//*如果行越界,返回首行 */
}   //*上半个字符输出结束 */

//*下半个字符输出,16列 */
col = bakerx;
row = bakery+1;
for(i=0;i<16;i++)    //*下半部分*/
{
Wrdata(Hzk);
x++;
col++;
if (col==LCMLIMIT){col=0;row++;row++;} //*下一列,如果列越界换行*/
   if (row>7) row=1;//*如果行越界,返回首行 */
}   //*下半个字符输出结束 */
row = bakery;
}      //*整个字符输出结束 */
//********************************/
//*定义中文字库*/
//********************************/
UcharHzk[]={
//*--文字:启--*/
0x00,0x00,0x00,0x00,0x1F,0x12,0x12,0x92,
         0x52,0x24,0x24,0x3C,0x00,0x00,0x00,0x00,
         0x02,0x04,0x18,0xE0,0x00,0x7E,0x44,0x44,
         0x44,0x88,0x88,0xF8,0x00,0x00,0x00,0x00,
//*--文字:动--*/
         0x00,0x02,0x02,0x13,0x14,0x24,0x24,0x00,
         0x04,0x05,0xFE,0x08,0x0F,0x00,0x00,0x00,
         0x00,0x00,0x70,0x90,0x20,0xA2,0x64,0x18,
         0x60,0x88,0x04,0x18,0xE0,0x00,0x00,0x00,
};
//********************************/
//*          主程序*/
//********************************/
void main()
{
INITIAL();
    col=0;
    row=0;
    Delay(240);//*延时大约40Ms,等待外设准备好*/
    Lcminit();      //*液晶模块初始化包括全屏幕清屏*/
   
   Putcdot(1);         //*第一个汉字输出*/
   // while(1)
    {
       ;
    }

}
页: [1]
查看完整版本: 一个picc编的192x64液晶显示问题