EDN首页   博客首页

日志档案

发表于 2006-11-13 21:04:47

6

标签: LCD  1602  显示  程序  

一个LCD1602的显示程序!!!

#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit LCM_RW="P1"^5; //定义引脚
sbit LCM_RS="P1"^4;
sbit LCM_E="P1"^6;
#define LCM_Data P0
#define Busy 0x80 //用于检测LCM状态字中的Busy标识

void WriteDataLCM(unsigned char WDLCM);
void WriteCommandLCM(unsigned char WCLCM,BuysC);
unsigned char ReadDataLCM(void);
unsigned char ReadStatusLCM(void);
void LCMInit(void);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
void Delay5Ms(void);
void Delay400Ms(void);

unsigned char code cdle_net[] = {"www.mkdz.cn"};
unsigned char code email[] =    {"wang1jin@163.com"};

void main(void)
{
Delay400Ms(); //启动等待,等LCM讲入工作状态
LCMInit(); //LCM初始化
Delay5Ms(); //延时片刻(可不要)

DisplayListChar(0, 0, cdle_net);
DisplayListChar(0, 1, email);
while(1);
}

//写数据
void WriteDataLCM(unsigned char WDLCM)
{
ReadStatusLCM(); //检测忙
LCM_Data = WDLCM;
LCM_RS = 1;
LCM_RW = 0;
LCM_E = 0; //若晶振速度太高可以在这后加小的延时
LCM_E = 0; //延时
LCM_E = 1;
}

//写指令
void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测
{
if (BuysC) ReadStatusLCM(); //根据需要检测忙
LCM_Data = WCLCM;
LCM_RS = 0;
LCM_RW = 0;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
}

//读数据
unsigned char ReadDataLCM(void)
{
LCM_RS = 1;
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
return(LCM_Data);
}

//读状态
unsigned char ReadStatusLCM(void)
{
LCM_Data = 0xFF;
LCM_RS="0";
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
while (LCM_Data & Busy); //检测忙信号
return(LCM_Data);
}

void LCMInit(void) //LCM初始化
{
LCM_Data = 0;
WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();

WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
WriteCommandLCM(0x08,1); //关闭显示
WriteCommandLCM(0x01,1); //显示清屏
WriteCommandLCM(0x06,1); // 显示光标移动设置
WriteCommandLCM(0x0C,1); // 显示开及光标设置
}

//按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
X |= 0x80; //算出指令码
WriteCommandLCM(X, 0); //这里不检测忙信号,发送地址码
WriteDataLCM(DData);
}

//按指定位置显示一串字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
unsigned char ListLength;

ListLength = 0;
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
while (DData[ListLength]>0x20) //若到达字串尾则退出
{
if (X <= 0xF) //X坐标应小于0xF
{
DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
ListLength++;
X++;
}
}
}

//5ms延时
void Delay5Ms(void)
{
unsigned int TempCyc = 5552;
while(TempCyc--);
}

//400ms延时
void Delay400Ms(void)
{
unsigned char TempCycA = 5;
unsigned int TempCycB;
while(TempCycA--)
{
TempCycB="7269";
while(TempCycB--);
};
}

 

系统分类: 单片机   |   用户分类: 单片机编程   |   来源: 无分类   |   【推荐给朋友】   |   【添加到收藏夹】

    阅读(2870)    回复(6)  

投一票您将和博主都有获奖机会!

最新评论

  • cocappjj

    2006-11-14 9:53:24

    俺是不懂了。。。

  • wang1jin

    2006-11-13 21:06:30

    今晚来分析下这个程序...学了这么久,竟然连这个都不会...惨...

  • wang1jin

    2006-11-15 0:26:52

    主程序
    ========================================
    在这里主程序,只做调用别的程序作用;

    主程序
    延时400毫秒
    进行LCD初始化子程序;
    再延时5MS.
    调用显示第一组数据;
    调用显示第二组数据;
    死循环;

    void main(void)
    {
    Delay400Ms(); //启动等待,等LCM讲入工作状态
    LCMInit(); //LCM初始化
    Delay5Ms(); //延时片刻(可不要)

    DisplayListChar(0, 0, cdle_net);
    DisplayListChar(0, 1, email);
    ReadDataLCM();//测试用句无意义
    while(1);
    }
    ========================================

    写数据
    void WriteDataLCM(unsigned char WDLCM)
    ========================================
    利用函数.把需要写入的数据送到P0口;

    写数据.
    调用写状态来判断LCD是否忙;
    用WDLCM来传递数据.
    把WDLCD的数据送到P0口..LCD的数据口..
    RS="1";
    RW="0";
    E=高脉冲.
    这样就能把数据送到LCD中.


    void WriteDataLCM(unsigned char WDLCM)
    {
    ReadStatusLCM(); //检测忙
    LCM_Data = WDLCM;
    LCM_RS = 1;
    LCM_RW = 0;
    LCM_E = 0; //若晶振速度太高可以在这后加小的延时
    LCM_E = 0; //延时
    LCM_E = 1;
    }

    写指令
    void WriteCommandLCM(unsigned char WCLCM,BuysC)
    ========================================
    定义二个变量.一个做数据传送,另一个做判断
    是否忙的标志位;如果不需要判断则把它清零;

    先判断LCD是否忙,如果忙则调用读状态子程序;
    一直等LCD不忙了再把数据送到P0;
    送数据到P0;
    RS="0";
    RW="0";
    E=高脉冲;


    读数据
    unsigned char ReadDataLCM(void)
    ========================================
    定义为有返回值的函数
    读数据不用判断是否忙.
    RS="1";
    RW="1";
    E=高脉冲;
    返回P0口当前状态;


    读状态
    unsigned char ReadStatusLCM(void)
    ========================================
    定义为有返回值的函数
    读状态要判断LCD是否忙;
    先把P0口置0XFF;
    RS="0";
    RW="1";
    E=高脉冲;
    检测P0的各口和LCD的标志位是否不为0;
    如果不为0则等待.为0;再返回P0的值;

    LCD初始化
    void LCMInit(void)
    ========================================
    这个函数不带任何返回值;
    只是执行初始化的任务;
    先把P0清0;
    写指令.(0X38.0);这里的38是设置显示模式;
    0为不检测忙信号...
    延时..5MS.
    Delay5Ms();
    WriteCommandLCM(0x38,0);
    Delay5Ms();
    WriteCommandLCM(0x38,0);
    Delay5Ms();

    再设置显示模式(38.1).写显示模式.38.
    检测忙;
    关闭显示(08.1)检测忙;
    显示清屏(01.1)检测忙;
    显示光标移动设置(06.1)检测忙;

    void LCMInit(void) //LCM初始化
    {
    LCM_Data = 0;
    WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
    Delay5Ms();
    WriteCommandLCM(0x38,0);
    Delay5Ms();
    WriteCommandLCM(0x38,0);
    Delay5Ms();

    WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
    WriteCommandLCM(0x08,1); //关闭显示
    WriteCommandLCM(0x01,1); //显示清屏
    WriteCommandLCM(0x06,1); // 显示光标移动设置
    WriteCommandLCM(0x0C,1); // 显示开及光标设置
    }


    在指定位置显示一个字符
    void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
    ========================================
    这里面定义了三个变量;
    X是16个显示地址...
    Y是二行...LCD1602能显示二行.
    DDATA是你要显示的数据;
    Y &= 0x1;Y与上0X01是不能让Y大于1;只能0和1;
    X &= 0XF;X与上0XF是不能让X大于15.因为LCD
    只能是0-15.共16个显示位.
    if (Y) 判断显示在哪行.如果在第二行就加上
    40;不在第二行跳过;
    X |= 0x80;
    由于LCD在写入显示地址的时候要求最高位D7
    为1..所以写入的时候要加上1000 0000.也就是
    80H;

    调用写指令程序WriteCommandLCM(X, 0)
    把显示地址X中的值送到写指令函数中.
    此时不必检测忙;

    写完指令把DDATA中的数据送到写数据函数中;
    显示字符.

    //按指定位置显示一个字符
    void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
    {
    Y &= 0x1;
    X &= 0xF; //限制X不能大于15,Y不能大于1
    if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
    X |= 0x80; //算出指令码
    WriteCommandLCM(X, 0); //这里不检测忙信号,发送地址码
    WriteDataLCM(DData);
    }


    在指定位置显示一串字符
    void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code
    *DData)
    ========================================
    定义显示坐标X和Y...X不能大于15.Y不能大于1;
    同时定义一个指针.DDATA;

    定义一个长度变量为0;
    Y不能大于1;只能为0或1;
    X不能大于15.只能为0-15;
    判断(DDATA在这里等于unsigned char code cdle_net[] = {"www.cdle.net"};
    unsigned char code email[] = {"pnzwzw@cdle.net"};)
    二个中的任何一个...
    如果DData[ListLength]>0x20...达到了字符
    尾就退出.
    X不能大于15...不能让数据显示到外面去了.
    调用显示一个字符程序...并把DDATA[LISTLENGTH]
    中数据送到显示一个字符子程序.
    LISTLENGTH加1;
    X坐标加1;因为在显示一个字符那里没有+.
    所以在这里面加.


    //按指定位置显示一串字符
    void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
    {
    unsigned char ListLength;

    ListLength = 0;
    Y &= 0x1;
    X &= 0xF; //限制X不能大于15,Y不能大于1
    while (DData[ListLength]>0x20) //若到达字串尾则退出
    {
    if (X <= 0xF) //X坐标应小于0xF
    {
    DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
    ListLength++;
    X++;
    }
    }
    }


    下面就是二个普通延时程序.
    //5ms延时
    void Delay5Ms(void)
    {
    unsigned int TempCyc = 5552;
    while(TempCyc--);
    }

    //400ms延时
    void Delay400Ms(void)
    {
    unsigned char TempCycA = 5;
    unsigned int TempCycB;
    while(TempCycA--)
    {
    TempCycB="7269";
    while(TempCycB--);
    };
    }

    这二个就不用解释了...

     

     

  • vfdff

    2007-5-5 0:03:22

    unsigned char code 类型的数据可以在程序中重新赋值吗??
    vfdff@hotmail.com 希望得到您的帮助

  • wang1jin

    2007-5-5 0:06:08

    是变量就可以重新赋值呀...

  • 战神

    2006-12-13 9:19:59

    http://blog.sina.com.cn/u/1252428584这是我的