找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 13109|回复: 2
打印 上一主题 下一主题
收起左侧

51单片机的LCD1602与12864函数-C

[复制链接]
跳转到指定楼层
楼主
ID:70941 发表于 2015-3-21 05:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
      
LCD1602和LCD12864的函数库,包括并行与串行

lcd12864
带中文字库的128X64 是一种具有4 位/8 位并行、2 线或3 线串行多种接口方式,内部含有国标一级、二级简体 中文字库的点阵图形液晶显示模块;其显示分辨率为128×64, 内置8192 个16*16 点汉字,和128 个16*8 点ASCII 字符 集.利用该模块灵活的接口方式和简单、方便的操作指令,可构成全中文人机交互图形界面。可以显示8×4 行16×16 点 阵的汉字. 也可完成图形显示.低电压低功耗是其又一显著特点。由该模块构成的液晶显示方案与同类型的图形点阵液晶 显示模块相比,不论硬件电路结构或显示程序都要简洁得多,且该模块的价格也略低于相同点阵的图形液晶模块。
LCD1602
1602液晶也叫1602字符型液晶,它是一种专门用来显示字母、数字、符号等的点阵型液晶模块。它由若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,正因为如此所以它不能很好地显示图形(用自定义CGRAM,显示效果也不好)。
1602LCD是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)。



LCD1602基础驱动函数#ifndef __LCD1602_JCK_C__
#define __LCD1602_JCK_C__
/************************************************
**                                              **
**            六哥LCD1602基础函数库              **
**                                              **
**************************************************/

//使用请注意定义引脚


#include"yscx.c"


/*****************************************************************
              LCD1602判忙函数
******************************************************************/
void LCD1602_PM(void)
{
unsigned char temp1;//状态信息(判断是否忙)
LCD1602_SJ=0xFF;//记得在包含该头文件前,定义引脚
LCD1602_RS=0; //记得在包含该头文件前,定义引脚
LCD1602_RW=1; //记得在包含该头文件前,定义引脚
LCD1602_E=1;  //记得在包含该头文件前,定义引脚
do
   {temp1 = LCD1602_SJ;//记得在包含该头文件前,定义引脚
    LCD1602_SJ=0xFF;
    }
while(temp1&0x80);
LCD1602_E=0;//记得在包含该头文件前,定义引脚
YS_us(1);        //
}
/*------------------------------------------------
              LCD1602写入命令函数
------------------------------------------------*/
void LCD1602_XZL(unsigned char ml)
{
LCD1602_PM(); //忙则等待
LCD1602_RS= 0; //记得在包含该头文件前,定义引脚
LCD1602_RW= 0; //记得在包含该头文件前,定义引脚
LCD1602_E = 1;//记得在包含该头文件前,定义引脚
LCD1602_SJ=ml; //记得在包含该头文件前,定义引脚
YS_us(1);//稍作延时给LCD反应的时间
LCD1602_E = 0;//记得在包含该头文件前,定义引脚
if(ml==0x01|ml==0x02) YS_ms(2);//清屏和地址归位大概需2ms时间处理
YS_us(35);//其他指令大概需35us
}
/*------------------------------------------------
              LCD1602写入数据函数
------------------------------------------------*/
void LCD1602_XSJ(unsigned char sj)
{
LCD1602_PM(); //忙则等待
LCD1602_RS=1; //记得在包含该头文件前,定义引脚
LCD1602_RW=0; //记得在包含该头文件前,定义引脚
LCD1602_E= 1;//记得在包含该头文件前,定义引脚
LCD1602_SJ=sj; //记得在包含该头文件前,定义引脚
YS_us(1);//稍作延时给LCD反应的时间
LCD1602_E= 0;//记得在包含该头文件前,定义引脚
}  

/*------------------------------------------------
              LCD1602初始化函数
------------------------------------------------*/
void LCD1602_CSH(void)
{
  LCD1602_XZL(0x38);    /*显示模式设置*/
  LCD1602_XZL(0x08);    /*显示光标移动设置*/   
  LCD1602_XZL(0x01);    /*显示开及光标设置*/
  LCD1602_XZL(0X06);
  LCD1602_XZL(0X0c);
  }


#endif

LCD1602显示函数

#ifndef __LCD1602_XSK_C__
#define __LCD1602_XSK_C__

/************************************************
*******                                 *********
*******       六哥LCD1602显示函数库     *********
*******                                 *********
************************************************/


#include"yscx.C"
#include"LCD1602_JCK_cx.C"

//为保证显示数制时的运行效率,制作了0—9,A—F的ascll码表
unsigned char  code ascll1602[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46};


/******************************************************
***************LCD1602数制显示(十或十六)************
*******************************************************
sj:需要显示的数据
ml:显示地址设定
xsfs:显示方式,进制和小数点的判断依据,
*/
void LCD1602_SZXS(signed long sj,unsigned char xsfs,ml)///wei为1输出十六进制,否则输出十进制
{
unsigned long xc;     //显示缓存                                 
unsigned char a;
bit xsd,fs,bf=0;
xsd=0;
fs=0;

LCD1602_XZL(0x04);//设置光标向左移
LCD1602_XZL(ml);

if(xsfs>10)
    {a=16;             //输出十六进制
     LCD1602_XSJ(0x48);//显示H
     xsfs=0;}          //
   else
      {a=10;   //否则输出十进制
       if(xsfs!=0) xsd=1;//显示小数点使能
       if(sj<0)
          {sj=~sj+1;
           fs=1;}       //显示负号使能
       }
xc=sj;

if(xc!=0)       //显示数据不为0;则显示
    {while(xsd)            //判是否需要显示小数
        {if(xc!=0)         //是否还需要计算
            {ml=xc%a;
             if(bf|ml!=0)  //小数部分为0不需要显示
                {LCD1602_XSJ(ascll1602[ml]); //取数的ascll码并显示
                 bf=1;     //小数部分不为0标志,小数部分数字有效
                 }
             xc/=a;        //取剩下的数
             }
           else if(bf) LCD1602_XSJ(0x30);//判是否需要补0
             else;            //小数部分无效,不需要补0

         xsfs--;
         if(xsfs==0)                    //小数点位数减一
            {xsd=0;                     //小数计算部分结束标志
             if(bf) LCD1602_XSJ(0x2e);  //小数部分存在有效数字则显示小数点
             }
         }
     }
////////////整数显示部分////////////////////////////////////////////
do
   {LCD1602_XSJ(ascll1602[xc%a]); //取数的ascll码并显示
    xc/=a;        
    }
while(xc!=0);
      
if(fs) LCD1602_XSJ(0x2d);//判是否需要显示负号

LCD1602_XZL(0x06);//还原光标移动方向

}



/********************************
     LCD1602LCD1602字符显示程序
*********************************/


void LCD1602_ZFXS(unsigned char *SJ,t,ml)/*h:行,SJ:字符串指针,t:间隔时间*/
{
LCD1602_XZL(ml); //写指令  

while(*SJ)//是否显示完
    {
     LCD1602_XSJ(*SJ);//写数据
     SJ++;        //取下一个字符
     YS_ms(t);    //延时
     }
}

#endif


LCD12864基础驱动函数并行

#ifndef __LCD12864_JCK_C__
#define __LCD12864_JCK_C__
/************************************************
**                                             **
**            六哥LCD12864基础函数库            **
**                                              **
**************************************************/

//使用请注意定义引脚
//通讯方式为并口PSB=1,在设计电路时就把PSB端焊好,节省I/O
#include"yscx.c"

/********************测忙碌**********************/
//测忙碌子程序
//RS=0,RW=1,E=H,D0-D7=状态字
/************************************************/
void LCD12864_PM(void)
{
unsigned char temp1;//状态信息(判断是否忙)
LCD12864_RS=0;    // 记得在包含该头文件前,定义引脚
LCD12864_RW=1;    // 记得在包含该头文件前,定义引脚
LCD12864_E=1;    //记得在包含该头文件前,定义引脚
do
   {temp1 = LCD12864_SJ;//记得在包含该头文件前,定义引脚
    LCD12864_SJ=0xFF;
    }
while(temp1&0x80);
LCD12864_E=0;      //记得在包含该头文件前,定义引脚
YS_us(1);        //

}
/********************写命令**********************/
//写命令子程序
//
/************************************************/
void LCD12864_XZL(unsigned char ml)/*写命令*/
{
LCD12864_PM();
LCD12864_RS=0; //记得在包含该头文件前,定义引脚
LCD12864_RW=0; //记得在包含该头文件前,定义引脚
LCD12864_E=1;  //记得在包含该头文件前,定义引脚
LCD12864_SJ=ml;//记得在包含该头文件前,定义引脚
YS_us(0);//稍作延时给LCD反应的时间
LCD12864_E=0;  //记得在包含该头文件前,定义引脚
if(ml==0x01|ml==0x02) YS_ms(3);//清屏和地址归位大概需3ms时间处理
YS_us(50);//其他指令大概需50us
}
/********************写数据**********************/
//写数据子程序
//
/************************************************/
void LCD12864_XSJ(unsigned char sj)
{
LCD12864_PM();
LCD12864_RS=1; //记得在包含该头文件前,定义引脚
LCD12864_RW=0; //记得在包含该头文件前,定义引脚
LCD12864_E=1;  //记得在包含该头文件前,定义引脚
LCD12864_SJ=sj;//记得在包含该头文件前,定义引脚
YS_us(0);//稍作延时给LCD反应的时间
LCD12864_E=0;  //记得在包含该头文件前,定义引脚
}

/********************初始化**********************/
//复位、通讯方式选择
/************************************************/
void LCD12864_CSH(void)
{
  //通讯方式为并口PSB=1,在设计电路时就把PSB端焊好,节省I/O
//LCD12864_XZL(0x34); //34H--扩充指令操作
LCD12864_XZL(0x30);  //功能设置,一次送8位数据,基本指令集
LCD12864_XZL(0x0C);  //0000,1100 整体显示,游标off,游标位置off
LCD12864_XZL(0x01);  //0000,0001 清DDRAM
LCD12864_XZL(0x02);  //0000,0010 DDRAM地址归位
LCD12864_XZL(0x80);  //1000,0000 设定DDRAM 7位地址000,0000到地址计数器AC
LCD12864_XZL(0x06);
}


#endif


LCD12864基础驱动函数串行

#ifndef __LCD12864_JCK_CX_C__
#define __LCD12864_JCK_CX_C__
/************************************************
**                                             **
**            六哥LCD12864基础函数库            **
**                  串行                        **
**************************************************/

//使用请注意定义引脚
//通讯方式为串行通信PSB=0,在设计电路时就把PSB端焊好,节省I/O
#include"yscx.c"
/*******************串行通信*********************
分别发送三个字节,11111AB0,DDDD0000,SSSS000,
  A:即表示并行的RW,1为读,0为写
  B:即表示并行的RS,1为数据,0为指令
  D:即表示并行的高四位数据
  S:即表示并行的低四位数据
注:串行要把PSB端为低电平
*************************************************/
void LCD12864_CXTX(unsigned char fs,sj)
{
unsigned char i;
LCD12864_E=0;//时钟SCLK
LCD12864_RS=1;///CS片选

do       ////LCD判忙=============
   {
    for(i=0;i<8;i++)
       {
        YS_us(1);//MCU与LCD速率匹配
        if(i<6) LCD12864_RW=1;//读LCD数据,前6位为1;后两位为0
          else  LCD12864_RW=0;//命令格式11111100B,0xfc
        YS_us(1);//MCU与LCD速率匹配
        LCD12864_E=1;//时钟SCLK
        YS_us(1);//MCU与LCD速率匹配
        LCD12864_E=0;//时钟SCLK
        }

    YS_us(5);//给LCD反应的时间
    LCD12864_E=1;//时钟SCLK
    YS_us(1); //给LCD反应的时间     
    }
while(LCD12864_RW);//判忙只需要取最高位,而不管后面7位

LCD12864_E=0;//时钟SCLK
LCD12864_RS=0;///CS片选
YS_us(1);//给LCD反应的时间
LCD12864_RS=1;///CS片选

for(i=0;i<24;i++)//、、、、送3字节
    {
     LCD12864_RW=fs&0x80;//数据SID
     fs<<=1;
     YS_us(1);    //MCU与LCD速率匹配
     LCD12864_E=1;       //时钟SCLK
     YS_us(1);    //MCU与LCD速率匹配
     if(i==7) fs=sj&0xf0; //取数据高四位
     if(i==15) fs=sj<<4;  //取数据低四位
     LCD12864_E=0;       //时钟SCLK
     YS_us(1);    //MCU与LCD速率匹配
     }
LCD12864_RS=0;///CS片选
LCD12864_E=1;//恢复高电平不影响其他用途
LCD12864_RW=1;//恢复高电平不影响其他用途
}
/********************写命令**********************/
void LCD12864_XZL(unsigned char ml)/*写命令*/
{
LCD12864_CXTX(0xf8,ml);//命令格式11111000B,0xf8
if(ml==0x01|ml==0x02) YS_ms(4);//清屏和地址归位大概需4ms时间处理
YS_us(50);//其他指令大概需50us     
}
/********************写数据**********************/
void LCD12864_XSJ(unsigned char sj)
{
LCD12864_CXTX(0xfa,sj);//命令格式11111010B,0xfa
}
/********************初始化**********************/
//复位、通讯方式选择
/************************************************/
void LCD12864_CSH(void)
{
//LCD12864_XZL(0x34);//34H--扩充指令操作
LCD12864_XZL(0x30);  //功能设置,一次送8位数据,基本指令集
LCD12864_XZL(0x0C);  //0000,1100 整体显示,游标off,游标位置off
LCD12864_XZL(0x01);  //0000,0001 清DDRAM
LCD12864_XZL(0x80);  //1000,0000 设定DDRAM 7位地址000,0000到地址计数器AC
LCD12864_XZL(0x06);
}


#endif



LCD12864显示函数
#ifndef __LCD12864_XSK_C__
#define __LCD12864_XSK_C__
/************************************************
*******                                 *********
*******       六哥LCD12864显示函数库     *********
*******                                 *********
************************************************/

//使用请注意定义引脚


#include"LCD12864_JCK_cx.C"//包含基础库

//为保证显示数制时的运行效率,制作了0—9,A—F的ascll码表
unsigned char  code ascll12864[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46};



/*****************************************************
**********LCD12864设置显示地址函数*********************
******************************************************/
unsigned char LCD12864_SZDZ(unsigned char x,y)//
{
switch(y)
    {case 0:x|=0x80;break;
     case 1:x|=0x90;break;
     case 2:x|=0x88;break;
     case 3:x|=0x98;break;
     default:;
     }
return(x);
}


/*****************************************************
**********LCD12864数制显示函数************************
******************************************************
sj:需要显示的数据,取值范围:十进制:-2147483648-2147483647,十六进制:0H-7FFFFFFFH
xsfs:显示方式,进制和小数点的判断依据,
x:显示列,取值范围0-7
y:显示行,取值范围0-3
*/
void LCD12864_SZXS(signed long sj,unsigned char xsfs,x,y)
{
unsigned long xc;     //显示缓存
unsigned char d[13];
bit xsd,fs,bf=0;
xsd=0;
fs=0;

LCD12864_XZL(0x04);//设置光标左移
LCD12864_XZL(LCD12864_SZDZ(x,y));//写入显示地址

y=0;

if(xsfs>10)  
      {x=16;         //输出十六进制
       d[y]=0x48;    //十六进制显示H
       y++;
       }         //
   else
      {if(sj<0)       //十进制正负数判断
          {sj=~sj+1;
           fs=1;}     //负号显示使能      
       if(xsfs!=0) xsd=1;//小数点显示使能
       x=10;
       }                //
xc=sj;

if(xc!=0)       //显示数据不为0;则显示
    {while(xsd)                     //判是否需要显示小数
        {if(xc!=0)                  //是否还需要计算
            {sj=xc%x;
             if(bf|sj!=0)           //小数部分为0不需要显示
                {d[y]=ascll12864[xc%x];
                 y++;               //取数的ascll码并显示
                 bf=1;              //小数部分不为0标志,小数部分数字有效
                 }
             xc/=x;                  //取剩下的数
             }
           else if(bf)
                   {d[y]=0x30;       //判是否需要补0
                    y++;}
             else;                   //小数部分无效,不需要补0

         xsfs--;
         if(xsfs==0)                    //小数点位数减一
            {xsd=0;                     //小数计算部分结束标志
             if(bf)
                {d[y]=0x2e;  //小数部分存在有效数字则显示小数点
                 y++;}
             }
         }
     }

do
   {d[y]=ascll12864[xc%x];     //取数的ascll码
    y++;   
    xc/=x;
    }         
while(xc!=0);

if(fs)
    {d[y]=0x2d;  //取负号ascll码
     y++;}   

if(y&&0x01)       //如果显示的位数为奇数
    {d[y]=0x20;    //显示一个空格
     y++;}

x=y;
y=1;
///////////////显示数据//////////////
do            
   {
    LCD12864_XSJ(d[y]);//显示一个地址的前一个字符
    y--;   
    LCD12864_XSJ(d[y]);//显示一个地址的后一个字符
    y+=3;              //跳到下一个要显示的两个字符
    }
while(y<x);        //判断是否显示完毕

LCD12864_XZL(0x06);//设置光标右移  

}


/*****************************************************
**********LCD12864字符显示函数************************
******************************************************
*zfc:需要显示的字符串指针,字符数不得超过64个
x:显示列,取值范围0-7
y:显示行,取值范围0-3
*/
void LCD12864_ZFXS(unsigned char *zfc,x,y)
{
unsigned char k1,k2,k3;
k3=x*2;

k1=16-k3;
k2=32-k3;
k3=48-k3;

switch(y)       //设置显示地址x和换行标志y
    {case 0:x|=0x80;y=0;break;
     case 1:x|=0x90;y=16;break;
     case 2:x|=0x88;y=32;break;
     case 3:x|=0x98;y=48;break;
     default:;}

LCD12864_XZL(x);//写显示地址


while(*zfc)
    {
     if(y==k1) LCD12864_XZL(0X90);//换行判断
      else if(y==k2) LCD12864_XZL(0X88);//换行判断
       else if(y==k3) LCD12864_XZL(0X98);//换行判断
        else;         
     LCD12864_XSJ(*zfc);//写显示数据
     y++;
/////////////判中文字符/////////
     if(*zfc>0x7f) zfc++;
       else
          {zfc++;           
           if(*zfc>0x7f && y&0x01)
              {LCD12864_XSJ(0x20);
               y++;}
            }
     }         
}


#endif

延时函数
#ifndef __yscx_C__
#define __yscx_C__
#include<intrins.h>
/*晶振频率33Mhz的stc15系列1T单片机适用*/
/**************************************************
          x*us延时函数
    精度极高,几乎可以忽略延时误差
***************************************************/
void YS_us(unsigned char t)
{
for( ;t>0;t--)
    {   
     _nop_();//16*nop
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();//16*nop
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();//16*nop
     }
_nop_();//12*nop
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();//12*nop
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();//12*nop
}

/*---------------------------------------------------
          x*1ms延时函数
----------------------------------------------------*/
void YS_ms(unsigned char t)  
{
for( ;t>0;t--)
    {   
     YS_us(250);
     YS_us(250);
     YS_us(250);
     YS_us(249);
     }
}
#endif

   




分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏5 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:373976 发表于 2018-7-20 09:06 | 只看该作者
这例程写的不错,很有功底。很有技巧性。
回复

使用道具 举报

板凳
ID:375751 发表于 2018-7-20 12:50 | 只看该作者
这例程写的不错
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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