A. 跪求:液晶LCD1602顯示時鍾的C程序!
頂層文件 萬年歷.C #include<reg51.h> #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;i<n;i++) write_data(pp[i]); } #endif (三)頭文件2 時鍾模塊 DS1302.H #ifndef _REAL_TIMER_DS1302_2009_5_20_ #define _REAL_TIMER_DS1302_2003_5_20_ sbit DS1302_CLK = P2^6; //實時時鍾時鍾線引腳 sbit DS1302_IO = P2^7; //實時時鍾數據線引腳 sbit DS1302_RST = P2^5; //實時時鍾復位線引腳 sbit ACC0 = ACC^0; sbit ACC7 = ACC^7; typedef struct SYSTEM_TIME { unsigned char Second; unsigned char Minute; unsigned char Hour; unsigned char Week; unsigned char Day; unsigned char Month; unsigned char Year; unsigned char DateString[9]; //用這兩個字元串來放置讀取的時間 unsigned char TimeString[9]; }SYSTEMTIME; //定義的時間類型 #define AM(X) X #define PM(X) (X+12) // 轉成24小時制 #define DS1302_SECOND 0x80 #define DS1302_MINUTE 0x82 #define DS1302_HOUR 0x84 #define DS1302_WEEK 0x8A #define DS1302_DAY 0x86 #define DS1302_MONTH 0x88 #define DS1302_YEAR 0x8C #define DS1302_RAM(X) (0xC0+(X)*2) //用於計算 DS1302_RAM 地址的宏 /******內部指令**********/ void DS1302InputByte(unsigned char d) //實時時鍾寫入一位元組(內部函數) { unsigned char i; ACC = d; for(i=8; i>0; 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
B. 跪求 51單片機+12864液晶+1302時鍾製成的萬年歷c程序
頂層文件 萬年歷.C
#include<reg51.h>
#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;i<n;i++)
write_data(pp[i]);
}
#endif
(三)頭文件2 時鍾模塊 DS1302.H
#ifndef _REAL_TIMER_DS1302_2009_5_20_
#define _REAL_TIMER_DS1302_2003_5_20_
sbit DS1302_CLK = P2^6; //實時時鍾時鍾線引腳
sbit DS1302_IO = P2^7; //實時時鍾數據線引腳
sbit DS1302_RST = P2^5; //實時時鍾復位線引腳
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
typedef struct SYSTEM_TIME
{
unsigned char Second;
unsigned char Minute;
unsigned char Hour;
unsigned char Week;
unsigned char Day;
unsigned char Month;
unsigned char Year;
unsigned char DateString[9]; //用這兩個字元串來放置讀取的時間
unsigned char TimeString[9];
}SYSTEMTIME; //定義的時間類型
#define AM(X) X
#define PM(X) (X+12) // 轉成24小時制
#define DS1302_SECOND 0x80
#define DS1302_MINUTE 0x82
#define DS1302_HOUR 0x84
#define DS1302_WEEK 0x8A
#define DS1302_DAY 0x86
#define DS1302_MONTH 0x88
#define DS1302_YEAR 0x8C
#define DS1302_RAM(X) (0xC0+(X)*2) //用於計算 DS1302_RAM 地址的宏
/******內部指令**********/
void DS1302InputByte(unsigned char d) //實時時鍾寫入一位元組(內部函數)
{
unsigned char i;
ACC = d;
for(i=8; i>0; 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
C. 單片機數字時鍾程序及電路圖
#include <reg51.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
sbit LCD_RS=P2^0;
sbit LCD_RW=P2^1;
sbit LCD_EN=P2^2;
sbit SPK=P3^0;
sbit key1=P1^0;
sbit key2=P1^1;
sbit key3=P1^2;
sbit key4=P1^3;
uchar Display_Buffer[16]=" ";
uchar Count,hour=12,min=12,sec=12;
bit flag,H_or_M;
uchar display[]="This is colck";
void _delay_ms(uint x)
{
uchar i;
while(x--)
{
for(i=0;i<120;i++);
}
}
/**********************************************************************
*函數名稱:LCD_Write_Command
*輸 入:uchar cmd
*輸 出:無
*功 能:向LCD1602寫指令
**********************************************************************/
void LCD_Write_Command(uchar cmd)
{
LCD_RS=0;//根據規定,RS和R/W同時為低電平時,可以寫入指令
LCD_RW=0;
LCD_EN=0;//EN置低電平
P0=cmd;//將數據送入P2口,即寫入指令或地址
LCD_EN=1;//EN置高電平
_delay_ms(1);//稍延時,給硬體反應時間
LCD_EN=0;//當EN由高電平跳變成低電平時,液晶模塊開始執行命令
}
/**********************************************************************
*函數名稱:LCD_Write_Data
*輸 入:uchar dat
*輸 出:無
*功 能:向LCD1602寫數據
**********************************************************************/
void LCD_Write_Data(uchar dat)
{
LCD_RS=1;//RS為高電平,RW為低電平時,可以寫入數據
LCD_RW=0;
LCD_EN=0;//EN置低電平
P0=dat;//將數據送入P0口,即將數據寫入液晶模塊
LCD_EN=1;//EN置高電平
_delay_ms(1);//稍延時,給硬體反應時間
LCD_EN=0;//當EN由高電平跳變成低電平時,液晶模塊開始執行命令
}
/**********************************************************************
*函數名稱:Init_LCD
*輸 入:無
*輸 出:無
*功 能:初始化LCD1602
**********************************************************************/
void Init_LCD(void)
{
LCD_Write_Command(0x38);//顯示模式設置:16×2顯示,5×7點陣,8位數據介面
_delay_ms(1);
LCD_Write_Command(0x06);//顯示模式設置:游標右移,字元不移
_delay_ms(1);
LCD_Write_Command(0x0c);//顯示模式設置:顯示開,無游標,游標不閃爍
_delay_ms(1);
LCD_Write_Command(0x01);//清屏幕指令,將以前的顯示內容清除
_delay_ms(1);
}
/**********************************************************************
*函數名稱:LCD_POS
*輸 入:uchar pos
*輸 出:無
*功 能:字元顯示位置
**********************************************************************/
void LCD_POS(uchar pos)
{
LCD_Write_Command(0x80|pos);//顯示位置的確定方法規定為"80H+地址碼x"
}
/**********************************************************************
*函數名稱:Show_String
*輸 入:uchar *str
*輸 出:無
*功 能:LCD1602顯示字元串處理函數
**********************************************************************/
void Show_String(uchar *str)
{
while(*str!='\0')//只要沒有寫到結束標志,就繼續寫
LCD_Write_Data(*str++);//將字元常量寫入LCD,並指向下一個字元
}
void song(void)
{
uchar i,j,k;
for(i=0;i<200;i++)
{
SPK=~SPK;
for(k=0;k<50;k++);
for(j=0;j<50;j++);
}
}
/////lcd1602液晶顯示//////
void Display_Time(uchar Hour,uchar Min,uchar Sec)
{
Display_Buffer[0]=Hour/10+'0';//小時十位
Display_Buffer[1]=Hour%10+'0';//小時個位
Display_Buffer[2]=':';//顯示:號
Display_Buffer[3]=Min/10+'0';//顯示分鍾十位
Display_Buffer[4]=Min%10+'0';//顯示分鍾個位
Display_Buffer[5]=':';//顯示:號
Display_Buffer[6]=Sec/10+'0';//顯示秒十位
Display_Buffer[7]=Sec%10+'0';//顯示秒個位
LCD_POS(0x40);//顯示在液晶第1行第0列
Show_String(Display_Buffer);
}
/////按鍵處理//////
void Set_time(void)
{
flag=0;
if(key1==0||key2==0||key3==0)//若key1,key2,key3其中有鍵按下,則為真
{
TR0=0;//定時器0停止
flag=1;//按鍵標志位為真
}
while(flag)//判斷那一個按鍵按下
{
if(key1==0)//判斷key1是否按下
{
while(!key1);//等待釋放
H_or_M=!H_or_M;//選擇是修改時還是分鍾
}
else if(key2==0)//判斷key2是否被按下
{
while(!key2);//等待釋放
if(H_or_M)//若H_OR_M為真,則修改小時
{
if(++hour==24)//若小時=24,則小時=0
hour=0;//小時加1
}
else//否則修改分鍾
{
if(++min==60)//若分鍾等於60,則分鍾等於0
min=0;//分鍾加1
}
}
else if(key3==0)//判斷key3是否被按下
{
while(!key3);//等待釋放
if(H_or_M)//若H_OR_M為真,則修改小時
{
if(--hour==0xff) //小時減1,若小時等於-1,則小時等於23
hour=23;
}
else//否則修改分鍾
{
if(--min==0xff)//分鍾減1,若分鍾等於-1,則分鍾等於59
min=59;
}
}
else if(key4==0)//判斷key4是否被按下
{
while(!key4);//等待釋放
flag=0;//按鍵標志清零
TR0=1;//定時器0啟動
}
Display_Time(hour,min,sec);//傳H,M,S值顯示到液晶
}
}
void timer0_init(void)//定時器0初始化
{
TMOD=0x01;//定時器0,方式1
ET0=1;//
EA=1;//總中斷允許
TR0=1;//啟動定時器0
TH0=(65535-50000)/256;//裝高8位初值
TL0=(65535-50000)%256;//裝低8位初值
}
void main(void)//主函數
{
//P0=0xff;
P1=0xff;//埠初始化
P3=0xff;
Init_LCD();//液晶初始化
timer0_init();//定時器0初始化
LCD_POS(0);//顯示在液晶第1行第0列
Show_String(display);
while(1)//無限循環
{
Display_Time(hour,min,sec);//液晶顯示時間
//_delay_ms(500);//延時
Set_time();//時間調整
}
}
void timer0() interrupt 1//定時器0中斷
{
TH0=(65535-50000)/256;//重裝定時器0高8位
TL0=(65535-50000)%256;//重裝定時器0低8位
Count++;//計數加1
if(Count==20)//如果COUNT等於20
{
Count=0;//計數清零
sec++;//秒加1
if(sec==60)//判斷秒是否等於60
{
sec=0;//秒清零
min++;//分鍾加1
if(min==60)//判斷分鍾是否等於60
{
min=0;//若等於60,則清零分鍾
hour++;//小時加1
if(hour==24)//判斷小時是否等於24
{
hour=0;//若小時等於24,則清零小時,分鍾,秒
min=0;
sec=0;
}
song();
}
}
}
}