要实现对16x2点阵字符液晶模块的高效控制,必须按照模块设计方式,建立起相关的子程序,下面先详细介绍驱动16x2点阵字符液晶模块的各功能子程序。
1.写命令到LCM子函数
vOid LCDWriteCommand(uchar CMD,uchar Attribc)
/*函数名为WriteCommandLCM的写指令到LCM子函数。
定义CMD、Attribc 为无符号字符型变量。*/
{
if(Attribc)WaitForEnable();
/*若Arrribc为“真”,则调用WaitForEnable子函数进行忙检测*/
LCM_RS_0;LCM_RW_0;_NOP0;
/*选中指令寄存器,写模式*/
DataPort=CMD;_NOP();
/*将变量WCLCM中的指令传送至数据口
LCM_EN_1;_NOP0;_NOP();LCM_EN_O:
/*LCM_EN端产生脉冲下降沿。*/
}
/*WriteCommandLCM 子函数结束。*/
2,写数据到LCM子函数
void LcdWritEDAta(dchar dataW)
/*函数名为WriteDataLCM的写数据到LCM子函数。定义
dataW 为无符号字符型变量。*/
{
/*WriteDataLCM子函数开始。*/
WaitForEnable(); */
LCM_RS_1;LCM_RW_0;_NOP0;
/*选中数据寄存器,写模式。*/
DataPort=dataW;_NOP();
/*将变量dataQW中数据传送至数据口。*/
LCM_EN_1;_NOP();_NOP0;LCM_EN_O:
/*LCM_EN端产生脉冲下降沿。WriteDataLCM子函数
结束*/
3.检测LCD忙信号子函数
void WaitForEnable(void)
/*函数名为WaitForEnable的检测忙信号子程序子函数。
/*WaitForEnable子函数开始。*/
uchar val;
/*定义局部变量val。*/
DataPOrt=Oxff;
/*置数据口为全1。*/
LCM_RS_0;LCM_RW_1;_NOP();
/*选中指令寄存器,读模式。*/
LCM_EN_1;_NOP();_NOP();
/*置LCM_EN端为高电平,读使能。*/
DDRA=0x00;
/*数据口置为输入*/
val=PINA:
/*读取数据*/
while(val&Busy)val=PINA:
/*检测忙信号。当数据口内容与0x80相与后不为零时,
程序原地踏步继续读取数据并检测忙信号。*/
LCM_EN_O:
/*置LCM_EN端为低电平。*/
DDRA=0xff;
/*数据口置为输出*/
}
/*WaitForEnable子函数结束。*/
4.显示光标定位子函数
void LOCateXY(char posx.char posy)
/*显示光标定位子函数,函数名为LocareXY,定义posx,
posxxy为字符型变量。*/
{
/*LocateXY子函数开始。*/
uchar temp;
/*定义temp为无符号字符型变量。*/
temp&=0x7f;
/*temp的变化范围0-15。*/
temp=posx&0xof;
/*屏蔽高4位。*/
posy&=0x01;
/*posy的变化范围0-1。*/
if(posy)tempㄧ=0x40;
/*若posy为1(显示第二行),地址码+0x40*/
tempㄧ=0x80;
/*指令码为地址码+0x80。*/
WriteCommandLCM(temp,0);
/*将指令temp写入LCM,忽略忙信号检测。*/
}
/*LocateXY子函数结束。*/
5.显示指定座标的一个字符(x=0~15,y=0~1)子函数
void DisplayOneChar(uchar x,uchar y,uchar Wdata)
/*显示指定座标的一个字符(x=0-15.y=0-1)子函数,函
数名为DispOneChar,定义x、y、Wdata为无符号字符型变量。
*/
{
/*DispOneChar函数开始*/
LocateXY(x,y):
/*调用LocateXY函数定位显示地址。*/
WriteDataLCM(Wdata);
/*将数据Wdata写入LCM。*/
}
/*DispONeChar函数结束。*/
6.演示第二行移动字符串子函数
void Display(uchar dd)
/*演示第二行移动字符串子函数,函数名为Dispiay,定义
dd为无符号字符型变量。*/
{
/*Display子函数开始。*/
uchari:
/*定义;为无符号字符型变量。*/
for(i=O;i<16:i++){
/*进入for语句循环。*/
DisplayOneChar(i,1,dd++);
/*显示单个字符。*/
dd&=Ox7f;
/*dd的变化范围0-127。*/
if(dd<32)dd=32:
/*dd的最小值为32,这样dd的变化范围为32-127。*/
}
/*for语句结束。*/
}
/*Display函数结束。*/
7.显示指定座标的一串字符子函数
void ePutstr(uchar x.uchar v,uchar code *ptr)
/*显示指定座标的一串字符(x=0-15,y=0-1)子函数,函
数名为ePutstr,定义x、y为无符号字符型变量,ptr为指向
code区的无符号字符型指针变量。*/
{
/*ePutetr子函数开始。*/
uchar i,I=O;
/*定义i,i为无符号字符型变量。*/
while(ptr[I]>31)(I++;}
/*ptr[I]大于31时,为ASCII码,进入While语句循环,I累
加,计算出字符串长度。*/
for(i=0;i
/*进入for语句循环。*/
DisplayOneChar(x++,y,ptr[i]);
/*显示单个字符,同时x轴座标递增。*/
if(x==1 6){
/*若x等于16,进入if语句。*/
x=O;y^=1;
/*x赋0,y与1按位异或(取反)。*/
}
/*if语句结束。*/
}
/*for语句结束。*/
}
/*ePutstr子函数结束。*/
8.在AVR单片机综合试验板上实现16x2LCM演示程序1
第一行显示“-This is a LCD-!”,第二行的第1个字符位置
显示“A”。过2秒后变为第一行的第8个字符位置显示“B”,第
二行显示“-Design by ZXH-!”。然后无限循环。
在我的文档中新建一个ac18的文件夹。建立一个ac18.prj
的工程项目,最后建立源程序文件ac18 C。输入下面的程序:
#include
/*包含头文件*/
#include
/*------------------------------------------*/
#define uchar unsigned char
/*变量类型的宏定义*/
#define uint unsigned int
/*----------------引脚电平的宏定义----------------*/
#define LCM_RS_1 PORTBㄧ=BIT(PB0)
/*RS脚输出高电平的宏定义*/
#define LCM_RS_0 PORTB&=~BIT(PBO)
/*RS脚输出低电平的宏定义*/
#define LCM_RW_1 PORTBㄧ=BIT(PB1)
/*RW脚输出高电平的宏定义*/
#define LCM_RW_O PORTB&=~BIT(PB1)
/*RW脚输出低电平的宏定义*/
#define LCM_EN_1 PORTBㄧ=BlT(PB2)
/*EN脚输出高电平的宏定义*/
#define LCM_EN_0 PORTB&=~BIT(PB2)
/*EN脚输出低电平的宏定义*/
/*===============================*/
#define DataPort PORTA
/*数据端口宏定义*/
#define Busy 0x80
/*忙信号的宏定义*/
#define xtaI 8
/*===============================*/
const uchar str0[]={“-This is a LCD-!”}
/*待显字符*/
const uchar str1 []={"-Design by ZXH-!"};
/*待显示字符串*/
/*==============函数说明===================*/
void Delay_1 ms(void);
void Delay_nms(uint n):
void WaitFOrEnable(void):
void LcdWriteData(uchar W):
void LcdWriteCommand(uchar CMD,uchar Attribc);
void InitLcd(void);
void Display(uchar dd):
void DispIayoneChar(uchar×.uchar y,uchar Wdata);
void ePutstr(uchar x,uchar y,uchar const*ptr);
/**********************************************/
void main(void)
/*定义主函数*/
{
Delay_nms(400);
/*延时400mS等待电源稳定*/
DDRA=0xff;PORTA=0x00;
/*初始化I*O口*/
DDRB=0xff;PORTB=0x00;
InitLcd();
/*LCD初始化*/
/**************************************/
while(1)
/*无限循环*/
{
LcdWriteCommand(0x01.1):
/*清屏*/
LcdWriteCommand(0xoc,1):
/*开显示*/
DisplayOneChar(O,1,0x41):
/*第二行的第1个字符位置显示A*/
ePutstr(0.0.str0);
/*第一行显示-This is a LCD-!*/
Delay_nms(2000);
/*延时2S*/
LcdWriteCommand(0x01.1):
/*清屏*/
LcdWriteCommand(0xoc,1):
/*开显示*/
DisplayOneChar(8,0,0x42);
/*第一行的第8个字符位置显示B*/
ePutstr(0.1,str1):
/*第二行显示-Design by AXH-!*/
Delay_nms(2000);
/*延时2S*/
}
}
/*************显示指定座标的一串字符子函数***************/
void ePutstr(uchar x,uchar y,uchar const*ptr)
{
uchar i.I=0:
while(ptr[I]>31){I++;)
for(i=0;i
DisplayoneChar(x++,Y,pt r[i]);
if(X==16){
x=0;y^=1:
}
}
}
/***************
void LocateXY(char posx,char posy)
{
uchar temp;
temp&=0x7f;
temp=posx&0xof;
posy&=0x01;
if(posy)templ=0x40;
templ=0x80;
LcdWriteCommand(temp,0):
}
/**************显示指定座标的一个字符子函数************/
void DisplayOneChar(uchar X.uchar y,uchar Wdata)
{
LocateXY(x,y):
LcdWriteData(Wdata);
}
/**************LCD初始化子函数******************/
void lnitLcd(void)
{
LcdWriteCommand(0x38,O):
/*8位数据传送,2行显示,5*7字形,不检测忙信号*/
Delay_nms(5);
LcdWriteCommand(Ox38,O):
/*8位数据传送;2行显示,5*7字形,不检测忙信号*/
Delay_nms(5);
LcdWriteCommand(0x38.0):
/*8位数据传送,2行显示,5*7字形,不检测忙信号*/
Delay_nms(5);
LcdWriteCommand(0x38,1):
/*8位数据传送,2行显示,5/7字形、检测忙信号*/
LcdWriteCommand(0x08,1):
/*关闭显示,检测忙信号*/
LcdWriteCommand(0x01,1);
/*清屏,检测忙信号*/
LcdWriteCommand(0x06,1):
/*显示光标右移设置,检测忙信号*/
LcdWriteCommand(0xoc,1):
/*显示屏打开,光标不显示、不闪烁,检测忙信号*/
}
/****************写命令到LCM子函数*******************/
void LcdWfiteCommand(uchar CMD,uchar Attribc)
{
if(Attribc)WaitForEnable():
LCM_RS_0;LCM_RW_0;_NOP();
DataPort=CMD;_NOP();
LCM_EN_1;_NOP0;_NOP();LCM_EN_O;
}
/***************写数据到LCM子函数***************/
void LEDWriteData(uchar dataW)
{
WaitF0rEnable();
LCM_RS_1;LCM_RW_O;_NOP();
DataPort=dataW;_NOP();
LCM_EN_1:_NOP();_NOP();LCM_EN_0;
}
/************检测LCD忙忙信号子函数**************/
void WaitFOrEnable(vOid)
{
uchar val;
DataPort=0xff;
LCM_RS_0;LCM_RW_1;_NOP();
LCM_EN_1:_NOP0;_NOP();
DDRA=0x00;
vaI=PINA;
while(val&Busy)val=PINA;
LCM_EN_O;
DDRA=0xff;
}
/************************************************/
void Delay_1 ms(void)
/*1mS延时子函数*/
{ uint i;
for(i=1;i<(uint)(xtal*143-2):i++)
}
/*==========================*/
void Delay_nms(uint n)
/*n*1mS延时子函数*/
{
uint i=0:
while(i {Delay_1 ms(); i++: } } 编译通过后,将ac18.hex文件下载到AVR单片机综合试验板上进行实际演示。标示“LCD16*2”的单排座上正确插上16x2液晶模块(脚号对应,不能插反),在标示“DC5V”电源端输入5V稳压电压。我们看到液晶屏上的显示与我们设计的目标完全一致。 9.在AVR单片机综合试验板上实现16x2LCM演示程序--2一开始第一行及第二行显示预定的字符串(第一行显示“--ELECTRONICS--”,第二行显示“WORLDMAgazine”),随后第二行显示移动的ASCII字符。 在我的文档中新建一个acl9的文件夹。建立一个acl9.pri的工程项目,最后建立源程序文件ac19.C。输入下面的程序: #include #include /*---------------------------------*/ #define uchar unsigned char #define uint unsigned int #define LCM_RS_1 PORTBI=BlT(P80) #define LCM_RS_O PORTB&=~BIT(PB0) #define LCM_RW_1 PORTBI=BIT(PBl) #define LCM_RW_0 PORTB&=~BlT(PBl) #define LCM_EN_1 PORTBl=BlT(PB2) #define LCM_EN_O PORTB&=~BIT(PB2) #define DataPort PORTA #define Busy 0x80 #define xtal 8 /*-----------------------------*/ const uchar exampl[]=“--ELECTRONlCS--WORLD magazine\n”; void Delay_1 ms(void); void Delay_nms(uint n); void WaitFOrEnabIe(void): void LcdWmeData(uchar W): void LcdWriteCommand(uchar CMD,uchar Attribc); void InitLcd(void); void Display(uchar dd): void DlsplayoneChar(uchar×,uchar y,uchar Wdata); void ePutstr(uchar x,uchar y,uchar const*ptr); /******************************************/ void main(void) { uchar temp; Delay_nms(400); DD RA:0xff:PO RTA=0x00; DDRB=0xff:PORTB=0x00; InitLcd(); temp=32; ePutstr(0,0,exampl); Delay_nms(3200); while(1) { temp&=0x7f; if(temp<32)temp=32; Display(temp++); Delay_nms(400); } } /*********************************/
上一篇:基于单片机与CPLD的混合式步进电机PWM驱动技术
下一篇:采用ATmega8控制器的倾角测量系统设计
推荐阅读最新更新时间:2024-03-16 15:58