找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机LCD1602字符液晶滚动演示程序问题

[复制链接]
跳转到指定楼层
楼主

uchar code Prompt[]="Press K1 - K3 To Start Demo Prog";--------------这条语句有作用不

while((Busy_Check()&0x80)==0x80);------------一个变量与上一个十六进制数,啥东东


void ShowString(uchar,uchar,uchar *);----------------这个是定义一个指针变量?



//main.c
/*        名称:LCD1602字符液晶滚动演示程序
        说明:K1~K3按钮分别实现液晶垂直或水平滚动显示及暂停与继续控制。
*/
#include<reg51.h>
#include<string.h>
#define uchar unsigned char
#define uint unsigned int
void Initialize_LCD();
void DelayMS(uint ms);
void ShowString(uchar,uchar,uchar *);
sbit K1=P3^0;
sbit K2=P3^1;
sbit K3=P3^2;
uchar code Prompt[]="Press K1 - K3 To Start Demo Prog";
//待滚动显示的信息段落,每行不超过80个字符,共6行
uchar const Line_Count=6;        
uchar code Msg[][80]=
{
        "Many CAD users dismiss schematic capture as a necessary evil in the ",
        "process of creating PCB layout but we have always disputed this point ",
        "of view. With PCB layout now offering automation of both component ",
        "can often be the most time consuming element of the exercise.",
        "And if you use circuit simulation to develop your ideas, ",
        "you are going to spend even more time working on the schematic."
};
//显示缓冲(2行)
uchar Disp_Buffer[32];
//垂直滚动显示
void V_Scroll_Display()
{
        uchar i,j,k=0;
        uchar *p=Msg[0];
        uchar *q=Msg[Line_Count]+strlen(Msg[Line_Count]);
        //以下仅使用显示缓冲的前16字节空间
        while(p<q)
        {
                for(i=0;i<16&&p<q;i++)
                {        //消除显示缓冲中待显示行首尾可能出现的空格
                        if((i==0||i==15)&&*p==' ') p++;
                        if(*p!='\0')
                        {
                                Disp_Buffer[ i]=*p++;
                        }
                        else
                        {
                                if(++k>Line_Count) break;
                                p=Msg[k];                                        //p指向下一串的首地址
                                Disp_Buffer[ i]=*p++;
                        }
                }
                //不足16个字符时空格补充
                for(j=i;j<16;j++) Disp_Buffer[j]=' ';
                //垂直滚动显示
                while(F0) DelayMS(5);
                ShowString(0,0,"                 ");
                DelayMS(150);
                while(F0) DelayMS(5);
                ShowString(0,1,Disp_Buffer);
                DelayMS(150);
                while(F0) DelayMS(5);
                ShowString(0,0,Disp_Buffer);
                ShowString(0,1,"                 ");
                DelayMS(150);
        }
        //最后清屏
        ShowString(0,0,"                 ");
        ShowString(0,1,"                 ");
}
//水平滚动显示
void H_Scroll_Display()
{
        uchar i,j,k=0,L=0;
        uchar *p=Msg[0];
        uchar *q=Msg[Line_Count]+strlen(Msg[Line_Count]);
        //将32个字符的显示缓冲前16个字符设为空格
        for(i=0;i<16;i++) Disp_Buffer[ i]=' ';
        while(p<q)
        {
                //忽略缓冲中首尾可能出现的空格
                if((i==16||i==31)&&*p==' ') p++;
                for(i=16;i<32&&p<q;i++)
                {        
                        if(*p!='\0')
                        {
                                Disp_Buffer[ i]=*p++;
                        }
                        else
                        {
                                if(++k>Line_Count) break;
                                p=Msg[k];                                        //p指向下一串的首地址
                                Disp_Buffer[ i]=*p++;
                        }
                }
                //不足32个字符时空格补充
                for(j=i;j<32;j++) Disp_Buffer[j]=' ';
                //水平滚动显示
                for(i=0;i<=16;i++)
                {
                        while(F0) DelayMS(5);
                        ShowString(0,L,Disp_Buffer+i);
                        while(F0) DelayMS(5);
                        DelayMS(20);
                }
                L=(L==0)?1:0;                //行号在0,1间交替
                DelayMS(300);
        }
        //如果显示结束时停留在第0行,则清除第1行的内容
        if(L==1) ShowString(0,1,"                 ");        
}
//外部中断0,由K3控制暂停与继续显示
void EX_INT0() interrupt 0
{
        F0=!F0;                //暂停与继续显示控制标志位
}
//主程序
void main()
{
        uint Count=0;
        IE=0x81;                //允许外部中断0
        IT0=1;                        //下降沿触发
        F0=0;                        //暂停与继续显示控制标志位
        Initialize_LCD();
        ShowString(0,0,Prompt);
        ShowString(0,1,Prompt+16);
        while(1)
        {
                if(K1==0)
                {
                        V_Scroll_Display();
                        DelayMS(300);
                }
                else
                if(K2==0)
                {        
                        H_Scroll_Display();
                        DelayMS(300);        
                }
        }
}
//LCD1602.c
/*        名称:液晶控制与显示程序
        说明:本程序是通用的1602液晶控制程序。
*/
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit RS=P2^0;
sbit RW=P2^1;
sbit EN=P2^2;
//延时
void DelayMS(uint ms)
{
        uchar i;
        while(ms--) for(i=0;i<120;i++);
}
//忙检查
uchar Busy_Check()
{
        uchar LCD_Status;
        RS=0;                                //寄存器选择
        RW=1;                                //读状态寄存器
        EN=1;                                //开始读
        DelayMS(1);
        LCD_Status=P0;
        EN=0;
        return LCD_Status;
}
//写LCD命令
void Write_LCD_Command(uchar cmd)
{
        while((Busy_Check()&0x80)==0x80);        //忙等待
        RS=0;                //选择命令寄存器
        RW=0;                //写
        EN=0;        
        P0=cmd;EN=1;DelayMS(1);EN=0;
}
//发送数据
void Write_LCD_Data(uchar dat)
{
        while((Busy_Check()&0x80)==0x80);        //忙等待
        RS=1;RW=0;EN=0;P0=dat;EN=1;DelayMS(1);EN=0;
}
//LCD初始化
void Initialize_LCD()
{
        Write_LCD_Command(0x38);DelayMS(1);
        Write_LCD_Command(0x01);DelayMS(1);        //清屏
        Write_LCD_Command(0x06);DelayMS(1);        //字符进入模式:屏幕不动,字符后移
        Write_LCD_Command(0x0c);DelayMS(1);        //显示开,光标关
}
//显示字符串
void ShowString(uchar x,uchar y,uchar *str)
{
        uchar i=0;
        if(y==0) Write_LCD_Command(0x80|x);        //设置显示起始位置
        if(y==1) Write_LCD_Command(0xc0|x);
        for(i=0;i<16;i++)                                        //输出字符串
        {
                Write_LCD_Data(str[ i]);
        }
}



图片1.png (25.27 KB, 下载次数: 43)

图片1.png
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:804115 发表于 2020-7-28 19:38 | 只看该作者
本帖最后由 1692483014 于 2020-7-28 19:40 编辑

uchar code Prompt[]="Press K1 - K3 To Start Demo Prog";--------------这条语句有作用不
答:有用,main函数进入后调用了
ShowString(0,0,Prompt);
ShowString(0,1,Prompt+16);
用于将"Press K1 - K3 To Start Demo Prog"字符串显示到屏幕上。

while((Busy_Check()&0x80)==0x80);------------一个变量与上一个十六进制数,啥东东

答:这个是检测Busy_Check()函数返回值的最高位BIT7是否为1,如果为1,那么就在这里死等,直到它为0再运行下面的代码,那BIT7什么时候会等于0呢?当LCD_Status不忙的时候就会为0了。
整个这一行是为了保证LCD处理完了上一条指令后才能进行后面的LCD指令的操作,要不可能出错。

void ShowString(uchar,uchar,uchar *);----------------这个是定义一个指针变量?
答:这是声明一个函数,声明函数要求必须列出参数的类型,但不一定非要列出变量。这个声明类似于.h文件的声明,只不过这是局部声明,只能在声明之后的函数里调用ShowString函数。
回复

使用道具 举报

板凳
ID:668004 发表于 2020-7-29 14:44 | 只看该作者
1692483014 发表于 2020-7-28 19:38
uchar code Prompt[]="Press K1 - K3 To Start Demo Prog";--------------这条语句有作用不
答:有用,mai ...

非常的帮  给你点赞  专业
回复

使用道具 举报

地板
ID:668004 发表于 2020-7-29 14:55 | 只看该作者
1692483014 发表于 2020-7-28 19:38
uchar code Prompt[]="Press K1 - K3 To Start Demo Prog";--------------这条语句有作用不
答:有用,mai ...

这里有个*号是啥意思
回复

使用道具 举报

5#
ID:668004 发表于 2020-7-29 14:57 | 只看该作者
1692483014 发表于 2020-7-28 19:38
uchar code Prompt[]="Press K1 - K3 To Start Demo Prog";--------------这条语句有作用不
答:有用,mai ...

与上1000 0000就是为了判断最高位是不是1 对吗?为什么是这一位进行判断就可以
回复

使用道具 举报

6#
ID:668004 发表于 2020-7-30 10:10 | 只看该作者
1692483014 发表于 2020-7-28 19:38
uchar code Prompt[]="Press K1 - K3 To Start Demo Prog";--------------这条语句有作用不
答:有用,mai ...

你是软硬件通吃的大牛。。。。原来
回复

使用道具 举报

7#
ID:804115 发表于 2020-8-1 02:44 | 只看该作者
QWE4562012 发表于 2020-7-29 14:55
这里有个*号是啥意思

void ShowString(uchar,uchar,uchar *);----------------这个是定义一个指针变量?

你说这个*吗?这不就是指针吗?
把C语言那本书再看几遍吧!
回复

使用道具 举报

8#
ID:804115 发表于 2020-8-1 02:46 | 只看该作者
QWE4562012 发表于 2020-7-29 14:57
与上1000 0000就是为了判断最高位是不是1 对吗?为什么是这一位进行判断就可以

与上1000 0000就是为了判断最高位是不是1 对吗?为什么是这一位进行判断就可以

是的,这一位对应P0口的P0.7引脚,这个脚为高电平,说明LCD在忙,你要等,等他变低,LCD就忙完了,所以要检测这个bit。
回复

使用道具 举报

9#
ID:804115 发表于 2020-8-1 02:51 | 只看该作者
QWE4562012 发表于 2020-7-30 10:10
你是软硬件通吃的大牛。。。。原来

我来这里回答问题,是为了学习的,但是我发现更多的是新手提问题,能提出难一点儿问题的不多,我很期待有难度而且我很感兴趣的问题,这样我就可以百度它,思考它,解决它,从而增长知识,顺便还能赚点儿金币,哈哈。
你要努力呀!希望再过几个月能提出更深一点儿的问题。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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