LCD 1602显示字符,编写程序的时候,为何要弄一个忙信号判断函数?这个有什么作用? 字符型1602LCD自定义字符地址设置后,字符显示时,地址需...

作者&投稿:池星 (若有异议请与网页底部的电邮联系)
你好:
LCD 1602的响应速度相对于单片机的速度来说是偏慢的。
举个简单的例子,把一桶油通过漏斗向一个瓶子里倒,倒油的速度,即流量必须维持在一定范围之内,倒得太快油会从漏斗顶部溢出来,这样就浪费掉了。我们通过眼睛可以判断并使油面保持在顶面以下,以漏斗的额定流量来倒油,这样效率最高。
而对于单片机来说,1602好比那个瓶子漏斗,写入1602中要显示的数据好比油,如果以单片机的高运行速度向1602写数据就很可能造成上面所说的溢出,比如连续写入abc,结果只显示出了a,这是因为1602的显示芯片每次都要花时间来处理输入的ascii码数据,并把它显示出来。而我们却不容易主动地去控制写入数据的速度,所以1602使用忙信号就有必要了,每次单片机只有检测到忙信号为0,即不忙时,才向1602发数据。比如要显示abc,则这样操作,写a---判忙---写b---判忙---写c---判忙。这样就不会出错了。
这几年推出的lcd,像手机的屏响应速度就比较快,而1602这个古董我用示波器测过,大约40us左右的忙处理时间,而很多速度快的单片机的指令周期都是ns级的。也就是说单片机相当一段时间都在‘等’LCD。

#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
void busy(void)
{ uchar temp=0x80; //初始化temp最高位为1,使得能够进入下面
//的while循环
P0=0xff;(P0就是8个数据口)
rs=0; //设置命令操作
rw=1; //设置读操作
en=1; //使能
delay(100);(这是设的延时函数,不用解释)
while(temp & 0x80) //判忙,一旦表达式为假,即temp最高位为0,
//则表示1602不忙,跳出while.
{temp=P0;delay(20);} //把p0的的高位读入temp,延时
en=0; //关闭使能信号
}

每次读写操作都要调用这个busy函数

这个程序是用来判断液晶是否忙碌的,可以一直留着以后用,大同小异

LCD1602用C语言编程如何显示字符?~

void delay(uint z);//延时,1微妙时间有点短

你看看下面我做的程序,在2051+12M晶振通过你可以套用这个程序,不行的话就改长延时
/******************AT89S51使用12M晶振*******************/
//LCD脚接法,根据实际接法定义
#define LCM_D4_RS P3_2//第4脚数据/命令
#define LCM_D5_RW P3_5//第5脚读/写
#define LCM_D6_E P3_7//第6脚使能
#define LCM_D16_BLK P3_0//背光负极
#define LCM_D7_Data P1//第7-14脚数据
//LCD脚接法,根据实际接法定义

#define Busy 0x80 //用于检测LCM状态字中的Busy标识
#define _LCD_BIT_IS 4 //CPU与LCD1602间使用DB7-DB4这4根数据线进行传输

#include //头文件
#include //strlen()函数头文件

void LCMInit(void); //LCM初始化化
void WriteDataLCM(unsigned char WDLCM);//写数据
void WriteCommandLCM(unsigned char WCLCM,int BuysC); //写指令
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData); //按指定位置显示一个字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);//按指定位置显示一串字符
void Delay5Ms(void); //5ms延时
unsigned char ReadStatusLCM(void); //读状态

unsigned char code Greetings_Line1[] = {"Welcome Control"};
unsigned char code Greetings_Line2[] = {" ChuLong Make "};
data unsigned char cou = 0; // 定义软计数器,放在程序最前面的寄存器定义部分

void main(void)
{
LCMInit(); //LCM初始化
LCM_D16_BLK= 0;//开背光灯

TMOD = 0x11; // 定时/计数器0,1工作于方式1 16位定时
TH0 = 0x3c; // 预置产生50ms时基信号
TL0 = 0xb0;
EA = 1; // 开总中断
ET0 = 1; // 定时/计数器0允许中断
TR0 = 1; // 开定时/计数器0

DisplayListChar(0, 0, Greetings_Line1);
DisplayListChar(0, 1, Greetings_Line2);

//while(1);
}
//

void LCMInit(void) //LCM初始化
{
WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,0);

#if(_LCD_BIT_IS == 8) //CPU与LCD1602间使用DB0-DB8这8根数据线进行传输
WriteCommandLCM(0x38,1); //显示8位模式设置,开始要求每次检测忙信号
#else //CPU与LCD1602间使用DB0-DB4这4根数据线进行传输
WriteCommandLCM(0x28,1); //显示4位模式设置,开始要求每次检测忙信号
#endif

WriteCommandLCM(0x08,1); //关闭显示
WriteCommandLCM(0x01,1); //显示清屏
WriteCommandLCM(0x06,1); // 显示光标移动设置
WriteCommandLCM(0x0C,1); // 显示开及光标设置
}

//写数据
void WriteDataLCM(unsigned char WDLCM)
{
ReadStatusLCM(); //检测忙

LCM_D4_RS = 1;
LCM_D5_RW = 0;
#if(_LCD_BIT_IS == 8) //CPU与LCD1602间使用DB0-DB8这8根数据线进行传输
{
LCM_D7_Data = WDLCM;
}
#else //CPU与LCD1602间使用DB0-DB4这4根数据线进行传输
{
LCM_D7_Data &= 0x0f; //清高四位
LCM_D7_Data |= WDLCM & 0xf0; //写高四位
LCM_D6_E = 0;
LCM_D6_E = 1;

WDLCM = WDLCM << 4; //低四位移到高四位
LCM_D7_Data &= 0x0f; //清高四位
LCM_D7_Data |= WDLCM & 0xf0; //写低四位
}
#endif

LCM_D6_E = 0;
LCM_D6_E = 1;
}

//写指令
void WriteCommandLCM(unsigned char WCLCM,int BuysC) //BuysC为0时忽略忙检测
{
if(BuysC)
ReadStatusLCM(); //根据需要检测忙

LCM_D4_RS = 0;
LCM_D5_RW = 0;

#if(_LCD_BIT_IS == 8) //CPU与LCD1602间使用DB7-DB4这4根数据线进行传输
{
LCM_D7_Data = WCLCM;
}
#else
{
LCM_D7_Data &= 0x0f; //清高四位
LCM_D7_Data |= WCLCM & 0xf0; //写高四位
LCM_D6_E = 0;
LCM_D6_E = 1;

WCLCM = WCLCM << 4; //低四位移到高四位
LCM_D7_Data &= 0x0f; //清高四位
LCM_D7_Data |= WCLCM & 0xf0; //写低四位
}
#endif

LCM_D6_E = 0;
LCM_D6_E = 1;
}

//读状态
unsigned char ReadStatusLCM(void)
{
LCM_D7_Data = 0xff;
LCM_D4_RS = 0;
LCM_D5_RW = 1;
LCM_D6_E = 1;
while (LCM_D7_Data & Busy); //检测忙信号
return(LCM_D7_Data);
}

//按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
X |= 0x80; //算出指令码
WriteCommandLCM(X, 0); //这里不检测忙信号,发送地址码
WriteDataLCM(DData);
}

//按指定位置显示一串字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
int ListLength;

Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
for(ListLength = 0;ListLength < strlen(DData);ListLength++) //若到达字串尾则退出
{
if (X <= 0xF) //X坐标应小于0xF
{
DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
X++;
}
}
}

//5ms延时
void Delay5Ms(void)
{
unsigned int TempCyc = 5552;
while(TempCyc--);
}

//10s延时
void tiem0(void) interrupt 1
{ // T/C0中断服务程序(产生50ms时基信号)
if(cou < 60)
{ // 计数值到1000(1s) (****时间为倒计时****)
cou = 0; // 软计数器清零


}
cou++; // 软计数器加1
TH0 = 0x3c; // 重置定时常数
TL0 = 0xb0;
}

代码贴出,供大家参考
需要设定开始地址和移动方式,而后写入数据地址自动加1,给你一段驱动程序,看你会用么

首先是库文件,自己建立一个LCD1602.h文件,用记事本或编译器打开,将代码粘贴进去,该文件放在项目文件夹下
#ifndef__LCD1602_H__#define __LCD1602_H__#include#include"timer.h"/*以下为函数开关*///#define LCD1602_CKECKBUSY//#define LCD1602_CLEANSCREEN#define LCD1602_DISPLAYSTR#define LCD1602_DSIPLAYINT/****************/#define lcd_port P0 //LCD1602总线接口sbit lcdrs = P2^3;//寄存器选择,高电平1选择数据寄存器、低电平0选择指令寄存器。sbit lcden = P2^5;//使能端,写操作时,下降沿使能,读操作时,E高电平有效sbit lcdrw = P2^4;//读写选通,高电平读,低电平写。//注意改驱动不支持从LCD读取数据void LCD1602_initialise();//初始化函数,开机后,显示内容之前,请初始化#ifdef LCD1602_CLEANSCREENvoid LCD1602_cleanScreen(bit rewind);//清屏函数(rewind为0),或使光标归位(rewind为1时)#endif#ifdef LCD1602_DISPLAYSTR//显示字符(串)void LCD1602_displayStr(unsigned char row,unsigned char position,unsigned char *dat);#endif#ifdef LCD1602_DSIPLAYINT //显示整型数据(-32767~32767)void LCD1602_displayInt(unsigned char row,unsigned char position,int dat);//一次写入整型数(-32767~32767),position为开始位置#endifvoid LCD1602_setCmd(unsigned char command);//设定子函数 写指令或设定地址void LCD1602_writeData(unsigned char dat);//向LCD1602写入数据,记得先用写指令函数设定地址#ifdef LCD1602_CKECKBUSY bit LCD1602_checkBusy();//判忙函数,忙返回值为1#endif/*****************************************************************//* row显示位置行选择,0为第一行,1为第二行 *//* position显示位置的其实位置,为该行所在位置,值:0~15 *//* dat为显示内容 *//*****************************************************************/#endif以下是驱动源代码,自己建立一个LCD1602.c文件,用记事本或编译器打开,复制粘贴进去:
该文件放在项目文件夹下
#include"LCD1602.h"void delay(unsigned int ms)//延时大约1ms{unsigned int i;for(;ms>0;ms--)for(i=0;i4;us-=4);}void LCD1602_setCmd(unsigned char command) //设定子函数 写指令{ lcdrs=0; //当lcdrs=0 时,允许写入指令 lcd_port=command; delayMicroseconds(5); lcden=1; delayMicroseconds(5); lcden=0; }void LCD1602_writeData(unsigned char dat) //写数据{ lcdrs=1; //当lcdrs=1 时,允许写入显示 lcd_port=dat; delay(1);lcden=1; //lcden高脉冲将P0口数据读走 delayMicroseconds(5); lcden=0; } #ifdef LCD1602_CLEANSCREENvoid LCD1602_cleanScreen(bit rewind)//清屏或光标归位函数{if(rewind)LCD1602_setCmd(0x02);//光标归位指令elseLCD1602_setCmd(0x01);//清屏指令delay(5);}#endif#ifdef LCD1602_CKECKBUSYbit LCD1602_checkBusy(void)//判忙函数{lcd_port=0xFF;lcdrs=0;lcdrw=1;lcden=0;delayMicroseconds(1);lcden=1;return !(bit)(lcd_port&0x80);}#endifvoid LCD1602_initialise() //初始化函数{lcden=0;lcdrw=0;LCD1602_setCmd(0x38); //指令码:设置16X2显示,5X7点阵,8位数据接口 LCD1602_setCmd(0x0C); //指令码:开显示,不显示光标 LCD1602_setCmd(0x06); //指令码:指针加一,整屏不移动 LCD1602_setCmd(0x01); //显示清屏 delay(10);//稍停顿下,让LCD正确配置好}//*/#ifdef LCD1602_DISPLAYSTRvoid LCD1602_displayStr(unsigned char row,unsigned char position,unsigned char *dat)//一次写入字符串(超出不显示),position为开始位置{LCD1602_setCmd(0x80+0x40*row+position);while(*dat){LCD1602_writeData(*dat++);}}#endif#ifdef LCD1602_DSIPLAYINTvoid LCD1602_displayInt(unsigned char row,unsigned char position,int dat)//一次写入整型数(-32767~32767),position为开始位置{unsigned char str[7];unsigned char i=0;bit flag=0;if(dat==0){str[i++]=0x30;}else {if(dat<0){str[i++]=0x2D;dat=-dat;}if(dat/10000 ||flag){str[i++]=dat/10000+0x30; flag=1;}if(dat/1000%10||flag){str[i++]=dat/1000%10+0x30;flag=1;}if(dat/100%10 ||flag){str[i++]=dat/100%10+0x30; flag=1;}if(dat/10%10 ||flag){str[i++]=dat/10%10+0x30; flag=1;}if(dat%10 ||flag){str[i++]=dat%10+0x30; }}str[i]=0;flag=0;i=0;LCD1602_setCmd(0x80+0x40*row+position);while(str[i]){LCD1602_writeData(str[i++]);}}#endif1、需要修改引脚设置,就到LCD1602.h中修改
2、主函数头写上#include“LCD1602.h”,将“LCD1602.c”添加到项目中
3、使用的时候先调用LCD1602_initialise();对1602初始化;其中光标移动方式已经设定好了
4、根据需要开关函数开关(注释掉定义就是关闭相应函数,取消注释则是打开),调用相关函数。关于函数功能,库文件注释得很详细,请自行查看;


提供一段main()函数代码,供参考:
#include#include"LCD1602.h"void main(void){ LCD1602_initialise(); LCD1602_displayStr(0,0,"Hello World!"); LCD1602_displayInt(1,0,2015); while(1);}手打不易,望采纳!