跪求:液晶LCD1602显示时钟的C程序!

2024-12-19 01:39:05
推荐回答(3个)
回答1:

顶层文件 万年历.C #include #include "LCD1602.h" #include "DS1302.h" #define uchar unsigned char #define uint unsigned int sbit speaker=P2^4; bit key_flag1=0,key_flag2=0; SYSTEMTIME adjusted; uchar sec_add=0,min_add=0,hou_add=0,day_add=0,mon_add=0,yea_add=0; uchar data_alarm[7]={0}; /************键盘控制******************************/ int key_scan() //扫描是否有键按下 { int i=0; uint temp; P1=0xf0; temp=P1; if(temp!=0xf0) i=1; else i=0; return i; } uchar key_value() //确定按键的值 { uint m=0,n=0,temp; uchar value; uchar v[4][3]={'2','1','0','5','4','3','8','7','6','b','a','9'} ; P1=0xfe; temp=P1; if(temp!=0xfe)m=0; P1=0xfd;temp=P1 ;if(temp!=0xfd)m=1; P1=0xfb;temp=P1 ;if(temp!=0xfb)m=2; P1=0xf7;temp=P1 ;if(temp!=0xf7)m=3; P1=0xef;temp=P1 ;if(temp!=0xef)n=0; P1=0xdf;temp=P1 ;if(temp!=0xdf)n=1; P1=0xbf;temp=P1 ;if(temp!=0xbf)n=2; value=v[m][n]; return value; } /***************************设置闹铃函数*******************************/ void naoling(void) { uchar i=0,l=0,j; init1602(); while(key_flag2&&i<12) if(key_scan()){j=key_value();write_data(j);if(i%2==0)data_alarm[l]=(j-'0')*10;else {data_alarm[l]+=(j-'0');l++;}i++;delay(600);} write_com(0x01); } uchar according(void) { uchar k; if(data_alarm[0]==adjusted.Year&&data_alarm[1]==adjusted.Month&&data_alarm[2]==adjusted.Day&&data_alarm[3]==adjusted.Hour&&data_alarm[4]==adjusted.Minute&&data_alarm[5]==adjusted.Second) k=1; else k=0; return k; } void speak(void) {uint i=50; while(i) {speaker=0; delay(1); speaker=1; delay(1); i--; } } void alarm(void) {uint i=10; while(i) { speak(); delay(10); i--; } } /**************************修改时间操作********************************/ void reset(void) { sec_add=0; min_add=0; hou_add=0; day_add=0; mon_add=0; yea_add=0 ; } void adjust(void) { if(key_scan()&&key_flag1) switch(key_value()) {case '0':sec_add++;break; case '1':min_add++;break; case '2':hou_add++;break; case '3':day_add++;break; case '4':mon_add++;break; case '5':yea_add++;break; case 'b':reset();break; default: break; } adjusted.Second+=sec_add; adjusted.Minute+=min_add; adjusted.Hour+=hou_add; adjusted.Day+=day_add; adjusted.Month+=mon_add; adjusted.Year+=yea_add; if(adjusted.Second>59) adjusted.Second=adjusted.Second%60; if(adjusted.Minute>59) adjusted.Minute=adjusted.Minute%60; if(adjusted.Hour>23) adjusted.Hour=adjusted.Hour%24; if(adjusted.Day>31) adjusted.Day=adjusted.Day%31; if(adjusted.Month>12) adjusted.Month=adjusted.Month%12; if(adjusted.Year>100) adjusted.Year=adjusted.Year%100; } /**************************中断处理函数*********************************/ void changing(void) interrupt 0 using 0 //需要修改时间和日期,或者停止修改 { if(key_flag1)key_flag1=0; else key_flag1=1; } void alarming(void) interrupt 3 using 0 //需要设置闹铃或者停止设置 { if(key_flag2)key_flag2=0; else key_flag2=1; } /********************************主函数***********************************/ main() {uint i; uchar *l; uchar p1[]="D:",p2[]="T:"; SYSTEMTIME T; EA=1; EX0=1; IT0=1; EA=1; EX1=1; IT1=1; init1602(); Initial_DS1302() ; while(1) { write_com(0x80); write_string(p1,2); write_com(0xc0); write_string(p2,2); DS1302_GetTime(&T) ; adjusted.Second=T.Second; adjusted.Minute=T.Minute; adjusted.Hour=T.Hour; adjusted.Week=T.Week; adjusted.Day=T.Day; adjusted.Month=T.Month; adjusted.Year=T.Year; for(i=0;i<9;i++) { adjusted.DateString[i]=T.DateString[i]; adjusted.TimeString[i]=T.TimeString[i]; } adjust(); if(key_flag2)naoling(); if(according())alarm(); DateToStr(&adjusted); TimeToStr(&adjusted); write_com(0x82); write_string(adjusted.DateString,8); write_com(0xc2); write_string(adjusted.TimeString,8); delay(10); } (二)头文件1 显示模块 LCD1602.H #ifndef LCD_CHAR_1602_2009_5_9 #define LCD_CHAR_1602_2009_5_9 #define uchar unsigned char #define uint unsigned int sbit lcdrs = P2^0; sbit lcdrw = P2^1; sbit lcden = P2^2; void delay(uint z) // 延时 { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void write_com(uchar com) // 写入指令数据到 lcd { lcdrw=0; lcdrs=0; P0=com; delay(5); lcden=1; delay(5); lcden=0; } void write_data(uchar date) // 写入字符显示数据到 lcd { lcdrw=0; lcdrs=1; P0=date; delay(5); lcden=1; delay(5); lcden=0; } void init1602() // 初始化设定 { lcdrw=0; lcden=0; write_com(0x3C); write_com(0x0c); write_com(0x06); write_com(0x01); write_com(0x80); } void write_string(uchar *pp,uint n) { int i; for(i=0;i0; i--) { DS1302_IO = ACC0; DS1302_CLK = 1; DS1302_CLK = 0; ACC = ACC >> 1; //因为在前面已经定义了ACC0 = ACC^0;以便再次利用DS1302_IO = ACC0; } } unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数) { unsigned char i; for(i=8; i>0; i--) { ACC = ACC >>1; ACC7 = DS1302_IO; DS1302_CLK = 1; DS1302_CLK = 0; } return(ACC); } /********************************/ void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据 { DS1302_RST = 0; DS1302_CLK = 0; DS1302_RST = 1; DS1302InputByte(ucAddr); // 地址,命令 DS1302InputByte(ucDa); // 写1Byte数据 DS1302_CLK = 1; DS1302_RST = 0; } unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据 { unsigned char ucData; DS1302_RST = 0; DS1302_CLK = 0; DS1302_RST = 1; DS1302InputByte(ucAddr|0x01); // 地址,命令 ucData = DS1302OutputByte(); // 读1Byte数据 DS1302_CLK = 1; DS1302_RST = 0; return(ucData); } void DS1302_SetProtect(bit flag) //是否写保护 { if(flag) Write1302(0x8E,0x10); else Write1302(0x8E,0x00); } void DS1302_SetTime(unsigned char Address, unsigned char Value) // 设置时间函数 { DS1302_SetProtect(0); Write1302(Address, ((Value/10)<<4 | (Value%10))); //将十进制数转换为BCD码 } //在DS1302中的与日历、时钟相关的寄存器存放的数据必须为BCD码形式 void DS1302_GetTime(SYSTEMTIME *Time) { unsigned char ReadValue; ReadValue = Read1302(DS1302_SECOND); Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将BCD码转换为十进制数 ReadValue = Read1302(DS1302_MINUTE); Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_HOUR); Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_DAY); Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_WEEK); Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_MONTH); Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_YEAR); Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); } unsigned char *DataToBCD(SYSTEMTIME *Time) { unsigned char D[8]; D[0]=Time->Second/10<<4+Time->Second%10; D[1]=Time->Minute/10<<4+Time->Minute%10; D[2]=Time->Hour/10<<4+Time->Hour%10; D[3]=Time->Day/10<<4+Time->Day%10; D[4]=Time->Month/10<<4+Time->Month%10; D[5]=Time->Week/10<<4+Time->Week%10; D[6]=Time->Year/10<<4+Time->Year%10; return D; } void DateToStr(SYSTEMTIME *Time) { //将十进制数转换为液晶显示的ASCII值 Time->DateString[0] = Time->Year/10 + '0'; Time->DateString[1] = Time->Year%10 + '0'; Time->DateString[2] = '-'; Time->DateString[3] = Time->Month/10 + '0'; Time->DateString[4] = Time->Month%10 + '0'; Time->DateString[5] = '-'; Time->DateString[6] = Time->Day/10 + '0'; Time->DateString[7] = Time->Day%10 + '0'; Time->DateString[8] = '\0'; } void TimeToStr(SYSTEMTIME *Time) { //将十进制数转换为液晶显示的ASCII值 Time->TimeString[0] = Time->Hour/10 + '0'; Time->TimeString[1] = Time->Hour%10 + '0'; Time->TimeString[2] = ':'; Time->TimeString[3] = Time->Minute/10 + '0'; Time->TimeString[4] = Time->Minute%10 + '0'; Time->TimeString[5] = ':'; Time->TimeString[6] = Time->Second/10 + '0'; Time->TimeString[7] = Time->Second%10 + '0'; Time->DateString[8] = '\0'; } void Initial_DS1302(void) { unsigned char Second; Second=Read1302(DS1302_SECOND); if(Second&0x80) //初始化时间 DS1302_SetTime(DS1302_SECOND,0); } void DS1302_TimeStop(bit flag) // 是否将时钟停止 { unsigned char Data; Data=Read1302(DS1302_SECOND); DS1302_SetProtect(0); if(flag) Write1302(DS1302_SECOND, Data|0x80); else Write1302(DS1302_SECOND, Data&0x7F); } #endif zftzbpujjj1134358763,jaiezwwysu6517560870,2012-2-15 11:08:28

回答2:

#include
#define uchar unsigned char
#define uint unsigned int
sbit e=P3^4; //1602液晶的使能
sbit rs=P3^5; //1602液晶的片选
sbit key1=P3^0; //第一按键功能:调节时间选择位
sbit key2=P3^1; //第二按键功能:加值键
sbit key3=P3^2; //第三按键功能:减值键
sbit rd=P3^7; //矩阵键盘一根线设置为0,用其中四个做独立按键
sbit dscs=P2^4;
sbit dsas=P2^5;
sbit dsrw=P2^6;
sbit dsds=P2^7;
sbit dsirq=P3^3;
sbit beep=P2^3;
uchar code table1[]=" 20 - - "; //初始1602液晶显示的内容
uchar code table2[]=" : : ";
uchar count,k,week,mon,day,year,flag,flag1; //定义年月日
char shi,fen,miao; //定义时分秒和星期(char型,因为要判断其值时出现-1)
void write_ds(uchar,uchar);
void set_alarm(uchar,uchar,uchar);
uchar read_ds(uchar);
void set_time();
void delay(uint z) //延时函数
{
uint i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--);
}
void didi()
{
beep=0;
delay(50);
beep=1;
delay(100);
beep=0;
delay(50);
beep=1;
}
void write_com(uchar com) //1602液晶写命令程序
{
rs=0;
P1=com;
e=0;
delay(5);
e=1;
delay(5);
e=0;
delay(5);
}
void write_dat(uchar dat) //1602液晶写数据程序
{
rs=1;
P1=dat;
e=0;
delay(5);
e=1;
delay(5);
e=0;
delay(5);
}
void write_sfm(uchar add,uchar dat) //写时分秒的程序
{
uchar sh,g;
sh=dat/10;
g=dat%10;
write_com(0x80+0x40+add);
write_dat(0x30+sh); //1602字符手册里的数字对应的编码值
write_dat(0x30+g);
}
void write_nyr(uchar add,uchar dat)//写年月日的程序
{
uchar sh,g;
sh=dat/10;
g=dat%10;
write_com(0x80+add);
write_dat(0x30+sh);
write_dat(0x30+g);
}
void write_week(char we)
{ //写液晶星期显示函数
write_com(0x80+12);
switch(we)
{
case 1: write_dat('M');delay(5);
write_dat('o');delay(5);
write_dat('n');
break;
case 2: write_dat('T');delay(5);
write_dat('u');delay(5);
write_dat('e');
break;
case 3: write_dat('W');delay(5);
write_dat('e');delay(5);
write_dat('d');
break;
case 4: write_dat('T');delay(5);
write_dat('h');delay(5);
write_dat('u');
break;
case 5: write_dat('F');delay(5);
write_dat('r');delay(5);
write_dat('i');
break;
case 6: write_dat('S');delay(5);
write_dat('a');delay(5);
write_dat('t');
break;
case 7: write_dat('S');delay(5);
write_dat('u');delay(5);
write_dat('n');
break;
}
}
void init() //初始化液晶和定时器
{
uchar num;
EA=1;
EX0=1;
IT0=1;
e=0;
set_alarm(11,13,10);
write_ds(0x0B,0x26);
read_ds(0x0c);
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
delay(2);
write_com(0x80); //为什么不能放在主函数的while大循环内呢?
for(num=0;num<16;num++) //因为这是初始数据,不能不断循环执行写入,
{ //只需把部分必须改变的改变即可。
write_dat(table1[num]);
delay(2);
}
write_com(0x80+0x40);
for(num=0;num<16;num++)
{
write_dat(table2[num]);
delay(2);
}
}
/*void keyscan() //键盘扫描程序
{
rd=0; //键盘的列端口设置
if(flag1==1)
{
if((key1==0)||(key2==0)||(key3==0))
{
delay(5);
if((key1==0)||(key2==0)||(key3==0))
{
while(!(key1&&key2&&key3));
didi();
flag1=0;
}
}
}
if(key1==0)
{
delay(5); //延时消抖
if(key1==0)//确认按键是否按下
{
flag=1;
flag1=0;
k++;
while(!key1);//松手检测
if(k==1) //按下功能键停止计时并分别用光标指向时分秒年月日进行调整
{
TR0=0;
write_com(0x80+0x40+11); //设置光标为写命令后不加1
write_com(0x0f);//设置光标为闪烁状态
}
}
if(k==2)
{
write_com(0x80+0x40+8);
}
if(k==3)
{
write_com(0x80+0x40+5);
}
if(k==4)
{
write_com(0x80+10);
}
if(k==5)
{
write_com(0x80+7);
}
if(k==6)
{
write_com(0x80+4);
}
if(k==7)
{
write_com(0x80+14);
}
if(k==8) //最后再按下功能键确认开始重新计时
{
k=0;
write_com(0x0c);
flag=0;
write_ds(0,miao);
write_ds(2,fen);
write_ds(4,shi);
write_ds(6,week);
write_ds(7,day);
write_ds(8,mon);
write_ds(9,year);
}
}
if(k!=0) //在key1键按下的情况下才能使用 加值(key2)功能键
{
if(key2==0)
{
delay(5);
if(key2==0)
{
while(!key2);
if(k==1) //秒加1(按下Key即秒加一)
{
miao++;
if(miao==60)
miao=0;
write_sfm(10,miao);
write_com(0x80+0x40+11);
}
if(k==2) //分加1
{
fen++;
if(fen==60)
fen=0;
write_sfm(7,fen);
write_com(0x80+0x40+8);
}
if(k==3) //时加1
{
shi++;
if(shi==24)
shi=0;
write_sfm(4,shi);
write_com(0x80+0x40+5);
}
if(k==4) //day加1
{
day++;
if(day==32)
day=0;
write_nyr(9,day);
write_com(0x80+10);
}
if(k==5) //mon加1
{
mon++;
if(mon==13)
mon=0;
write_nyr(6,mon);
write_com(0x80+7);
}
if(k==6) //year加1
{
year++;
if(year==100)
year=0;
write_nyr(3,year);
write_com(0x80+4);
}
if(k==7) //week加1
{
week++;
if(week==8)
week=1;
write_week(week);
write_com(0x80+14);
}
}
}
if(key3==0)//在key1键按下的情况下才能使用 减值(key3)功能键
{
delay(5);
if(key3==0)
{
while(!key3);
if(k==1) //秒减1
{
miao--;
if(miao==-1)
miao=59;
write_sfm(10,miao);
write_com(0x80+0x40+11);
}
if(k==2) //分减1
{
fen--;
if(fen==-1)
fen=59;
write_sfm(7,fen);
write_com(0x80+0x40+8);
}
if(k==3) //时减1
{
shi--;
if(shi==-1)
shi=23;
write_sfm(4,shi);
write_com(0x80+0x40+5);
}
if(k==4) //day减1
{day--;
if(day==0)
day=31;
write_nyr(9,day);
write_com(0x80+10);
}
if(k==5) //mon减1
{mon--;
if(mon==0)
mon=12;
write_nyr(6,mon);
write_com(0x80+7);
}
if(k==6) //year减1
{
year--;
if(year==0)
year=99;
write_nyr(3,year);
write_com(0x80+4);
}
if(k==7)//week减1
{week--;
if(week==0)
week=7;
write_week(week);
write_com(0x80+14);
}
}
}
}
} */
void write_ds(uchar add,uchar dat)
{dscs=0;
dsas=1;
dsds=1;
dsrw=1;
P0=add;
dsas=0;
dsrw=0;
P0=dat;
dsrw=1;
dsas=1;
dscs=1;
}
uchar read_ds(uchar add)
{uchar ds_dat;
dscs=0;
dsas=1;
dsds=1;
dsrw=1;
P0=add;
dsas=0;
dsds=0;
P0=0xff;
ds_dat=P0;
dsds=1;
dsas=1;
dscs=1;
return ds_dat;
}
void set_time()
{write_ds(0,0);
write_ds(2,59);
write_ds(4,23);
write_ds(6,1);
write_ds(7,28);
write_ds(8,2);
write_ds(9,10);
}
void set_alarm(uchar ashi,uchar afen,uchar amiao)
{write_ds(1,amiao);
write_ds(3,afen);
write_ds(5,ashi);
}
void main()
{init();
while(1) //不停调用键盘扫描看是否有按键按下
{
//keyscan();
if(flag1==1)
didi();
if(flag==0)
{miao=read_ds(0);
fen=read_ds(2);
shi=read_ds(4);
week=read_ds(6);
day=read_ds(7);
mon=read_ds(8);
year=read_ds(9);
write_sfm(10,miao);
write_sfm(7,fen);
write_sfm(4,shi);
write_nyr(9,day);
write_nyr(6,mon);
write_nyr(3,year);
write_week(week);
}
}
}
void exter() interrupt 0
{uchar c;
flag1=1;
c=read_ds(0x0c);
}

回答3:

北航的《PIC16系列单片机C程序设计与PROTEUS仿真》一书有这种LCD的仿真的线路图和程序,并有详细介绍使用,你看一下,会有好处的。
因为这种程序比较复杂,如果只给你程序,没搞懂其中的原理,今后要改都很困难。所以要认真看一下书,知道其原理后才变成真正是你的东东。
如果有人给你粘贴一大段的程序,会有用么?除了程序难看懂外,程序还与硬件有关!
所以建议你看一下书,搞清原理(硬件与软件)才是硬道理!