赞助论坛
  • 3757阅读
  • 0回复

发一个我自己写的51控制字符型LCD 源程序,希望大家一起完善。 [复制链接]

楼层直达
hahanet  
发帖
19
精华
0
金币
26
威望
2
贡献
0
好评
0
注册
2008-12-25
楼主    hahanet 发表于: 2008-12-26 00:06:34 
自己写的51控制字符型LCD 源程序,希望大家一起完善.
可输出一个8位的16进制等

#ifndef __REG52_H__
   #include <REG52.H>
#endif

#ifndef __INTRINS_H__
   #include <INTRINS.H>
#endif




#define HIGH_LEVEL 1
#define LOW_LEVEL 0
#ifndef LCD_BUS4Bit
   #define LCD_BUS4Bit 0 //定义LCD的总线宽度是否为4位 1为是 0为否
#ednif
#if LCD_BUS4Bit //此处定义LCD的4位总线是在8位中的是高4位还是低4位,只能二选一
   //#define LCD_BUS4Bit_HIGH //定义LCD的4位总线是在8位中的高4位
   #ifndef LCD_BUS4Bit_HIGH
       #ifndf LCD_BUS4Bit_LOW
           #define LCD_BUS4Bit_LOW    //定义LCD的4位总线是在8位中的低4位
       #endif
   #endif
#endif

#ifndef LCD_RS_PORT_ADD
   #define LCD_RS_PORT_ADD 0xa6 //p2.6
#endif

#ifndef LCD_RW_PORT_ADD
   #define LCD_RW_PORT_ADD 0xa7 //P2.7
#endif

#ifndef LCD_EN_PORT_ADD
   #define LCD_EN_PORT_ADD 0xb7 //P3.7
#endif

#ifndef LCD_BUS_PORT_ADD
   #define LCD_BUS_PORT_ADD 0xa0     //P2
#endif

#ifndef LCD_X_LINE
   #define LCD_X_LINE 4
#endif

#ifndef LCD_X_CHAR_1LINE
   #define LCD_X_CHAR_1LINE 16
#endif




sbit LCD_RS=LCD_RS_PORT_ADD; //定义Lcd的RS脚
sbit LCD_RW=LCD_RW_PORT_ADD; //定义LCD的RW脚
sbit LCD_EN=LCD_EN_PORT_ADD; //定义LCD的EN脚
sfr LCDBUS=LCD_BUS_PORT_ADD;    //定义LCD的总线端口

unsigned char code LCD_CGRAM[64]={
/*            0x1c,0x14,0x1c,0x00,0x00,0x00,0x00,0x00, //自定义字符00字符代码0x00 显示“°”
           0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //自定义字符01字符代码0x01 显示“°”
           0x00,0x1f,0x00,0x00,0x00,0x00,0x00,0x00, //自定义字符02字符代码0x02 显示“°”
           0x1f,0x1f,0x00,0x00,0x00,0x00,0x00,0x00, //自定义字符03字符代码0x03 显示“°”
           0x00,0x00,0x1f,0x00,0x00,0x00,0x00,0x00, //自定义字符04字符代码0x04 显示“°”
           0x1f,0x00,0x1f,0x00,0x00,0x00,0x00,0x00, //自定义字符05字符代码0x05 显示“°”
           0x00,0x1f,0x1f,0x00,0x00,0x00,0x00,0x00, //自定义字符06字符代码0x06 显示“°”
           0x1f,0x1f,0x1f,0x00,0x00,0x00,0x00,0x00, //自定义字符07字符代码0x07 显示“°”
*/
   0x1c,0x14,0x1c,0x00,0x00,0x00,0x00,0x00,    //自定义字符00字符代码0x00 显示“°”
//   0x0e,0x00,0x1f,0x0a,0x0a,0x0a,0x13,0x00,   //"元"代码
  0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02,   //"年"代码
  0x0f,0x09,0x0f,0x09,0x0f,0x09,0x11,0x00,   //"月"代码
  0x1f,0x11,0x11,0x1f,0x11,0x11,0x1f,0x00,   //"日"代码
  0x00,0x1F,0x15,0x15,0x1B,0x11,0x1F,0x00,   //"四"代码
  0x1F,0x08,0x1e,0x0A,0x0A,0x12,0x1F,0x00,   //"五"代码
  0x08,0x04,0x1F,0x00,0x0A,0x11,0x00,0x00,   //"六"代码
//    0x11,0x1b,0x1f,0x1f,0x1f,0x0e,0x04,0x00,
   0x1c,0x14,0x1c,0x00,0x00,0x00,0x00,0x00,    //自定义字符00字符代码0x00 显示“°”
//   0x00,0x10,0x08,0x04,0x02,0x01,0x00,0x00,   //"\"代码

           };


//unsigned char lcdcounter;

unsigned char lcd_rddate(void) //返回LCD的数据
{
   register lcdstate;
#if LCD_BUS4Bit
   register i;
#endif
   LCD_RS=LOW_LEVEL;
   LCD_RW=HIGH_LEVEL;
#if LCD_BUS4Bit
//lcd总线为4位时的读
   #ifdef LCD_BUS4Bit_HIGH //LCD总线为高4位
       LCDBUS|=0xf0;
       LCD_EN=HIGH_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       i=LCDBUS;
       lcdstate=i&0xf0;
       _nop_();
       _nop_();
       _nop_();
       LCD_EN=LOW_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCDBUS|=0xf0;
       LCD_EN=HIGH_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       i=LCDBUS>>4;
       i&=0x0f;
       lcdstate|=i;
       _nop_();
       _nop_();
       _nop_();
   #endif
   #ifdef LCD_BUS4Bit_LOW //LCD总线为低4位
       LCDBUS|=0x0f;
       LCD_EN=HIGH_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       i=LCDBUS;
       lcdstate=i<<4;
       _nop_();
       _nop_();
       _nop_();
       LCD_EN=LOW_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCDBUS|=0x0f;
       LCD_EN=HIGH_LEVEL;
       _nop_();
       _nop_();
       _nop_();

       i=LCDBUS;
       i&=0x0f;
       lcdstate|=i;
       _nop_();
       _nop_();
       _nop_();

   #endif
#else
       LCDBUS=0xff;
       LCD_EN=HIGH_LEVEL;
       _nop_();
       _nop_();
       _nop_();

       lcdstate=LCDBUS;
       _nop_();
       _nop_();
       _nop_();

#endif        
   LCD_EN=LOW_LEVEL;
   return(lcdstate);
}


void lcd_wrcmd(unsigned char lcd_cmd) //写LCD命令
{
       unsigned int i;
       i=3000;
       while ((bit)(lcd_rddate()&0x80))
       {
           if (--i == 0) break;
       }
#if LCD_BUS4Bit
//lcd总线为4位时的写
   #ifdef LCD_BUS4Bit_HIGH //LCD总线为高4位
       LCDBUS&=0x0f;
       LCDBUS|=lcd_cmd&0xf0;
       LCD_RS=LOW_LEVEL;
       LCD_RW=LOW_LEVEL;
       LCD_EN=HIGH_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCD_EN=LOW_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCDBUS&=0x0f;
       LCDBUS|=lcd_cmd<<4;
       LCD_EN=HIGH_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCD_EN=LOW_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCD_RW=HIGH_LEVEL;
       LCDBUS|=0xf0;
   #endif
   #ifdef LCD_BUS4Bit_LOW //LCD总线为低4位
       LCDBUS&=0xf0;
       LCDBUS|=lcd_cmd>>4;
       LCD_RS=LOW_LEVEL;
       LCD_RW=LOW_LEVEL;
       LCD_EN=HIGH_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCD_EN=LOW_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCDBUS&=0xf0;
       LCDBUS|=lcd_cmd&0x0f;
       LCD_EN=HIGH_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCD_EN=LOW_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCD_RW=HIGH_LEVEL;
       LCDBUS|=0x0f;
   #endif
#else
//lcd总线为8位时的写
       LCDBUS=lcd_cmd;
       LCD_RS=LOW_LEVEL;
       LCD_RW=LOW_LEVEL;
       LCD_EN=HIGH_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCD_EN=LOW_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCDBUS=0xff;
#endif
}

void lcd_moveto(unsigned char position)
{
   register cmd=0x80;
   cmd=cmd|position;
   lcd_wrcmd(cmd);
}


void lcd_wrdata(char lcddata)    //写LCD数据
{
       unsigned int i;
       i=3000;
       while((bit)(lcd_rddate()&0x80))
       {
           if (--i == 0) break;
       }

#if LCD_BUS4Bit
//lcd总线为4位时的写
   #ifdef LCD_BUS4Bit_HIGH //LCD总线为高4位
       LCDBUS&=0x0f;
       LCDBUS|=lcddata&0xf0;
       LCD_RS=HIGH_LEVEL;
       LCD_RW=LOW_LEVEL;
       LCD_EN=HIGH_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCD_EN=LOW_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCDBUS&=0x0f;
       LCDBUS|=lcddata<<4;
       LCD_EN=HIGH_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCD_EN=LOW_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCD_RW=HIGH_LEVEL;
       LCDBUS|=0xf0;
   #endif
   #ifdef LCD_BUS4Bit_LOW //LCD总线为低4位
       LCDBUS&=0xf0;
       LCDBUS|=lcddata>>4;
       LCD_RS=HIGH_LEVEL;
       LCD_RW=LOW_LEVEL;
       LCD_EN=HIGH_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCD_EN=LOW_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCDBUS&=0xf0;
       LCDBUS|=lcddata&0x0f;
       LCD_EN=HIGH_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCD_EN=LOW_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCD_RW=HIGH_LEVEL;
       LCDBUS|=0x0f;
   #endif
#else
//lcd总线为8位时的写
       LCDBUS=lcddata;
       LCD_RS=HIGH_LEVEL;
       LCD_RW=LOW_LEVEL;
       LCD_EN=HIGH_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCD_EN=LOW_LEVEL;
       _nop_();
       _nop_();
       _nop_();
       LCDBUS=0xff;
#endif    
   }

void lcd_cls(unsigned char line)
{    
   unsigned char i;
   if(line==-1) //是否为全屏清屏
       {lcd_wrcmd(0x01); //全屏清屏
       }
   else {
       //以下为单行清屏
       line%=LCD_X_LINE;
       switch (line)
       {
           case 0:
               lcd_moveto(0x00);
               break;
           case 1:
               lcd_moveto(0x40);
               break;
           case 2:
               lcd_moveto(0x14);
               break;
           case 3:
               lcd_moveto(0x54);
               break;
       }
       for (i=0;i<LCD_X_CHAR_1LINE;i++)
           {lcd_wrdata(0x20);
           }
       }
}





void lcd_string(char *strpoint)
{
   register i=0;
   while (strpoint[i]!=0){
       lcd_wrdata(strpoint[i]);
       i++;
   }
}

unsigned char lcd_CR(void)
{
   register ret_code=0;
   register i=0;
   i=lcd_rddate()&0x7f;
   if (i<=0x14)   //第一行的回车
       {
       if (LCD_X_LINE>=2)
           {
           lcd_moveto(0x40);
           }
       else
           {
           ret_code=-1;
           }
       
       }
   else if (i<=0x27&&i>0x14)     //第三行的回车
       {
       lcd_moveto(0x54);
       }

   else if (i<=0x54&&i>0x40)     //第二行的回车
       {

       if (LCD_X_LINE>2)
           {
           lcd_moveto(0x14);
           }
       else
           {
           ret_code=-1;
           }
       
       }
   else if (i<=0x67&&i>0x54)         //第四行的回车
       {
           ret_code=-1;
       }
   return(ret_code);    

}

unsigned char lcd_printf(char *strpoint)
{
   register i=0;
   register temp_point=0;
   register ret_code=0;
   while (strpoint[i]!=0){
       if (strpoint[i]==0x0a)
           {
           if(lcd_CR()!=0)
               {
                   ret_code=-1;
                   break;
               }
           i++;
           if(strpoint[i]==0){
               break;
           }
           }
       temp_point=lcd_rddate()&0x7f;
       //判断光标是否在行尾        

                       switch (temp_point) {
                           case LCD_X_CHAR_1LINE :
                           case 0x40+LCD_X_CHAR_1LINE :
                           case 0x14+LCD_X_CHAR_1LINE :
                           case 0x54+LCD_X_CHAR_1LINE :
                               {
                               if(lcd_CR()!=0)
                                   {
                                   ret_code=-1;
                                   }
                               break;
                               }
                           
                           }
                       if(ret_code==-1)
                           {
                            break;
                           }

         



       //判断是否输出到显示屏的最后一个字符    

       if (temp_point!=0x27){
           if (temp_point!=0x67){
               lcd_wrdata(strpoint[i]);
               }
           else {
               lcd_wrdata(strpoint[i]);
               if (strpoint[i+1]==0){
                   break;
                   }
               else {
                   ret_code=-1;
                   break;
                   }
              }
           }
       else {
           lcd_wrdata(strpoint[i]);
           lcd_moveto(0x54);
           }

       i++;
   }
return(ret_code);
}                                                                                            

//LCD按位置输出字符串

void lcd_point_print(char *strpoint,unsigned char print_line,unsigned char start_point)
{
   register unsigned char i;
   print_line%=LCD_X_LINE;
   if (start_point<LCD_X_CHAR_1LINE){
       switch(print_line){
           case 0:
               lcd_moveto(0x00+start_point);
               break;
           case 1:
               lcd_moveto(0x40+start_point);
               break;
           case 2:
               lcd_moveto(0x14+start_point);
               break;
           case 3:
               lcd_moveto(0x54+start_point);
               break;
       }
       for (i=0;i<LCD_X_CHAR_1LINE-start_point;i++){
           if (strpoint[i]!=0){
               lcd_wrdata(strpoint[i]);
           }
           else {
               break;
           }
       }
   }
}

//输出单字符
void lcd_char_print(char out_char,unsigned char print_line,unsigned char start_point)
{
   print_line%=LCD_X_LINE;
   #ifdef DEBUG            
       printf("start_point=%x\n",(int)(start_point));
   #endif
   if (start_point<LCD_X_CHAR_1LINE){
       switch(print_line){
           case 0:
               lcd_moveto(0x00+start_point);
               break;
           case 1:
               lcd_moveto(0x40+start_point);
               break;
           case 2:
               lcd_moveto(0x14+start_point);
               break;
           case 3:
               lcd_moveto(0x54+start_point);
               break;
       }
       lcd_wrdata(out_char);

       
   }
}

void lcd_hex_print(unsigned char out_hex,unsigned char print_line,unsigned char start_point)
{
   
   print_line%=LCD_X_LINE;
   #ifdef DEBUG            
       printf("start_point=%x\n",(int)(start_point));
   #endif
   if (start_point<LCD_X_CHAR_1LINE){
       switch(print_line){
           case 0:
               lcd_moveto(0x00+start_point);
               break;
           case 1:
               lcd_moveto(0x40+start_point);
               break;
           case 2:
               lcd_moveto(0x14+start_point);
               break;
           case 3:
               lcd_moveto(0x54+start_point);
               break;
       }
       if ((out_hex>>4)>9){
           lcd_wrdata(0X37+(out_hex>>4));
       }
       else {
           lcd_wrdata(0X30+(out_hex>>4));
       }
       if ((out_hex&0x0f)>9){
           lcd_wrdata(0X37+(out_hex&0x0f));
       }
       else {
           lcd_wrdata(0X30+(out_hex&0x0f));
       }


   }

}


//LCD 从行开始输出字符串
void lcd_line_print(char *strpoint,unsigned char print_line)
{
   register unsigned char i;
   print_line=print_line%LCD_X_LINE;
   lcd_cls(print_line);
   switch (print_line)
       {
           case 0:
               lcd_moveto(0x00);
               break;
           case 1:
               lcd_moveto(0x40);
               break;
           case 2:
               lcd_moveto(0x14);
               break;
           case 3:
               lcd_moveto(0x54);
               break;
       }
   for (i=0;i<LCD_X_CHAR_1LINE;i++){
       if (strpoint[i]!=0){
           lcd_wrdata(strpoint[i]);
           }
       else{
           break;
           }        
   }
}




void lcd_init()
{                                                                              
   register unsigned int i;                                                            
#if LCD_BUS4Bit
   lcd_wrcmd(0x28);    //4BIT 2 line 5*7
#else
   lcd_wrcmd(0x38);    //8BIT 2 line 5*7
#endif
   for (i=0;i<30000;i++)    //软件延时
       {
           _nop_();
           _nop_();
           _nop_();
       }

#if LCD_BUS4Bit
   lcd_wrcmd(0x28);    //4BIT 2 line 5*7
#else
   lcd_wrcmd(0x38);    //8BIT 2 line 5*7
#endif
   for (i=0;i<30000;i++)    //软件延时
       {
           _nop_();
           _nop_();
           _nop_();
       }

#if LCD_BUS4Bit
   lcd_wrcmd(0x28);    //4BIT 2 line 5*7
#else
   lcd_wrcmd(0x38);    //8BIT 2 line 5*7
#endif
   lcd_wrcmd(0x0c);    //display on
   lcd_wrcmd(0x06);
   lcd_wrcmd(0x01);
   //写CGram
   lcd_wrcmd(0x40);
   
   for (i=0;i<64;i++)
       {
           lcd_wrdata(LCD_CGRAM[i]);
       }

}