⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cs23-2.c

📁 《手把手教你学单片机的C程序设计》及实验程序
💻 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 + -