📄 lcd显示c程序全解(hd61202).txt
字号:
LCD显示C程序全解
在本程序中,实现了显示英文字符,汉字以及打点画线的功能,并有翻滚效果。程序中给出了常用的英文字符的字模,只要在程序中给出所要实现的字符,程序就会自动把字符转换成对应的字模并写入液晶显示模块。但是由于HD61202显示存储器的特点,显示汉字时不能将单片机内的汉字库提出直接使用,需要将其转90度,再写入。这里使用了汉字字模提取软件PICKHZB.EXE,将汉字从单片机内的汉字库提取,并旋转90度后生成专用的用户字库。
#include <reg51.h>
#include <math.h>
#include <INTRINS.H>
#define uchar unsigned char
/***************************液晶显示器接口引脚定义*****************************/
sbit Elcm=P2^7; //使通信号
sbit CSALCM=P2^2; //CSA控制信号
sbit CSBLCM=P2^3; //CSB控制信号
sbit Dilcm=P2^0; //D/I信号
sbit Rwlcm=P2^1; //R/W信号
sbit DataIcm=0x80; //数据口
/*************************常用操作命令和参数定义********************************/
#define DISPON 0X3F //显示开
#define DISPOFF 0x3e //显示关
#define DISPIRST 0xc0; //显示起始行定义
#define SETX 0x40; //X定位设定指令(页)
#define SETY 0xb8;//((40代表起始列 b8代表起始页))
#define Lcdbusy 0x80; //LCM是否忙
/**************************显示分区边界位置**************************************/
#define MODL 0x00; //left(00,01,10,11)
#define MODM 0x40; //左区和中区分界
#define MODR 0x80; //中区和右区分界
#define LCMLIMIT 0xc0; //显示区的右边区
/******************************全局变量定义*************************************/
uchar col, row,cbyte; //列、行(页)、输出数据
bit xy; //画线的方向标志,1为水平
/*******************************************************************************/
void Lcminit(void);
void Delay(uchar);
void lcdbusyL(void);
void lcdbusyM(void);
void lcdbusyR(void);
void Putedut(uchar); //半角字符输出
void Putcdot(uchar); //全角字符输出
void Wrdata(uchar); //数据输出给LCM
void Lcmcls(void); //LCM全屏幕清0
void wtcom(void); //公用BUSY等待
void Locatexy(void); //光标定位
void WrcmdL(uchar); //左区命令输出
void WrcmdM(uchar); //中
void WrcmdR(uchar); //右区命令输出
void Putstr(uchar *puts, uchar i); //中英文字符串输出
void Rollscreen(uchar x); //屏幕向上滚动
void Rddata(void); //从液晶片上读数据
void Linehv(uchar length); //横竖方向画线
void point(void); //打点
void Linexy(uchar endx, uchar endy);
/*********************************数组列表************************************/
uchar code Ezk[]; //ASCII常规字符点阵码表
uchar code Hzk[]; //自定义汉字点阵码表
uchar code STR1[]; //自定义字符串
uchar code STR2[];
uchar code STR3[];
uchar code STR4[];
//*********************************主程序**************************************/
void main(void)
{
uchar x;
col=0;
row=0;
Delay(40); //延时大约40ms
Lcminit(); //液晶模块初始化,包括全屏清屏
Putstr(STR1,12);
col=0;
row=2;
Putstr(STR2,14);
col=0;
row=4;
Putstr(STR3,11);
col=0;
row=6;
Putstr(STR4,12);
x=0;
col=0;
row=0;
xy=1; //方向标志
Linehv(192); //画一条横线(0,0)--(191,0)
col=0;
row=15;
xy=1;
Linehv(192);
col=0;
row=32;
xy=1;
Linehv(192);
col=0;
row=1;
xy=0;
Linehv(31);
col=191;
row=1;
xy=0;
Linehv(31);
col=0;
row=63;
Linexy(44,31);
col=44;
row=31;
Linexy(192,62);
while (1)
{
Rollscreen(); //定位新的显示起始行
x++;
Delay(100);
}
}
/**********************画线,任意方向,不支持垂直或水平线**********************/
void Linexy(uchar endx, uchar endy)
{
register uchar t;
int 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;
if (delta_x==0)
incx=0;
else
incx=-1;
if (delta_y>0) incy=1;
if (delta_y==0)
incy=0;
else
incy=-1;
//区别哪个距离比较大
//cabs()功 能: 计算复数的绝对值 用 法: double cabs(struct complex z)
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<=distace+1; t++)
{
point();
xerr+=delta_x;
yerr+=delta_y;
if (xerr>distace)
{
xerr -= distance;
col += incx;
}
if (yerr > distance)
{
yerr -= distance;
row += incy;
}
}
}
/*****************************画直线或垂线********************************/
void Linehv(uchar length)
{
uchar xs, ys;
if (xy)
{
ys = col;
for (xs=0; xs < length; xs++)
{
col = ys + xs;
point();
}
}
else
{
xs = row;
for (ys=0; ys < length; ys++)
{
row = ys + xs;
point();
}
}
}
/**********************************画点**************************************/
void point(void)
{
uchar x1, y1, x, y;
x1 = col;
y1 = row;
row = y1>>3; //取Y方向分页地址 ??
Rddata();
y = y1 & 0x07; //字节内位置计算
x = 0x01;
Wrdata(cbyte | x); //画上屏幕
col = x1;
row = y1;
}
/*********************************屏幕滚动定位*******************************/
void Rollscreen(uchar x)
{
cbyte = DISPFIRST | x; //定义显示起始行为 x??
WrcmdL(cbyte);
WrcmdM(cbyte);
WrcmdR(cbyte);
}
/**********************************一个字串的输出****************************/
void Putstr(uchar *puts, uchar i)
{
uchar j, X;
for (j=0; j<i; j++)
{
X = puts[j];
if (X & 0x80)
Putcdot(X & 0x7f); //只保留低7位
else
Putcdot(X - 0x20); //ASCII码表从0x20开始
}
}
/**********************************半角字符点阵码数据输出**********************/
void Putedot(uchar Order)
{
uchar i, bakerx, bakery;
int x;
bakerx = col;
bakery = row;
x = Order * 0x10;
//上半个字符输出,8列
for (i = 0; i < 8; i++)
{
cbyte = Ezk[x];
Wrdata(cbyte);
x++;
col++;
if (col == LCMLIMIT)
{
col = 0;
row++;
row++;
} //下一列,如果列越界换行
if (row > 7) row = 0;
}
col = bakerx;
row = bakery + 1;
//下半个字符输出,8列
for (i = 0; i < 8; i++)
{
cbyte = Ezk[x];
Wrdata(cbyte);
x++;
col++;
if (col == LCMLIMIT)
{
col = 0;
row++;
row++;
} //下一列,如果列越界换行
if (row > 7) row = 0;
}
row = bakery;
} //整个字符输出结束
/***************************全角字符点阵数据输出***********************************/
void Putcdot(uchar Order)
{
uchar i, bakerx, bakery;
int x;
bakerx = col;
bakery = row;
x = Order * 0x20; //字义每个字符32b
//上半个字符输出,16列
for (i = 0; i < 16; i++)
{
Wrdata(cbyte);
x++;
col++;
if (col == LCMLIMIT)
{
col = 0;
row++;
row++;
} //下一列,如果列越界换行
if (row > 6) row = 0;
}
col = bakerx;
row = bakery + 1;
//下半个字符输出,8列
for (i = 0; i < 16; i++)
{
cbyte = Ezk[x];
Wrdata(cbyte);
x++;
col++;
if (col == LCMLIMIT)
{
col = 0;
row++;
row++;
} //下一列,如果列越界换行
if (row > 7) row = 0;
}
row = bakery;
}
/******************************从液晶片上读数据保留在全局变量中*********************************/
void Rddata(void)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -