📄 cs23-2.c
字号:
#include <REG51.H>
#include<math.h>
#define uchar unsigned char
#define uint unsigned int
sbit CS1=P2^4;
sbit CS2=P2^3;
sbit RS=P2^7;
sbit RW=P2^6;
sbit EN=P2^5;
sbit RST=P2^2;
#define DataPort P0
/**********常用操作命令和参数定义***********/
#define DISPON 0x3f //显示屏开
#define DISPOFF 0x3e //显示屏关
#define DISPFIRST 0xc0 //起始行显示定义
#define SETX 0x40 //X定位(页)
#define SETY 0xb8 //Y定位(列)
#define Lcdbusy 0x80 //LCM忙判断定义
/***********************************************/
#define MODL 0x00 //左区
#define MODM 0x40 //左区与中区分界
//#define MODR 0x80 //中区与右区分界
#define LCMLIMIT 0x80 //中区的边界
//#define LCMLIMIT 0xc0 //右区的边界(这里不用)
/*************************************************/
uchar col,row,cbyte; //列、行、数据的变量定义
bit xy; //画线标志,"1"水平线,"0"垂直线。
/**************************************************/
void Lcminit(void); //液晶模块初始化子函数
void Delay(unsigned long MS); //延时子函数
void lcdbusyL(void); //左区判忙子函数
void lcdbusyM(void); //中区判忙子函数
//void lcdbusyR(void); //右区判忙子函数(这里不用)
void Wrdata(uchar X); //写数据至LCM
void Lcmcls(void); //LCM清屏
void Lcmclsxx(void); //LCM全屏置黑
void wtcom(void); //公用判忙等待子函数
void Locatexy(void); //光标定义
void WrcmdL(uchar X); //写命令至左区
void WrcmdM(uchar X); //写命令至中区
//void WrcmdR(uchar X); //写命令至右区(这里不用)
void Rddata(void); //读LCM状态子函数
void Linehv(uchar length); //水平、垂直画线子函数
void point(void); //画点子函数
void Linexy(uchar endx, uchar endy); //画斜线子函数
/************************复位子函数*************************/
void reset() //复位子函数
{ //复位子函数开始
RST=0; //复位端置0
Delay(20); //延时20ms
RST=1; //复位端置1
Delay(20); //延时20ms
} //复位子函数结束
/*********************主函数**********************/
void main(void)
{ //主函数开始
col=0; //定位0列、0页
row=0;
Delay(10); //延时一会
Lcminit(); //液晶模块初始化
Delay(1000); //延时一会
/***********以下使用画直线与斜线的方法,画出一条小舢舨*********/
/****************先画出船上建筑**************/
col=0; //定位x方位0、y方位32
row=32;
xy=1; //水平线
Linehv(127); //画线,长度127
/*----------------------------------------------*/
col=33; //定位x方位33、y方位48
row=48;
xy=1; //水平线
Linehv(30); //画线,长度30
col=36; //定位x方位36、y方位32
row=32;
xy=0; //垂直线
Linehv(16); //画线,长度16
col=64; //定位x方位64、y方位48
row=48;
xy=1; //水平线
Linehv(30); //画线,长度30
col=91; //定位x方位91、y方位32
row=32;
xy=0; //垂直线
Linehv(16); //画线,长度16
/*------------------------------------------------*/
col=10; //定位x方位10、y方位32
row=32;
xy=0; //垂直线
Linehv(27); //画线,长度27
/************以下画出船底的弧形***********/
col=0; //定位x方位0、y方位32
row=32;
Linexy(10,16); //画斜线,终点为x方位10、y方位16
col=10; //定位x方位10、y方位16
row=16;
Linexy(30,8); //画斜线,终点为x方位30、y方位8
col=30; //定位x方位30、y方位8
row=8;
Linexy(64,5); //画斜线,终点为x方位64、y方位5
/*-----------------------------------------------------------------*/
col=65; //定位x方位65、y方位5
row=5;
Linexy(97,8); //画斜线,终点为x方位97、y方位8
col=97; //定位x方位97、y方位8
row=8;
Linexy(117,16); //画斜线,终点为x方位117、y方位16
col=117; //定位x方位117、y方位16
row=16;
Linexy(127,32); //画斜线,终点为x方位127、y方位32
/*----------------------------------画舢舨结束------------------------------------*/
while(1); //死循环
} //主函数结束
/*************************画斜线子函数************************/
void Linexy(uchar endx, uchar endy)
{
register uchar t;
char xerr=0,yerr=0,delta_x,delta_y,distance;
uchar incx,incy;
delta_x=endx-col;
delta_y=endy-row;
if(delta_x>0)incx=1;
else if(delta_x==0)incx=0;
else incx=-1;
if(delta_y>0)incy=1;
else if(delta_y==0)incy=0;
else incy=-1;
delta_x=cabs(delta_x);
delta_y=cabs(delta_y);
if(delta_x>delta_y) distance=delta_x;
else distance=delta_y;
/*-----------开始画线-------------*/
for(t=0;t<=distance+1;t++){
point();
xerr+=delta_x;
yerr+=delta_y;
if(xerr>distance){
xerr-=distance;
col+=incx;
}
if(yerr>distance){
yerr-=distance;
row+=incy;
}
}
}
/*********************画水平、垂直线子函数***********************/
void Linehv(uchar length) /*函数名为Linehv的画水平、垂直线子函数,定义
length 为线段长度的无符号字符型变量。*/
{ //画水平、垂直线子函数开始
uchar xs,ys; //定义xs、ys 为无符号字符型变量。
if(xy){ys=col; //若xy为1,则为水平划线
for(xs=0;xs<length;xs++){
col=ys+xs;
point();}
}
else {xs=row; //否则为垂直划线
for(ys=0;ys<length;ys++)
{
row=xs+ys;
point();}
}
} //画水平、垂直线子函数结束
/**********************画点子函数***************************/
void point(void) //画点子函数
{ //画点子函数开始
uchar x1,y1,x,y; //定义x1、y1、x、y 为无符号字符型变量
x1=col; //x方向座标col赋予x1(暂存)
y1=row; //y方向座标row赋予y1(暂存)
row=y1>>3; //y1右移3位后赋予row,获得y方向的页地址
Rddata(); //读取列(x)地址、页(y)地址处的数据
y=y1&0x07; //计算出该页(1字节)内的y轴点位置地址
x=0x01;
x=x<<y; //移入所画点
Wrdata(cbyte|x); //画上屏幕
col=x1; //恢复x、y座标
row=y1;
} //画点子函数结束
/***************全屏幕清屏子函数**********************/
void Lcmcls(void) //函数名为Lcmcls的全屏幕清屏子函数
{ //函数开始
for(row=0;row<8;row++)
{for(col=0;col<LCMLIMIT;col++)
Wrdata(0);} //将数据0写到屏幕
} //函数结束
/**********************全屏幕置黑子函数**********************/
void Lcmclsxx(void) //函数名为Lcmclsxx的全屏幕置黑子函数
{ //函数开始
for(row=0;row<8;row++)
for(col=0;col<LCMLIMIT;col++)
Wrdata(255); //将8位数据全1(255)写到屏幕
} //函数结束
/*************读取液晶x列、y页座标处的数据至全局变量cbyte中************/
void Rddata(void) //函数名为Rddata的子函数
{ //函数开始
Locatexy(); //座标定位
DataPort=0xff; //LCM口置全1
RS=1; //选择数据寄存器
RW=1; //选择读
EN=1; //使能
cbyte=DataPort; //虚读一次
EN=0; //禁能
Locatexy(); //座标定位
DataPort=0xff; //LCM口置全1
RS=1; //选择数据寄存器
RW=1; //选择读
EN=1; //使能
cbyte=DataPort; //读取数据(真读)
EN=0; //禁能
} //函数结束
/**************将数据X写入液晶x列、y页座标处***********/
void Wrdata(uchar X) //函数名为Wrdata 的子函数,定义X为无符号字符型变量
{ //函数开始
Locatexy(); //座标定位
RS=1; //选择数据寄存器
RW=0; //选择写
DataPort=X; //将数据X写入LCM口
EN=1; //使能
EN=0; //禁能
} //函数结束
/******************写命令至左区********************/
void WrcmdL(uchar X) //函数名为WrcmdL 的子函数,定义X为无符号字符型变量
{ //函数开始
lcdbusyL(); //调用左区判忙子函数
RS=0; //选择指令寄存器
RW=0; //选择写
DataPort=X; //数据输出至数据口
EN=1;EN=0; //使能,禁能
} //函数结束
/********************写命令至中区************************/
void WrcmdM(uchar X) //函数名为WrcmdM的子函数,定义X为无符号字符型变量
{ //函数开始
lcdbusyM(); //调用中区判忙子函数
RS=0; //选择指令寄存器
RW=0; //选择写
DataPort=X; //数据输出至数据口
EN=1;EN=0; //使能,禁能
} //函数结束
/**************写命令至右区****************
void WrcmdR(uchar X) //函数名为WrcmdR的子函数,定义X为无符号字符型变量
{ //函数开始
lcdbusyR(); //调用右区判忙子函数
RS=0; //选择指令寄存器
RW=0; //选择写
DataPort=X; //数据输出至数据口
EN=1;EN=0; //使能,禁能
} //函数结束
***********************左区判忙子函数***********************/
void lcdbusyL(void) //函数名为lcdbusyL 的左区判忙子函数
{ //函数开始
CS1=1;CS2=0; //选中左区
wtcom(); //调用判忙等待子函数
} //函数结束
void lcdbusyM(void) //函数名为lcdbusyM的中区判忙子函数
{ //函数开始
CS1=0;CS2=1; //选中中区
wtcom(); //调用判忙等待子函数
} //函数结束
/*void lcdbusyR(void) //函数名为lcdbusyR的右区判忙子函数(这里不用)
{ //函数开始
CS1=?;CS2=?; //根据所用LCM器件决定取值
wtcom(); //调用判忙等待子函数
}*/ //函数结束
/***********公用判忙等待子函数********************/
void wtcom(void) //函数名为wtcom 的公用判忙等待子函数
{ //函数开始
RS=0; //选择指令寄存器
RW=1; //选择读
DataPort=0xff; //数据0xff输出至数据口
EN=1; //使能
while(DataPort&Lcdbusy);// 若LCM忙则等待
EN=0; //禁能
} //函数结束
/************根据设定的col、row座标数据,定位LCM下一个操作单元************/
void Locatexy(void) //函数名为Locatexy 的子函数
{ //函数开始
uchar x,y; //定义x,y为无符号字符型变量
switch(col&0xc0) //限定x列最大值为192
{
case 0:{lcdbusyL();break;} //判左区忙
case 0x40:{lcdbusyM();break;} //判中区忙
//case 0x80:{lcdbusyR();break;} //判右区忙(这里不用)
}
x=col&0x3f|SETX; //获得x列(0~63)地址
y=row&0x07|SETY; //获得y页(0~7)地址
wtcom(); //调用判忙等待子函数
RS=0; //选择指令寄存器
RW=0; //选择写
DataPort=y; //y页地址传送至LCM口
EN=1;EN=0; //使能,禁能
wtcom(); //调用判忙等待子函数
RS=0; //选择指令寄存器
RW=0; //选择写
DataPort=x; //x列地址传送至LCM口
EN=1;EN=0; //使能,禁能
} //函数结束
/*******************液晶屏初始化******************************/
void Lcminit(void) //函数名为Lcminit的液晶屏初始化子函数
{ //函数开始
reset(); //调用复位子函数
cbyte=DISPFIRST; //定义起始行为0行
WrcmdL(cbyte); //写命令至左区
WrcmdM(cbyte); //写命令至中区
//WrcmdR(cbyte); //写命令至右区(这里不用)
cbyte=DISPOFF; //关闭显示屏
WrcmdL(cbyte); //写命令至左区
WrcmdM(cbyte); //写命令至中区
//WrcmdR(cbyte); //写命令至右区(这里不用)
cbyte=DISPON; //打开显示屏
WrcmdL(cbyte); //写命令至左区
WrcmdM(cbyte); //写命令至中区
//WrcmdR(cbyte); //写命令至右区(这里不用)
Lcmcls(); //清屏
Delay(10000); //延时一会
Lcmclsxx(); //全屏置黑
Delay(10000); //延时一会
Lcmcls(); //清屏
Delay(30000); //延时一会
col=0; //定位x方向为0列
row=0; //定位y方向为0页
Locatexy(); //定位0列、0页为LCM下一个操作单元
} //函数结束
/*********************延时子函数**********************/
void Delay(unsigned long MS)
{
while(MS!=0)MS--;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -