您好,欢迎来到刀刀网。
搜索
您的当前位置:首页1602液晶显示DS1302实时时钟程序.

1602液晶显示DS1302实时时钟程序.

来源:刀刀网


#include #include

unsigned char code dis_week[]={\"SUN,MON,TUE,WED,THU,FRI,SAT\ unsigned char code para_month[13]={0,0,3,3,6,1,4,6,2,5,0,3,5}; //星期月参变数

unsigned char data dis_buf1[16]; //lcd上排显示缓冲区 unsigned char data dis_buf2[16]; //lcd下排显示缓冲区

unsigned char data year,month,date,week;//年、月、日、星期 unsigned char data armhour,armmin,armsec;//闹钟时、分、秒

unsigned char data hour,min,sec,sec100; //时、分、秒、百分之一秒 unsigned char data flag,vkey,skey;//设置状态计数标志、按键先前值、按键当前值

bit alarm; //标识是否启用闹钟,1--启用,0--关闭

sbit rs = P2^0; //LCD数据/命令选择端(H/L)

sbit rw = P2^1; //LCD读/写选择端(H/L) sbit ep = P2^2; //LCD使能控制 sbit PRE = P1^6; //调整键(k3) sbit SET = P1^7; //调整键(k4) sbit SPK = P3^7; void delayms(unsigned char ms); //延时程序

bit lcd_busy(); //测试LCD忙碌状态程序 void lcd_wcmd(char cmd); //写入指令到LCD程序 void lcd_wdat(char dat); //写入数据到LCD程序 void lcd_pos(char pos); //LCD数据指针位置程序 void lcd_init(); //LCD初始化设定程序 void pro_timedate(); //时间日期处理程序 void pro_display(); //显示处理程序 void pro_key(); //按键处理程序

void time_alarm(); //定时报警功能(闹钟) unsigned char scan_key(); //按键扫描程序

unsigned char week_proc(); //星期自动计算与显示函数 bit leap_year(); //判断是否为闰年 void lcd_sef_chr(); //LCD自定义字符程序

void update_disbuf(unsigned char t1,unsigned char t2[],unsigned char dis_h,unsigned char dis_m,unsigned char dis_s); //更新显示缓冲区函数

// 延时程序

void delay(unsigned char ms) { while(ms--)

{ unsigned char i;

for(i = 0; i 250; i++) {

_nop_(); //执行一条_nop_()指令为一个机器周期

_nop_(); _nop_(); _nop_(); } } }

//测试LCD忙碌状态 bit lcd_busy() {

bit result; rs = 0; rw = 1; ep = 1; _nop_(); _nop_(); _nop_(); _nop_();

result =(bit)(P0&0x80); //LCD的D0--D7中,D7=1为忙碌,D7=0为空闲

ep = 0;

return result; }

//写入指令到LCD

void lcd_wcmd(char cmd)

{

while(lcd_busy()); //当lcd_busy为1时,再次检测LCD忙碌状态,lcd-busy为0时,开始写指令 rs = 0; rw = 0; ep = 0; _nop_();

_nop_(); P0 = cmd; _nop_(); _nop_(); _nop_();

_nop_(); ep = 1; _nop_(); _nop_(); _nop_(); _nop_();

ep = 0; }

//写入数据到LCD

void lcd_wdat(char dat)

{

while(lcd_busy()); //当lcd_busy为1时,再次检测LCD忙碌状态,lcd-busy为0时,开始写数据 rs = 1; rw = 0; ep = 0; P0 = dat; _nop_(); _nop_(); _nop_(); _nop_(); ep = 1; _nop_(); _nop_(); _nop_(); _nop_(); ep = 0; }

//LCD数据指针位置程序 void lcd_pos(char pos)

{

lcd_wcmd(pos|0x80); //数据指针=80+地址码(00H~27H,40H~67H) }

//设定二个自定义字符,(注意:LCD1602中自定义字符的地址为0x00--0x07,即可定义8个字符)

//这里我们设定把一个自定义字符放在0x00位置(000),另一个放在0x01位子(001)

void lcd_sef_chr()

{ //第一个自定义字符

lcd_wcmd(0x40); //\"01 000 000\" 第1行地址 (D7D6为地址设定命令形式D5D4D3为字符存放位置(0--7),D2D1D0为字符行地址(0--7))

lcd_wdat(0x1f); //\"XXX 11111\" 第1行数据(D7D6D5为XXX,表示为任意数(一般用000),D4D3D2D1D0为字符行数据(1-点亮,0-熄灭) lcd_wcmd(0x41); //\"01 000 001\" 第2行地址 lcd_wdat(0x11); //\"XXX 10001\" 第2行数据 lcd_wcmd(0x42); //\"01 000 010\" 第3行地址 lcd_wdat(0x15); //\"XXX 10101\" 第3行数据 lcd_wcmd(0x43); //\"01 000 011\" 第4行地址 lcd_wdat(0x11); //\"XXX 10001\" 第4行数据 lcd_wcmd(0x44); //\"01 000 100\" 第5行地址 lcd_wdat(0x1f); //\"XXX 11111\" 第5行数据 lcd_wcmd(0x45); //\"01 000 101\" 第6行地址 lcd_wdat(0x0a); //\"XXX 01010\" 第6行数据 lcd_wcmd(0x46); //\"01 000 110\" 第7行地址 lcd_wdat(0x1f); //\"XXX 11111\" 第7行数据 lcd_wcmd(0x47); //\"01 000 111\" 第8行地址 lcd_wdat(0x00); //\"XXX 00000\" 第8行数据 //第二个自定义字符

lcd_wcmd(0x48); //\"01 001 000\" 第1行地址 lcd_wdat(0x01); //\"XXX 00001\" 第1行数据 lcd_wcmd(0x49); //\"01 001 001\" 第2行地址 lcd_wdat(0x1b); //\"XXX 11011\" 第2行数据 lcd_wcmd(0x4a); //\"01 001 010\" 第3行地址 lcd_wdat(0x1d); //\"XXX 11101\" 第3行数据 lcd_wcmd(0x4b); //\"01 001 011\" 第4行地址 lcd_wdat(0x19); //\"XXX 11001\" 第4行数据 lcd_wcmd(0x4c); //\"01 001 100\" 第5行地址 lcd_wdat(0x1d); //\"XXX 11101\" 第5行数据 lcd_wcmd(0x4d); //\"01 001 101\" 第6行地址 lcd_wdat(0x1b); //\"XXX 11011\" 第6行数据 lcd_wcmd(0x4e); //\"01 001 110\" 第7行地址 lcd_wdat(0x01); //\"XXX 00001\" 第7行数据 lcd_wcmd(0x4f); //\"01 001 111\" 第8行地址 lcd_wdat(0x00); //\"XXX 00000\" 第8行数据 }

//LCD初始化设定 void lcd_init()

{

lcd_wcmd(0x38); //设置LCD为16X2显示,5X7点阵,八位数据借口

delay(1);

lcd_wcmd(0x0c); //LCD开显示及光标设置(光标不闪烁,不显示\"-\")

delay(1);

lcd_wcmd(0x06); //LCD显示光标移动设置(光标地址指针加1,整屏显示不移动) delay(1);

lcd_wcmd(0x01); //清除LCD的显示内容 delay(1); }

//闰年的计算 bit leap_year() {

bit leap;

if((year%4==0&&year%100!=0)||year%400==0)//闰年的条件 leap=1; else

leap=0; return leap; }

//星期的自动运算和处理 unsigned char week_proc() { unsigned char num_leap; unsigned char c;

num_leap=year/4-year/100+year/400;//自00年起到year所经历的闰年数

if( leap_year()&& month=2 ) //既是闰年且是1月和2月 c=5; else

c=6;

week=(year+para_month[month]+date+num_leap+c)%7;//计算对应的星期

return week; }

//更新显示缓冲区

void update_disbuf(unsigned char t1,unsigned char t2[],unsigned char dis_h,unsigned char dis_m,unsigned char dis_s) { dis_buf1[0]=t1; // dis_buf1[1]=0x20; //空格 dis_buf1[2]=50; //'2' dis_buf1[3]=48; //'0'

dis_buf1[4]=year/10+48; dis_buf1[5]=year%10+48; dis_buf1[6]=0x2d;

dis_buf1[7]=month/10+48; dis_buf1[8]=month%10+48;

dis_buf1[9]=0x2d; //'-' dis_buf1[10]=date/10+48; dis_buf1[11]=date%10+48; dis_buf1[12]=0x20;

dis_buf1[13]=dis_week[4*week]; dis_buf1[14]=dis_week[4*week+1]; dis_buf1[15]=dis_week[4*week+2];

dis_buf2[0]=t2[0]; dis_buf2[1]=t2[1]; dis_buf2[2]=t2[2]; dis_buf2[3]=t2[3]; dis_buf2[4]=t2[4]; dis_buf2[5]=t2[5];

dis_buf2[6]=0x20; //空格 if (alarm)

dis_buf2[7]=0x01; //alarm=1,显示闹钟启用标致(第二个自定义字符) else

dis_buf2[7]=0x20; //alarm=0,不显示闹钟启用标致

dis_buf2[8]=dis_h/10+48; dis_buf2[9]=dis_h%10+48;

dis_buf2[10]=0x3a; //':' dis_buf2[11]=dis_m/10+48; dis_buf2[12]=dis_m%10+48; dis_buf2[13]=0x3a;

dis_buf2[14]=dis_s/10+48; dis_buf2[15]=dis_s%10+48; }

//时间和日期处理程序 void pro_timedate() {

sec++;

if(sec > 59) {sec = 0; min++; if(min>59)

{min=0; hour++; if(hour>23) {hour=0; date++; if

(month==1||month==3||month==5||month==7||month==8||month==10||month==12)

if (date>31)

{date=1;month++;} //大月31天 if

(month==4||month==6||month==9||month==11) if (date>30)

{date=1;month++;} //小月30天 if (month==2)

{if( leap_year()) //闰年的条件

{if (date>29)

{date=1;month++;}} //闰年2月为29天 else

{if (date>28)

{date=1;month++;}} //平年2月为28天 } if (month>12) {month=1;year++;} if (year>99) year=0; } } }

week_proc();

if (sec==armsec && min==armmin &&

hour==armhour) {if (alarm)

TR1=1; //闹钟启用时,报警时间到,启动Timer1 } }

//显示处理程序 void pro_display() { unsigned char i; lcd_pos(0x00); for (i=0;i=15;i++)

{lcd_wdat(dis_buf1[i]);}

lcd_pos(0x40); for (i=0;i=15;i++)

{lcd_wdat(dis_buf2[i]);} }

//Timer0中断处理程序,秒的产生 void timer0() interrupt 1 {

TH0=0xdc; //Timer0置10ms定时初值dc00H(2^16=65536D,dc00H=56320D) TL0=0x00; //定时时间

=(65536-56320)*(1/11.0592)*12=10ms (f0=11.0592Mhz) sec100++;

if(sec100 >= 100) //1秒时间 (100*10ms=1000ms=1s) {sec100 = 0;

pro_timedate();//调用时间和日期处理程序 } if

(sec&0x01) /\"willar\"闪一秒,停一秒

update_disbuf(0x00,\" \0表示显示00位置的自定义字符 else

update_disbuf(0x00,\"willar\ pro_display(); //调用显示处理函数

}

//按键扫描程序

unsigned char scan_key() {

skey=0x00; 给变量vkey置初值

skey|=PRE; 读取PRE键的状态

skey=skey<<1; PRE键的状态存于skey的B1位

skey|=SET; 读取SET键的状态,并存于skey的B0位

return skey; 返回skey的键值(即PRE,SET的状态)

/ //0x0 // //将 // // //

}

//外部中断INT0中断处理程序 void int0() interrupt 0 {

TR0=0; //禁止Timer0

IE=0; //禁止中断

lcd_wcmd(0x0e); //显示光标\"_\整个光标不闪烁 alarm=1;

update_disbuf(0x50,\"alarm:\更新显示数据,0x50表示要显示\"P\"

pro_display(); //调用显示处理程序

lcd_pos(0x47); //使光标位于第一个调整项下

flag=0;

vkey=0x03;

while(flag^0x0a) {skey = scan_key(); //扫描按键状态

if (skey^vkey) //若skey与vkey相同,跳出循环,相异执行循环体

{ delay(10); //去按键抖动

skey = scan_key(); //转回扫描按键状态

if (skey^vkey) //若skey与vkey相同,跳出循环,相异执行循环体

{ vkey=skey; //将skey的值付给vkey

if (skey==0x01) //PRE键按下

{ flag++; //调整标志位加1

switch (flag) //将光标置于相应调整位置

{

case 1: lcd_pos(0x49);break; //光标置小时报警设置位置

case 2: lcd_pos(0x4c);break; //光标置分钟报警设置位置

case 3: lcd_pos(0x4f);break; //光标置秒时报警设置位置

e 4: update_disbuf(0x50,\"time: \

pro_display();

lcd_pos(0x05);break; //光标置年调整位

e 5: lcd_pos(0x08);break; //光标置月调整位置

e 6: lcd_pos(0x0b);break; //光标置日调整位置

e 7: lcd_pos(0x49);break; //光标置时调整位置

e 8: lcd_pos(0x4c);break; //光标置分调整位置

e 9: lcd_pos(0x4f);break; //光标置秒调整位置

ault:break;

} } if (skey==0x02) //SET键按下

{ pro_key(); //转设置按键处理程序

} }

}

cas cas cas cas cas cas def

}

lcd_wcmd(0x0c); //设置LCD开显示及光标不闪烁,不显示\"-\"

lcd_wcmd(0x01); //清除LCD的显示内容

IE=0x8f; //CPU开中断,INT0,INT1,开中断

TR0=1; //Timer0启动 }

//主程序,初始化及初值设定 void main() {

lcd_init(); //初始化LCD

lcd_sef_chr(); //写入自定义字符号

hour=0;min=0;sec=0; //开机时的时,分,秒显示

armhour=0;armmin=0;armsec=0; //开机时的时,分,秒报警初值

year= 5; month=1;date=1; //开机时的年,月,日,星期显示

week_proc();

alarm=1; //初始开机,启用闹钟

IE = 0x8f; //CPU开中断,INT0,INT1,Timer0,Timer1开中断 IP = 0x04; //设置INT0为中断最高优先级

IT0=0;IT1=0; //外部

INT0,INT1设置为电平触发方式(注意,触发不要选边沿方式,易误动) TMOD = 0x11; //Timer0,Timer1工作于模式1, 16位定时方式

TH0 = 0xdc;TL0 = 0x00; //Timer0置10ms定时初值

TH1 = 0xff;TL1 = 0x00; //Timer1置初值

TR0 = 1; //Timer0启动

TR1 = 0;

while(1); }

//设置按键处理程序 void pro_key() {

switch (flag) {

case 0:alarm=!alarm; //启用或关闭闹钟(alarm=1:启用,alarm=0:关闭)

update_disbuf(0x50,\"alarm:\msec); //更新显示数据

pro_display(); //调用显示处理

lcd_pos(0x47);break; //光标回到原调整位置 case 1:armhour++;

if (armhour>23) armhour=0;

update_disbuf(0x50,\"alarm:\msec); //更新显示数据

pro_display(); //调用显示处理

lcd_pos(0x49);break; //光标回到原调整位置 case 2:armmin++;

if (armmin>59) armmin=0;

update_disbuf(0x50,\"alarm:\msec);

pro_display();

lcd_pos(0x4c);break; case 3:armsec++;

if (armsec>59) armsec=0;

update_disbuf(0x50,\"alarm:\msec);

pro_display();

lcd_pos(0x4f);break;

case 4:year++;

if (year> 99) year= 0;

week_proc(); //星期自动运算

update_disbuf(0x50,\"time: \

pro_display();

lcd_pos(0x05);break; case 5:month++;

if (month>12) month=1;

week_proc(); //星期自动运算

update_disbuf(0x50,\"time: \

pro_display();

lcd_pos(0x08);break; case 6:date++; if

(month==1||month==3||month==5||month==7||month==8||month==10||month==12)

if (date>31) date=1; //大月31天

if

(month==4||month==6||month==9||month==11)

if (date>30) date=1; //小月30天

if (month==2)

{if(leap_year()) //闰年的条件

{if (date>29) date=1;} //闰年2月为29天

else {if (date>28) date=1;}} //平年2月为28天

week_proc(); //星期自动运算

update_disbuf(0x50,\"time: \

pro_display();

lcd_pos(0x0b);break;

case 7:hour++;

if (hour>23) hour=0; update_disbuf(0x50,\"time: \

pro_display();

lcd_pos(0x49);break; case 8:min++;

if (min>59) min=0; update_disbuf(0x50,\"time: \

pro_display();

lcd_pos(0x4c);break; case 9:sec++;

if (sec>59) sec=0; update_disbuf(0x50,\"time: \

pro_display();

lcd_pos(0x4f);break; default:

break ; } }

//Timer1中断处理程序,产生报警的声音 void timer1() interrupt 3 {

TH1=0xff; TL1=0x00;

SPK=~SPK; }

//外部中断INT1中断处理程序,停止报警声音 void int1() interrupt 2 {

if(TR1)

TR1=0; }

//DS1302时钟程序 #include #include #define uchar unsigned char #define uint unsigned int

/********************************************************************/

//少占鱼制作 河北正定欢迎您 长沙航空职业技术学院 //2010 年QQ:4116534 //版权所有:www.51hei.com

#define LCD1602_RS P2_5 //定义引脚 #define LCD1602_RW P2_6 #define LCD1602_E P2_7 #define LCD1602_IO P0

#define Busy 0x80 //用于检测LCD1602状态字中的Busy标识

const uchar num[]=\" 34567+\"; uchar code a[] = {\" E N v\void WriteData(uchar DAT);

void WriteCommand(uchar command,BuysC); uchar ReadData(void); void Readbusy(void); void LCD1602_Init(void);

void DisplayOneChar(uchar X, uchar Y, uchar DData); void Displaystring(uchar X, uchar Y, uchar *DData); void Delay5Ms(void); void Delay400Ms(void); void delayms(uint); void delays(uint m) ; void delayus(uchar x) ; sbit DS1302_CLK =P2^0;// P1^0; sbit DS1302_IO =P2^1;// P1^1; sbit DS1302_RST =P2^2;// P1^2;

uchar shuju;

unsigned char time[]={0x11,0x03,0x28,0x01,0x12,0x39,0x00};// 初始化时间年月日星期时分秒

uchar Display_Buffer[12]={\"12:25:00\时、分、秒 的格式 uchar riqi[12]={\"11-03-28\年、月、日 的格式 uchar xingqi[5]=\"week\";//星期

unsigned char second,minute,hour,week,day,month,year; /******************1602函数********************************/

/********************************************************************/

void delays(uint m) { uint i,j; for(i=0;ifor(j=0;j<1000;j++) {;} } }

void Delay(void) {

unsigned char i; unsigned int j; for(i=0;i<200;i++) for(j=300;j>0;j--);

}

/*****************************************************************************

函数功能:向DS1302送一字节数据子程序 入口参数: 出口参数:

*****************************************************************************/

void InputByte(unsigned char BYTE) { char i;

for(i=8;i>0;i--)

{ //前面在read_ds1302()函数里已经把CLK清0了 DS1302_CLK=0;//这里再清0一次,看着清楚。呵呵 _nop_();

DS1302_IO=(bit)(BYTE&0x01);//取出低位数据给数据引脚 _nop_(); _nop_();

DS1302_CLK=1;//置1,时钟上升沿,引脚上的数据传入1302寄存器中 _nop_(); _nop_();

BYTE>>=1;//因为这里移位的BYTE不是最后要的结果,虽然最后循环完会多移一位,但没影响。 _nop_();

//循环最后一次后,时钟状态是高电平。 }

_nop_(); _nop_();

}

/*****************************************************************************

函数功能:读DS1302一个字节子程序,读数据是下降沿读 入口参数: 出口参数:

*****************************************************************************/

unsigned char OutputByte(void) {

unsigned char i; unsigned char ucdat=0; for(i=8;i>0;i--)

{ //前面时钟状态是高电平。

ucdat>>=1; //移位注意,移位不能放在循环语句末,否则最后循环完会多移一位。得到结果就错了。

DS1302_IO=1;//单片机端置高防止破坏1302传来的数据,开始接收1302端的高低数据对数据线的改变。

DS1302_CLK=0;//紧接着时钟变低,下降沿数据输出。 if(DS1302_IO)//数据已经输出,判断是1还是0.

ucdat|=0x80;//如果引脚是高则此位保存1。低不保存,右移的时候自然补0了。 _nop_();

DS1302_CLK=1;//读完一位数据,再置高时钟,准备读下一个。 _nop_();//延时一下。 }

//读完数据还是把时钟清0,下次好直接用。

DS1302_CLK=0;//读完数据还是把时钟清0,下次好直接用。 _nop_(); _nop_(); DS1302_RST=0; _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); DS1302_CLK=0; _nop_(); _nop_(); _nop_(); _nop_(); DS1302_RST=0; _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); return(ucdat); }

/*****************************************************************************

函数功能:向DS1302某地址写一字节数据子程序 入口参数:addr,TDat

出口参数:

*****************************************************************************/

void write_ds1302(unsigned char addr,unsigned char TDat) {

DS1302_RST=0; _nop_(); _nop_(); DS1302_CLK=0; _nop_(); _nop_(); DS1302_RST=1; _nop_(); _nop_(); _nop_(); _nop_();

InputByte(addr);//先写地址 _nop_(); _nop_();

InputByte(TDat);//再写数据

DS1302_IO=1;//单片机端置高防止破坏1302传来的数据,开始接收1302端的高低数据对数据线的改变。 DS1302_RST=0; delayus(10); DS1302_CLK=0; delayus(10); }

/*****************************************************************************

函数功能:读DS1302地址子程序 入口参数:add 出口参数:timedata

*****************************************************************************/

unsigned char read_ds1302(unsigned char addr) {

unsigned char timedata; DS1302_RST=0; _nop_(); DS1302_CLK=0; _nop_(); DS1302_RST=1;

InputByte(addr);//先写入读命令 timedata=OutputByte();//再读出数据

DS1302_IO=1;//单片机端置高防止破坏1302传来的数据,开始接收1302端的高低数据对数据线的改变。 DS1302_RST=0; delayus(10); DS1302_CLK=0; delayus(10); return(timedata); }

/*****************************************************************************

函数功能:初始化DS1302子程序

入口参数:time[](全局变量) 出口参数:

*****************************************************************************/

void initial_ds1302() {

DS1302_IO=1;//单片机端置高防止破坏1302传来的数据,开始接收1302端的高低数据对数据线的改变。 DS1302_RST=0; delayms(100); DS1302_CLK=0; delayms(100);

write_ds1302(0x8e,0x00); //写保护寄存器,在对时钟或RAM写前WP一定要为0

write_ds1302(0x8c,time[0]); //年 write_ds1302(0x88,time[1]); //月 write_ds1302(0x86,time[2]); //日 write_ds1302(0x8A,time[3]); //星期 write_ds1302(0x84,time[4]); //时 write_ds1302(0x82,time[5]); //分 write_ds1302(0x80,time[6]); //秒 write_ds1302(0x8e,0x80); //写保护寄存器 }

/*****************************************************************************

函数功能:读DS1302时间子程序 入口参数:

出口参数:全局变量(second,minute,hour,week,day,month,year)

*****************************************************************************/ void read_time() {

second=read_ds1302(0x81); //秒寄存器 _nop_();

minute=read_ds1302(0x83); //读分 _nop_();

hour=read_ds1302(0x85); //读时 _nop_();

week=read_ds1302(0x8B); //读星期 _nop_();

day=read_ds1302(0x87); //日 _nop_();

month=read_ds1302(0x); //月 _nop_();

year=read_ds1302(0x8d); //年 _nop_(); }

void main(void) {uchar shuju; delayms(2);

Delay400Ms(); //启动等待,等LCM讲入工作状态 delays(1);

LCD1602_Init(); //LCM初始化 Delay5Ms(); //延时片刻(可不要) DS1302_RST=0; delayms(1000);

DS1302_CLK=0; delayms(1000); shuju=ReadData(); Displaystring(2, 0, a); Delay();Delay(); delayms(2000);

Displaystring(3,0,riqi); Displaystring(12,0,xingqi); delayms(4000);

// initial_ds1302(); //初始化DS1302 delayms(1200); while(1) {

read_time();//读取时间

Display_Buffer[0]=hour/16+'0';//存储下时的高位进数组 Display_Buffer[1]=hour%16+'0';//存储下时的低位进数组

Display_Buffer[3]=minute/16+'0';//注意+'0'后存储的是ASCII。用于下面液晶显示。

Display_Buffer[4]=minute%16+'0';//注意+'0'后存储的是ASCII。用于下面液晶显示。

Display_Buffer[6]=second/16+'0'; Display_Buffer[7]=second%16+'0'; riqi[0]=year/16+'0'; riqi[1]=year%16+'0'; riqi[3]=month/16+'0'; riqi[4]=month%16+'0'; riqi[6]=day/16+'0'; riqi[7]=day%16+'0'; Displaystring(3,0,riqi);

delayms(1);

DisplayOneChar(14,1,week+'0'); Displaystring(3,1,Display_Buffer); } }

//写数据

void WriteData(uchar DAT) {

Readbusy(); LCD1602_RS = 1; LCD1602_RW = 0; LCD1602_IO = DAT;

LCD1602_E = 0; //若晶振速度太高可以在这后加小的延时 LCD1602_E = 0; //延时 LCD1602_E = 1; LCD1602_E=1; LCD1602_E=0; }

//写指令

void WriteCommand(uchar command,BuysC) //BuysC为0时忽略忙检测 {

LCD1602_IO=0x00; if (BuysC)

Readbusy(); //根据需要检测忙

LCD1602_RS = 0; LCD1602_RW = 0; LCD1602_IO = command; LCD1602_E = 0; LCD1602_E = 0; LCD1602_E = 1; LCD1602_E = 1; LCD1602_E=0; }

//读数据

uchar ReadData(void) {

Readbusy(); LCD1602_RS = 1; LCD1602_RW = 1; LCD1602_E = 0; LCD1602_E = 0; LCD1602_E = 1; delayms(1); LCD1602_E = 0; return(LCD1602_IO); } //读忙

void Readbusy(void) {

LCD1602_IO = 0xff;

LCD1602_RS = 0; LCD1602_RW = 1; LCD1602_E = 0; LCD1602_E = 0; LCD1602_E = 1; delayms(2);

while (LCD1602_IO&0x80); //检测忙信号 LCD1602_E = 0; } //初始化

void LCD1602_Init(void) //LCM初始化 {

Delay400Ms(); LCD1602_E = 0; LCD1602_IO=0x00;

WriteCommand(0x38,0); //三次显示模式设置,不检测忙信号 Delay5Ms();

WriteCommand(0x38,0); Delay5Ms();

WriteCommand(0x38,0); Delay5Ms();

WriteCommand(0x38,1); //显示模式设置,开始要求每次检测忙信号 Delay5Ms();

WriteCommand(0x08,1); //关闭显示 ] Delay5Ms();

WriteCommand(0x01,1); //显示清屏 Delay5Ms();

WriteCommand(0x06,1); // 显示光标移动设置 Delay5Ms();

WriteCommand(0x0f,1); // 显示开及光标设置 Delay5Ms(); }

//按指定位置显示一个字符

void DisplayOneChar(uchar X, uchar Y, uchar DData) {

Y &= 0x01;

X &= 0x0f; //X不能大于15,Y不能大于1 if (Y) X |= 0x40; //当要显示第二行时地址码+0x40; X |= 0x80; // 算出指令码

WriteCommand(X, 0); //这里不检测忙信号,发送地址码 WriteData(DData); }

//按指定位置显示一串字符

void Displaystring(uchar X, uchar Y, uchar *DData) {

uchar ListLength;

ListLength = 0; Y &= 0x01;

X &= 0x0f; //X不能大于15,Y不能大于1

while (DData[ListLength]>0x20) //若到达字串尾则退出 {

if (X <= 0x0f) //X坐标应小于0x0f {

DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符 ListLength++; X++; } } }

//5ms延时

void Delay5Ms(void) {

unsigned int t = 5552; while(t--); }

//400ms延时

void Delay400Ms(void) {

uchar i = 5; uint j; while(i--) { j=7269; while(j--); } } //

void delayms(uint k) {

uint data i,j;

for(i=0;ifor(j=0;j<121;j++) {;} } }

void delayus(uchar x) {

while(--x); }

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- gamedaodao.com 版权所有 湘ICP备2022005869号-6

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务