判忙作用是向1602写入数据或命令是有一定的等待时间的
其实可以通过延时程序来解决,不需要判忙
这是我的1602程序,晶振为110592的,单片机AT89S52
delay(240)的延时时间约为240217+55 = 526us
void delay(uchar tt) // delay tt217us+55us
{
while(--tt);
}
void LCDSendCommand(uchar ch)
{
/ if(busy) cack(); /
L1602_RS=0;
L1602_RW=0;
P0=ch;
L1602_E=1;
delay(1);
L1602_E=0;
delay(240);
}
void LCDSendData(uchar ch)
{
/ cack();/
L1602_RS=1;
L1602_RW=0;
P0=ch;
L1602_E=1;
delay(1);
L1602_E=0;
delay(240);
}
这是我写的一个成功的,你仔细对比下就知道了!
#include<reg52h>
#include<intrinsh>
#define U8 unsigned char
#define U16 unsigned int
#define BOOL bit
U8 secondh,secondl,minuteh,minutel,hourh,hourl,second,minute,hour;
U8 monthl,monthh,month,day,datel,dateh,date,year,yearl,yearh;
/定义LCD功能管脚/
sbit LCDRS = P2^6 ; //控制LCD数据或命令的读写
sbit LCDRW = P2^5 ; //控制LCD读写信号
sbit LCDEN = P2^7 ; //使能LCD
//
/定义DS1302功能管脚/
sbit DSRST = P3^5 ; //DS1302复位管脚
sbit DSIO = P3^4 ; //控制DS1302数据传输
sbit DSCLK = P3^6 ; //DS1302时钟
//
/延时函数/
void delay(U16 time)
{
U16 time1,time2;
for(time1=time;time1>0;time1--)
for(time2=110;time2>0;time2--);
}
//
/检测LCD忙碌状态/
BOOL judge_lcd()
{
BOOL flag;
LCDEN = 0;
LCDRS = 0;
LCDRW = 1;
LCDEN = 1;
delay(1);
flag=(BOOL)(P0&0x80); //状态位第7位为1时禁止读写,为0时可读写
LCDEN = 0;
return flag;
}
//
/实现LCD写指令/
void write_lcd_command(U16 command)
{
while(judge_lcd()); //检测LCD是否为忙碌状态
P0 = command ;
LCDRS = 0 ;
LCDRW = 0 ;
LCDEN = 1 ;
delay(1);
LCDEN = 0 ;
}
//
/实现LCD写数据/
void write_lcd_date(U16 date)
{
while(judge_lcd()); //检测LCD是否为忙碌状态
P0 = date ;
LCDRS = 1 ;
LCDRW = 0 ;
LCDEN = 1 ;
delay(1);
LCDEN = 0 ;
}
//
/实现LCD写指令及数据/
void write_lcd_com_date(U16 addr,U16 date)
{
write_lcd_command(addr);
delay(1);
write_lcd_date(date);
}
//
/初始化LCD/
void init_lcd()
{
write_lcd_command(0x38); //设置16x2显示,5x7点阵,8位数据口
delay(1);
write_lcd_command(0x0c); //开显示,不显示光标,光标不闪烁
delay(1);
write_lcd_command(0x06); //读写一个字符后,地址自动加1,不移动屏幕
delay(1);
write_lcd_command(0x01); //清屏
delay(1);
}
//
/读DS1302/
U8 read_ds1302(U8 addr)
{
U8 i,temp=0x00;
DSRST=0;
DSIO=1;
DSCLK=0;
DSRST=1;
for (i=0;i<8;i++) //循环8次 写入地址数据
{
DSCLK=0;
DSIO=addr&0x01; //每次传输低字节
addr>>=1; //右移一位
DSCLK=1;
}
delay(1);
if(DSIO)
temp|=0x80; //每次传输低字节
DSCLK=0;
temp>>=1;
for (i=0;i<7;i++) //循环8次 读取数据
{
DSCLK=0;
if(DSIO)
temp|=0x80; //每次传输低字节
DSCLK=1;
temp>>=1; //右移一位
}
DSCLK=1;
DSRST=0;
DSIO=0;
return temp; //返回
}
//
/写DS1302/
void write_ds1302(U8 addr, U8 date)
{
U8 i;
DSRST=0;
DSCLK=0;
DSRST=1;
for (i=0;i<8;i++) //循环8次 写入地址数据
{
DSCLK=0;
_nop_();
DSIO=addr&0x01; //每次传输低字节
addr>>=1; //右移一位
DSCLK=1;
_nop_();
}
for (i=0;i<8;i++) //循环8次 写入数据
{
DSCLK=0;
_nop_();
DSIO=date&0x01; //每次传输低字节
date>>=1; //右移一位 DSCLK=1
DSCLK=1;
_nop_();
}
DSRST=0;
delay(1);
}
//
/初始化DS1302/
void init_ds1302()
{
//读秒
if((((second=read_ds1302(0x81))>>7)&&0x01)==1)
{
write_ds1302(0x8e,0x00); //关闭写保护
write_ds1302(0x80,0x00); //00秒
write_ds1302(0x82,0x54); //54分
write_ds1302(0x84,0x17); //17点
write_ds1302(0x86,0x14); //14日
write_ds1302(0x88,0x10); //10月
write_ds1302(0x8a,0x05); //星期五
write_ds1302(0x8c,0x11); //2011年
write_ds1302(0x8e,0x80); //允许写保护
}
}
//
/主函数/
void main()
{
init_lcd();
delay(2);
write_lcd_com_date(0x81,'2');
write_lcd_com_date(0x82,'0');
delay(1);
init_ds1302();
delay(1);
while(1)
{
second=read_ds1302(0x81);
secondl=second&0x0f;
secondh=second>>4;
minute=read_ds1302(0x83);
minutel=minute&0x0f;
minuteh=minute>>4;
hour=read_ds1302(0x85);
hourl=hour&0x0f;
hourh=hour>>4;
month=read_ds1302(0x89);
monthl=month&0x0f;
monthh=month>>4;
year=read_ds1302(0x8d);
yearl=year&0x0f;
yearh=year>>4;
date=read_ds1302(0x87);
datel=date&0x0f;
dateh=date>>4;
day=read_ds1302(0x8b);
day=day&0x0f;
delay(15);
write_lcd_com_date(0xca,0x30+secondl);
write_lcd_com_date(0xc9,0x30+secondh);
write_lcd_com_date(0xc8,':');
write_lcd_com_date(0xc7,0x30+minutel);
write_lcd_com_date(0xc6,0x30+minuteh);
write_lcd_com_date(0xc5,':');
write_lcd_com_date(0xc4,0x30+hourl);
write_lcd_com_date(0xc3,0x30+hourh);
write_lcd_com_date(0x84,0x30+yearl);
write_lcd_com_date(0x83,0x30+yearh);
write_lcd_com_date(0x85,'-');
write_lcd_com_date(0x87,0x30+monthl);
write_lcd_com_date(0x86,0x30+monthh);
write_lcd_com_date(0x88,'-');
write_lcd_com_date(0x8a,0x30+datel);
write_lcd_com_date(0x89,0x30+dateh);
write_lcd_com_date(0x8c,0x30+day);
}
}
void delay_1ms(uint x)//延时
{ uchar j; //加一变量 uchar i,j;
while((x--)!=0) //改为for(i=0;i<x;i++)
{ for(j=0;j<125;j++) ;
}
}
//检查LCD忙状态
bit lcd_busy() //其实大多数都delayms(5)代替的,尤其是仿真时不能用此函数
{
bit result;
rs=0;
rw=0;
e = 1;
delay_1ms(1);
result = (bit)(data&0x80); //不知data是不是已经#define了
e = 0;
return(result);
}
//写指令数据到LCD
void write1602_com(uchar com)
{while(lcd_busy());
rs = 0;
rw = 0;
e = 0;
delay_1ms(1);
data= com;
delay_1ms(1);
e = 1;
delay_1ms(1);
e = 0;
}
//写显示数据到LCD
void write1602_data(uchar dat)
{while(lcd_busy());
rs = 1;
rw = 0;
e = 0;
data = dat;
delay_1ms(1);
e = 1;
delay_1ms(1);
e = 0;
}
void start(void) //LCD初始化
{delay_1ms(15);
write1602_com(0x38);
delay_1ms(5);
write1602_com(0x38);
delay_1ms(5);
write1602_com(0x38);
delay_1ms(5);
write1602_com(0x0F);//显示开,关光标
delay_1ms(5);
write1602_com(0x06);//移动光标
delay_1ms(5);
write1602_com(0x01);//清除LCD的显示内容
delay_1ms(5);
}
/ 设定显示位置 /
/
void lcd_data(uchar dat) //1602两行地址不是连续的,第二行是0xC0开始的
{
write1602_com(dat|0x80); //数据指针=80+地址变量
}
/
void lcd_data(uchar dat)
{
unsigned char p;
if (pos>=0x10)
p=pos+0xb0;
else
p=pos+0x80;
write1602_com(p);
write1602_data(c);
}
void main()
{
start();
delay_1ms(10);
write1602_com(0x01); //已经清屏,不知道这句的意义
delay_1ms(10);
delay_1ms(5);
lcd_data(0x00);
delay_1ms(5);
for(i=0;i<12;i++)
{
if(i==13){ //建议这句话加上大括号,放到后边,放在这影响不好
while(1);}
write1602_data(table2[i]);//应先写地址再写数据,而你这地址是不变的,最终导致数组数据在
//一个地址上陆续显示,不知道会是啥效果,并且希望你的数组不是const的。
//可以写个连续显示的函数,加指针的
delay_1ms(1);
}
}
我这1602的程序及仿真还有很多,可以向我联系的
所有人回答的都不对,其实是忘了将1602第5脚rw设置为0了,而郭天祥的板子是直接接地,所以不用设置,但是别的板子却不能照搬了。所以程序应改为
sbit lcdrw=P3^6;
void write_com(uchar com)
{
lcdrs=0;
lcdrw=0;//加这一条
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_data(uchar date)
{
lcdrs=1;
lcdrw=0;//加这一条
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
给你推荐一本书《MCS51单片机应用设计》哈尔滨工业大学出版社,里面很详细的
#include "reg52h"
#include "intrinsh"
unsigned char text1[] = "TTT TTTT add:qhd" ;
unsigned char text2[] = "TEL:13333333333 " ;
sbit RS = P2^0;
sbit RW = P2^1;
sbit EN = P1^2;
void delay_ms(unsigned char t);
void init_1602(void);
void write_command(unsigned char cmd);
void write_data(unsigned char dat);
void dsp_onechar(unsigned char pos,unsigned char c);
void dsp_string(unsigned char line,unsigned char p,unsigned char length);
void main(void)
{
init_1602();
delay_ms(15);
dsp_string(0,text1,16);
dsp_string(1,text2,16);
while(1);
}
void delay_ms(unsigned char t)//毫秒延时大约延时1ms
{
unsigned char i;
while(t--)
{
for(i=0;i<112;i++);
}
}
void write_command(unsigned char cmd)//写指令函数(按规定RS=0,RW=0为写指令)
{
delay_ms(5); // check busy flag
EN = 0;
RS = 0;
RW = 0;
_nop_();
EN = 1;
P0 = cmd;
EN = 0;
}
void write_data(unsigned char dat)//往1602写数据
{
delay_ms(5); //busy flag check
EN = 0;
RS = 1;
RW = 0;
_nop_();
EN = 1;
P0 = dat;
EN = 0;
RS = 0;
}
void dsp_onechar(unsigned char pos,unsigned char c)//写一个字节函数
{
unsigned char p;
if (pos>=0x10)
p=pos+0xb0;
else
p=pos+0x80;
write_command(p);
write_data(c);
}
void dsp_string(unsigned char line,unsigned char p,unsigned char length)
{
unsigned char l,i;
l=line<<4;
for (i=0;i<length;i++)
dsp_onechar(l++,(p+i));
}
void init_1602(void)//1602初始化
{
delay_ms(15);
write_command(0x38);
write_command(0x38);
write_command(0x38);
write_command(0x06);
write_command(0x0c);
write_command(0x01);
}
以上就是关于1602的判忙作用是什么时序该怎么写全部的内容,包括:1602的判忙作用是什么时序该怎么写、单片机1602液晶显示的DS1302实时时钟帮我分析以下程序运行步骤,详细解释一下,尤其是Bcd转换、大家帮忙看看这个1602的显示程序有什么问题void delay_1ms(uint x)//延时 { uchar j; while((x--)!=0) {等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)