📄 lcd.c
字号:
/*-------------------------------------------------------------------------*
*文件描述:本文件包含了液晶显示相关子程序,分别为: *
*(1)Lcdinit:液晶初始化子程序 *
*(2)LcdShCh:在液晶显示屏上显示字符数据 *
*(3)LcdShGrRe:在Lcd的指定行上显示或取消矩型边框 *
*(4)LcdShGrCil:在Lcd上显示或取消空心圆型 *
*-------------------------------------------------------------------------*/
//包含头文件
#include "LCD.h" //Lcd头文件
//定义延时子程序
#define delay1600us DelayTimes(4000) //延时>1.6ms
#define delay72us DelayTimes(30) //延时>72us
#define delay40ms DelayTimes(10000) //延时>40ms
//内部调用函数声明
//在Lcd指定位置上设置线型16个点的显示
void LcdShGr16P(INT8U,INT8U,INT16S);
//在Lcd指定位置上画1个点
void LcdShGr1P(INT8U,INT8U);
void DelayTimes(INT16U); //延时指定时间
void Wtite_Command(INT8U); //将控制命令写入Lcd
void Wtite_Data(INT8U); //将数据写入Lcd
void LcdShGrClr(void); //在Lcd上清图形显示屏
/*===========================[Lcd初始化操作]==============================*/
//Lcdinit:初始化液晶-------------------------------------------------------*
//功 能:初始化液晶,设置显示方式,清屏、C自动+1 *
//参 数:无 *
//返 回:无 *
//-------------------------------------------------------------------------*
void LCDInit(void)
{
/*控制口高四位设置为输出*/
// LCD_CtrlPort|=1<<LCD_BL;//BL=1,关掉背光
LCD_CtrlPortDDR|=(1<<LCD_RS);//RS的方向为输出
LCD_CtrlPortDDR|=(1<<LCD_RW);//RW的方向为输出
LCD_CtrlPortDDR|=(1<<LCD_E); // E的方向为输出
LCD_CtrlPortDDR|=(1<<LCD_BL);//BL的方向为输出
//数据口设置为输出
LCD_DataPortDDR=0xff;
//[Lcd初始化]
delay40ms; //延时>40ms
Wtite_Command(0b00110000); //8位数据,基本指令
Wtite_Command(0b00001100); //开显示
Wtite_Command(0b00000001); //清屏
delay1600us; //延时>1.6ms
Wtite_Command(0b00000110); //进入模式设定
LcdShGrClr(); //清Lcd图形显示屏
// LCD_CtrlPort&=~(1<<LCD_BL);//BL=0,打开背光
}
/*=======================[Lcd显示字符操作]================================*/
/*LcdShCh:在液晶显示屏上显示字符数据---------------------------------------*
*功 能:在液晶显示屏上显示以LcdSBuff为首地址的64个数据 *
*参 数:待显示的64个数据的首地址 *
*返 回:无 *
*-------------------------------------------------------------------------*/
void LcdShCh(INT8U *LcdSBuff)
{
unsigned char i; //data数组计数器(0-63)
//[Lcd显示64个数据]
Wtite_Command(0x80); //DDRAM地址设置
for(i=0;i<64;i++) //显示data中的64个数据
{
//[Lcd按行显示16个数据]
if((i<=15)||(i>=48)) //第一行和第四行不变
Wtite_Data(LcdSBuff[i]);
else if(i<=31) //显示的第二行为缓冲的第三行
Wtite_Data(LcdSBuff[i+16]);
else //显示的第三行为缓冲的第二行
Wtite_Data(LcdSBuff[i-16]);
}
}
/*===[Lcd画图操作:包括画圆,画矩形框,图形清屏,画点等]===================*/
/*LcdShGrCil:在Lcd上显示或取消空心圆型-------------------------------------*
*功 能:在Lcd上的指定位置显示或取消空心圆型 *
*参 数:Cx为圆心横坐标,Cy为圆心纵坐标 *
* CR为圆的半径,GrE确定图形是否有效 *
* GrCilMV为显示圆型时的正误差值 *
* 例如:半径为10,误差为4;半径为30,误差为30 *
*返 回:无 *
*-------------------------------------------------------------------------*/
void LcdShGrCil(INT8U Cy,INT8U Cx,INT8U CR,INT8U GrCilMV,INT8U GrE)
{
INT8U x,y; //坐标的循环控制变量
INT32S mistake; //显示时的误差值
Wtite_Command(0b00110110); //扩展指令,绘图开
for(y=Cy-CR;y<=Cy+CR;y++)
for(x=Cx-CR;x<=Cx+CR;x++)
{
mistake=(x-Cx)*(x-Cx)+(y-Cy)*(y-Cy)-CR*CR;
//误差在范围之内时,显示该点
if((mistake<=GrCilMV)&&(mistake>=-GrCilMV))
{
if(GrE==1) LcdShGr1P(y,x);//显示该点
//清除该点
else if(y<=31) LcdShGr16P(y,(x/16),0);
else LcdShGr16P(y-32,x/16+8,0);
}
}
//LcdShGr1P(Cy,Cx);//显示圆心
Wtite_Command(0b00110000);//基本指令
}
/*LcdShGrRe:在Lcd的指定行上显示或取消矩型边框------------------------------*
*功 能:在Lcd上指定行上显示或取消矩型边框 *
*参 数:ln为指定的行数(0-3), GrE确定图形是否有效 *
*返 回:无 *
*-------------------------------------------------------------------------*/
void LcdShGrRe(INT8U ln,INT8U GrE)
{
INT8U Px,y; //行页号坐标,列坐标
INT8U i; //循环变量
INT16S LC,RC,TBC; //左,右和上下边框色
//[确定ln所在行的起始坐标(左上角)]
if((ln==0)||(ln==2)) y=0;
else y=16;
if(ln<=1) Px=0;
else Px=8;
//[确定有无边框(有GrE决定)]
if(GrE==1) //有表框
{TBC=65535;LC=32768;RC=1;}
else //无边框
{TBC=0;LC=0;RC=0;}
Wtite_Command(0b00110110);//扩展指令,绘图开
//[在Lcd上指定行上显示矩型边框]
for(i=0;i<=7;i++,Px++)
{
LcdShGr16P(y,Px,TBC); //显示上边框
LcdShGr16P(y+15,Px,TBC); //显示下边框
}
for(i=1,y++,Px--;i<=14;i++,y++)
{
LcdShGr16P(y,Px,RC); //显示右边框
LcdShGr16P(y,Px-7,LC); //显示左边框
}
Wtite_Command(0b00110000);//基本指令
}
/*LcdShGrClr:在Lcd上清图形显示屏-------------------------------------------*
*功 能:在Lcd上清图形显示屏(清GDRAM) *
*参 数:无 *
*返 回:无 *
*-------------------------------------------------------------------------*/
void LcdShGrClr(void)
{
INT8U Px,y; //行页号,列坐标的循环变量
Wtite_Command(0b00110110);//扩展指令,绘图开
//[清图形显示屏(清GDRAM)]
for(y=0;y<=31;y++)
for(Px=0;Px<=15;Px++)
LcdShGr16P(y,Px,0); //写入0为清屏
Wtite_Command(0b00110000);//基本指令
}
/*LcdShGr1P:在Lcd的指定位置上画一个点--------------------------------------*
*功 能:在Lcd的指定位置上画一个点 *
*参 数:y为纵坐标(0-63),x为横坐标(0-127) *
*返 回:无 *
*-------------------------------------------------------------------------*/
void LcdShGr1P(INT8U y,INT8U x)
{
INT16U value=32768; //初始值为0b1000000000000000
if(y>=32) //第三四行必须调整x和y坐标
{y=y-32;x=x+16*8;}
value>>=(x-x/16*16); //写入的16位数据
LcdShGr16P(y,x/16,value);//显示相应的点
}
/*LcdShGr16P:在Lcd指定位置上设置线型16个点的显示---------------------------*
*功 能:在Lcd指定位置上设置线型16个点的显示 *
*参 数:y为纵坐标(0-63),Px为页号(0-15),value为16位数据 *
*返 回:无 *
*-------------------------------------------------------------------------*/
void LcdShGr16P(INT8U y,INT8U Px,INT16S value)
{
//Wtite_Command(0b00110110); //8位数据,扩展指令,绘图开
Wtite_Command(y|0b10000000);//设置6位绘图列地址
Wtite_Command(Px|0b10000000);//设置4位绘图行地址
Wtite_Data((INT8U)(value>>8));//写入高8个字节
Wtite_Data((INT8U)value); //写入低8个字节
//Wtite_Command(0b00110000); //8位数据,基本指令
}
/*===============[Lcd基本操作:包括写指令,写数据和延时]===================*/
/*Wtite_Command:执行参数中的给定命令---------------------------------------*
*功 能:执行参数中的给定命令 *
*参 数:command为待执行的命令码 *
*返 回:无 *
*-------------------------------------------------------------------------*/
void Wtite_Command(INT8U command)
{
LCD_CtrlPort&=~(1<<LCD_RS); //RS=0
LCD_CtrlPort&=~(1<<LCD_RW); //RW=0
LCD_DataPort=command; //数据上线
LCD_CtrlPort|=(1<<LCD_E); //E=1
asm("nop"); //使数据稳定
asm("nop");
LCD_CtrlPort&=~(1<<LCD_E); //E=0,使数据有效
delay72us; //延时>72us
}
/*Wtite_Data:将参数中给定的数据写入液晶控制器------------------------------*
*功 能:将参数中给定的数据写入液晶控制器 *
*参 数:data为待写入的数据 *
*返 回:无 *
*-------------------------------------------------------------------------*/
void Wtite_Data(INT8U data)
{
LCD_CtrlPort|=(1<<LCD_RS); //RS=1
LCD_CtrlPort&=~(1<<LCD_RW); //RW=0
LCD_DataPort=data; //数据上线
LCD_CtrlPort|=(1<<LCD_E); //E=1
asm("nop"); //使数据稳定
asm("nop");
LCD_CtrlPort&=~(1<<LCD_E); //E=0,使数据有效
delay72us; //延时>72us
}
/*DelayTimes:延时指定时间--------------------------------------------------*
*功 能:延时指定的时间 *
*入 口:tn为延时时间数(0到65535) *
*出 口:无 *
*-------------------------------------------------------------------------*/
void DelayTimes(INT16U tn)
{
INT16U i; //循环变量
for(i=0;i<tn;i++);
}
//其他特殊功能函数
//LcdShBigNum:在Lcd上显示自定义32*16点阵的数字(0--999)---------------------*
//功 能:在Lcd上显示自定义32*16点阵的数字(0--999) *
//参 数:X表示Lcd上显示字符的横坐标(0--5),Y为显示字符的纵坐标(0--1) *
// BigNumCodeAdrr为32*16点阵数字编码首地址,Num为当前的数据值(0--999) *
//返 回:无 *
//内部调用:LcdShGr16P:在Lcd指定位置上设置线型16个点的显示 *
// Wtite_Command:执行参数中的给定命令 *
//-------------------------------------------------------------------------*
void LcdShBigNum(INT8U Y,INT8U X,INT16U * BigNumCodeAdrr,INT16U Num)
{
INT8U GBit,SBit,BBit; //存放个位,十位,百位数据
INT8U Yi; //Y坐标方向的循环控制变量
if(Y>1||X>5||Num>999) goto LcdShBigNum_End; //参数值范围检测
GBit=Num%10; BBit=Num/100; SBit=(Num%100)/10;
Wtite_Command(0b00110110); //扩展指令,绘图开
if(Y==1) X+=8; //参数调整
for(Yi=0;Yi<32;Yi++)
{
if(BBit!=0) LcdShGr16P(Yi,X,*(BigNumCodeAdrr+BBit*32+Yi));
else LcdShGr16P(Yi,X,0x0000);
if((SBit!=0) ||(BBit!=0)) LcdShGr16P(Yi,X+1,*(BigNumCodeAdrr+SBit*32+Yi));
else LcdShGr16P(Yi,X,0x0000);
LcdShGr16P(Yi,X+2,*(BigNumCodeAdrr+GBit*32+Yi));
}
Wtite_Command(0b00110000); //基本指令
LcdShBigNum_End:;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -