标题:
12864-ds1302-ds18b20-单片机万年历程序
[打印本页]
作者:
51hei人人
时间:
2016-3-12 21:21
标题:
12864-ds1302-ds18b20-单片机万年历程序
#include<reg52.h>
#include<intrins.h>
#define SoundSpace 3/4
unsigned char sec,min,hour,day,month,year,year1,cen,week; //秒,分,小时,公历日期,月份,年份,世纪,星期
unsigned char LunarMonth,LunarDay,LunarYear; //阴历日期,月份,年份
bit c_moon; //大小月标志位
bit cenbit=0; //世纪标志,为1,则表示20世纪,为0,则表示21世纪
bit w; //调时状态标志位
unsigned char next;
/**********定义LCD12864的数据线和相关函数*************/
sbit LCD_RS=P2^6; //模式位,低电平输入指令,高电平输入数据
sbit LCD_RW=P2^5; //读写位,低电平读,高电平写
sbit LCD_E=P2^7; //LCD12864使能位,低电平无效,高电平使能
sbit PSB=P3^2;
#define Busy 0x80
#define LCD_Data P0 //LCD12864的8位数据总线,单片机的P0端口
void WriteDataLCD(unsigned char WDLCD); //给LCD12864写数据
void WriteCommandLCD(unsigned char WCLCD); //给LCD12864写指令
void LCDInit(void); //LCD12864初始化
void LCDClear(void); //LCD12864清屏
void CheckBusy(void); //忙检测
void LCDSendWord(unsigned char *p); //向LCD发送一个字符串
void LCDTestWord(bit i,unsigned char word);
void DisplaySec(void); //在LCD上显示秒钟
void DisplayMin(void); //在LCD上显示分钟
void DisplayHour(void); //在LCD上显示小时
void DisplayDay(void); //在LCD上显示日期
void DisplayYear(void); //在LCD上显示年份
void DisplayMonth(void); //在LCD上显示月份
void DisplayWeek(void); //在LCD上显示星期
void Holidays(void); //在LCD上显示节日
/*********定义时间芯片DS1302的数据线及相关函数***********/
sbit DS1302_CLK=P3^6; //DS1302的时钟信号线
sbit DS1302_IO=P3^0; //DS1302的数据端口线
sbit DS1302_RST=P3^5; //DS1302的片选信号线
void WriteDs1302byte(unsigned char temp); //给DS1302写一个字节
void WriteDs1302(unsigned char address,unsigned char dat); //给DS1302写入时间,先确定地址,再确定要写入的数据
unsigned char ReadDs1302(unsigned char address); //读取DS1302的数据
void InitDS1302();
/**********定义温度传感器DS18B20的数据线和相关函数*************/
sbit DS18B20=P3^7; //DS18B20的数据线
int temp;
void DS18B20Init(void); //DS18B20初始化函数
int GetTemp(void);
void TempWriteByte(unsigned char dat);
unsigned char TempRead(void);
bit TempReadBit(void);
void delayb(unsigned int count);
void TempChange(void);
void Conversion(bit cen_m,unsigned char year,unsigned char month,unsigned char day);
bit GetMoonDay(unsigned char month_p,unsigned int TableAddr);
void DisplayShengXiao(void);
void DelayMs(unsigned int a);
void Delay(unsigned char num);
/**********定义开关按键,及蜂鸣器的数据线************/
sbit SetKey=P1^0; //按键功能:设置
sbit SureKey=P1^1; //按键功能:确认
sbit PlusKey=P1^2; //按键功能:加
sbit ReduceKey=P1^3; //按键功能:减
void Key(void);
#define Fosc 12000000 //定义晶振频率12000000HZ
#define jiepai 3/4 //定义普通音符演奏的长度分率,//每4分音符间隔
sbit Speaker=P1^5; //定义输出管脚
unsigned int code FreTab[12]={262,277,294,311,330,349,369,392,415,440,466,494}; //C调歌曲12个半音的频率
unsigned char code PositTab[7]={0,2,4,5,7,9,11}; //1~7在频率表中的位置
unsigned char code LengthTab[7]={1,2,4,8,16,32,64};
unsigned char SoundTempTH0,SoundTempTL0; //音符定时器初值暂存
unsigned char SoundTempTH1,SoundTempTL1; //音长定时器初值暂存
void SpeakerDiDi(void);
void SpeakerDiDi(void)
{
unsigned char i;
for(i=0;i<3;i++)
{
Speaker=0;
DelayMs(100);
Speaker=1;
DelayMs(100);
}
DelayMs(500);
for(i=0;i<3;i++)
{
Speaker=0;
DelayMs(100);
Speaker=1;
DelayMs(100);
}
DelayMs(500);
for(i=0;i<2;i++)
{
Speaker=0;
DelayMs(500);
Speaker=1;
DelayMs(100);
}
}
void InitialSound(void)
{
Speaker=1;
SoundTempTH1=(65535-(1/1200)*Fosc)/256; //计算TL1应装入的初值 (10ms的初装值)
SoundTempTL1=(65535-(1/1200)*Fosc)%256; //计算TH1应装入的初值
TH1=SoundTempTH1; //装入初值
TL1=SoundTempTL1;
TMOD|=0x11; //定时器1、2都工作在定时器模式,工作方式1
ET0=1; //定时器0开中断
ET1=0; //定时器1关中断
TR0=0; //不启动定时器
TR1=0; //不启动定时器
EA=1; //开启CPU中断
}
void Speakertimer(void) interrupt 1 //音符发生中断
{
Speaker=!Speaker; //取反
TH0=SoundTempTH0; //定时器0重新装初值
TL0=SoundTempTL0;
}
void PlayMusic(unsigned char *SoundName,unsigned char diaohao,unsigned shengjiang,unsigned int Speed)
//SoundName为演奏歌曲歌名 diaohao是指乐曲升多少个半音演奏
//shengjiang 1:降八度, 2:不升不降, 3:升八度; Speed歌曲演奏速度
{
unsigned int NewFreTab[12]; //新的频率表
unsigned char i,j;
unsigned int Point,yinfuchang,yipai,LDiv1,LDiv2,sifenyifu,CurrentFre,TempCounter,SoundLength;
//Point 指针索引值 LDiv 音符演奏的长度(多少个10ms) yipai 1分音符的长度(几个10ms)即一个节拍
//sifenyifu 4分音符的长度 CurrentFre 查出对应音符的频率 SoundLength歌曲长度 TempCounter计算计数器初值
unsigned char yindiao,length,yinfu,shengban,gaodi,SLen,leixing,fudian;
//yindiao音调 length音长 yinfu音符 gaodi高低音 shengban是否升半 leixing音符类型(0普通1连音2顿音)
for(i=0;i<12;i++) // 根据调号及升降八度来生成新的频率表
{
j=i+diaohao;
if(j>11)
{
j=j-12;
NewFreTab[i]=FreTab[j]*2; //频率翻倍速
}
else
NewFreTab[i]=FreTab[j];
if(shengjiang==1) NewFreTab[i]>>=2; //如果是降调 则频率除以2
else if(shengjiang==3) NewFreTab[i]<<=2; //如果是升调 则频率翻倍速
}
SoundLength=0;
while(SoundName[SoundLength]!=0x00) //计算歌曲长度 以0X00结尾
{
SoundLength+=2;
}
Point=0;
yindiao=SoundName[Point]; //第一个字节为音符音调
length=SoundName[Point+1]; //第二个字节为音符时值
yipai=12000/Speed; //算出一个节拍的长度(单位是10ms)
sifenyifu=yipai/4; //算出4分音符的长度
sifenyifu=sifenyifu-sifenyifu*jiepai; //普通音最长间隔标准
TR0=0;
TR1=1; //启动定时器1
while(Point<SoundLength)
{
yinfu=yindiao%10; //个位,1--7七个音符
gaodi=yindiao/10%10; //十位,高低音
shengban=yindiao/100; //百位,是否升半
CurrentFre=NewFreTab[PositTab[yinfu-1]+shengban]; //查出对应音符的频率
if(yinfu!=0)
{
if (gaodi==1) CurrentFre>>=2; //低音,频率除以2
if (gaodi==3) CurrentFre<<=2; //高音, 频率翻倍速
TempCounter=65536-(50000/CurrentFre)*10/(12000000/Fosc);//计算计数器初值
SoundTempTH0=TempCounter/256;
SoundTempTL0=TempCounter%256;
TH0=SoundTempTH0;
TL0=SoundTempTL0+12; //加12是对中断延时的补偿
}
SLen=LengthTab[length%10]; //算出是几分音符
leixing=length/10%10; //算出音符类型(0普通1连音2顿音)
fudian=length/100;
yinfuchang=yipai/SLen; //算出连音音符演奏的长度(多少个10ms)
if (fudian==1)
yinfuchang=yinfuchang+yinfuchang/2;
if(leixing!=1)
if(leixing==0) //算出普通音符的演奏长度
if (SLen<=4)
LDiv1=yinfuchang-sifenyifu;
else
LDiv1=yinfuchang*jiepai;
else
LDiv1=yinfuchang/2; //算出顿音的演奏长度
else
LDiv1=yinfuchang;
if(yinfu==0) LDiv1=0;
LDiv2=yinfuchang-LDiv1; //算出不发音的长度
if (yinfu!=0)
{
TR0=1;
for(i=LDiv1;i>0;i--) //发规定长度的音
{
while(TF1==0);
TH1=SoundTempTH1;
TL1=SoundTempTL1;
TF1=0;
}
}
if(LDiv2!=0)
{
TR0=0; Speaker=0;
for(i=LDiv2;i>0;i--) //音符间的间隔
{
while(TF1==0);
TH1=SoundTempTH1;
TL1=SoundTempTL1;
TF1=0;
}
}
Point+=2;
yindiao=SoundName[Point];
length=SoundName[Point+1];
}
Speaker=1;
}
//**************************************************************************
unsigned char code HappyBirthday[]=
{//生日歌
0x19,0x03, 0x19,0x03, 0x1A,0x02, 0x19,0x02, 0x1F,0x02,
0x1B,0x01, 0x19,0x03, 0x19,0x03, 0x1A,0x02, 0x19,0x02,
0x20,0x02, 0x1F,0x01, 0x19,0x03, 0x19,0x03, 0x23,0x02,
0x21,0x02, 0x1F,0x02, 0x1B,0x0C, 0x1A,0x15, 0x22,0x03,
0x22,0x03, 0x21,0x02, 0x1F,0x02, 0x20,0x02, 0x1F,0x15,
0x00,0x00
};
unsigned char code Butterfly[]=
{
0x17,0x03, 0x16,0x03, 0x17,0x01, 0x16,0x03, 0x17,0x03,
0x16,0x03, 0x15,0x01, 0x10,0x03, 0x15,0x03, 0x16,0x02,
0x16,0x0D, 0x17,0x03, 0x16,0x03, 0x15,0x03, 0x10,0x03,
0x10,0x0E, 0x15,0x04, 0x0F,0x01, 0x17,0x03, 0x16,0x03,
0x17,0x01, 0x16,0x03, 0x17,0x03, 0x16,0x03, 0x15,0x01,
0x10,0x03, 0x15,0x03, 0x16,0x02, 0x16,0x0D, 0x17,0x03,
0x16,0x03, 0x15,0x03, 0x10,0x03, 0x15,0x03, 0x16,0x01,
0x17,0x03, 0x16,0x03, 0x17,0x01, 0x16,0x03, 0x17,0x03,
0x16,0x03, 0x15,0x01, 0x10,0x03, 0x15,0x03, 0x16,0x02,
0x16,0x0D, 0x17,0x03, 0x16,0x03, 0x15,0x03, 0x10,0x03,
0x10,0x0E, 0x15,0x04, 0x0F,0x01, 0x17,0x03, 0x19,0x03,
0x19,0x01, 0x19,0x03, 0x1A,0x03, 0x19,0x03, 0x17,0x01,
0x16,0x03, 0x16,0x03, 0x16,0x02, 0x16,0x0D, 0x17,0x03,
0x16,0x03, 0x15,0x03, 0x10,0x03, 0x10,0x0D, 0x15,0x00,
0x19,0x03, 0x19,0x03, 0x1A,0x03, 0x1F,0x03, 0x1B,0x03,
0x1B,0x03, 0x1A,0x03, 0x17,0x0D, 0x16,0x03, 0x16,0x03,
0x16,0x0D, 0x17,0x01, 0x17,0x03, 0x17,0x03, 0x19,0x03,
0x1A,0x02, 0x1A,0x02, 0x10,0x03, 0x17,0x0D, 0x16,0x03,
0x16,0x01, 0x17,0x03, 0x19,0x03, 0x19,0x03, 0x17,0x03,
0x19,0x02, 0x1F,0x02, 0x1B,0x03, 0x1A,0x03, 0x1A,0x0E,
0x1B,0x04, 0x17,0x02, 0x1A,0x03, 0x1A,0x03, 0x1A,0x0E,
0x1B,0x04, 0x1A,0x03, 0x19,0x03, 0x17,0x03, 0x16,0x03,
0x17,0x0D, 0x16,0x03, 0x17,0x03, 0x19,0x01, 0x19,0x03,
0x19,0x03, 0x1A,0x03, 0x1F,0x03, 0x1B,0x03, 0x1B,0x03,
0x1A,0x03, 0x17,0x0D, 0x16,0x03, 0x16,0x03, 0x16,0x03,
0x17,0x01, 0x17,0x03, 0x17,0x03, 0x19,0x03, 0x1A,0x02,
0x1A,0x02, 0x10,0x03, 0x17,0x0D, 0x16,0x03, 0x16,0x01,
0x17,0x03, 0x19,0x03, 0x19,0x03, 0x17,0x03, 0x19,0x03,
0x1F,0x02, 0x1B,0x03, 0x1A,0x03, 0x1A,0x0E, 0x1B,0x04,
0x17,0x02, 0x1A,0x03, 0x1A,0x03, 0x1A,0x0E, 0x1B,0x04,
0x17,0x16, 0x1A,0x03, 0x1A,0x03, 0x1A,0x0E, 0x1B,0x04,
0x1A,0x03, 0x19,0x03, 0x17,0x03, 0x16,0x03, 0x0F,0x02,
0x10,0x03, 0x15,0x00, 0x00,0x00
};
/*音乐歌谱每个音符由两个字节表示,第一个字节表示音高,第二个字节表示音长
音高由三位数字组成:个位是表示 1~7 这七个音符
十位是表示音符所在的音区:1-低音,2-中音,3-高音;百位表示这个音符是否要升半音: 0-不升,1-升半音。
音长最多由三位数字组成:
个位表示音符的时值,其对应关系是:
数值(n): |0 |1 |2 |3 | 4 | 5 | 6 |
几分音符: |1 |2 |4 |8 |16 |32 |64
十位表示音符的演奏效果 (0-2): 0-普通,1-连音,2-顿音 百位是符点位: 0-无符点,1-有符点
阳历对应的阴历数据,每年三字节,
格式第一字节BIT7-4位表示闰月月份,为0,则无闰月,BIT3-0对应阴历第1-4月的大小,
第二字节BIT7-0对应阴历第5-12月大小,第三字节BIT7表示阴历第13月大小
月分对应的位为1,表示农历月大(30天)为0表示小(29天)
第三字节BIT6-5表示春节的公历月份,BIT4-0表示春节公历日期
*/
code unsigned char YearCode[597]=
{
0x04,0xAe,0x53, //1901 0
0x0A,0x57,0x48, //1902 3
0x55,0x26,0xBd, //1903 6
0x0d,0x26,0x50, //1904 9
0x0d,0x95,0x44, //1905 12
0x46,0xAA,0xB9, //1906 15
0x05,0x6A,0x4d, //1907 18
0x09,0xAd,0x42, //1908 21
0x24,0xAe,0xB6, //1909
0x04,0xAe,0x4A, //1910
0x6A,0x4d,0xBe, //1911
0x0A,0x4d,0x52, //1912
0x0d,0x25,0x46, //1913
0x5d,0x52,0xBA, //1914
0x0B,0x54,0x4e, //1915
0x0d,0x6A,0x43, //1916
0x29,0x6d,0x37, //1917
0x09,0x5B,0x4B, //1918
0x74,0x9B,0xC1, //1919
0x04,0x97,0x54, //1920
0x0A,0x4B,0x48, //1921
0x5B,0x25,0xBC, //1922
0x06,0xA5,0x50, //1923
0x06,0xd4,0x45, //1924
0x4A,0xdA,0xB8, //1925
0x02,0xB6,0x4d, //1926
0x09,0x57,0x42, //1927
0x24,0x97,0xB7, //1928
0x04,0x97,0x4A, //1929
0x66,0x4B,0x3e, //1930
0x0d,0x4A,0x51, //1931
0x0e,0xA5,0x46, //1932
0x56,0xd4,0xBA, //1933
0x05,0xAd,0x4e, //1934
0x02,0xB6,0x44, //1935
0x39,0x37,0x38, //1936
0x09,0x2e,0x4B, //1937
0x7C,0x96,0xBf, //1938
0x0C,0x95,0x53, //1939
0x0d,0x4A,0x48, //1940
0x6d,0xA5,0x3B, //1941
0x0B,0x55,0x4f, //1942
0x05,0x6A,0x45, //1943
0x4A,0xAd,0xB9, //1944
0x02,0x5d,0x4d, //1945
0x09,0x2d,0x42, //1946
0x2C,0x95,0xB6, //1947
0x0A,0x95,0x4A, //1948
0x7B,0x4A,0xBd, //1949
0x06,0xCA,0x51, //1950
0x0B,0x55,0x46, //1951
0x55,0x5A,0xBB, //1952
0x04,0xdA,0x4e, //1953
0x0A,0x5B,0x43, //1954
0x35,0x2B,0xB8, //1955
0x05,0x2B,0x4C, //1956
0x8A,0x95,0x3f, //1957
0x0e,0x95,0x52, //1958
0x06,0xAA,0x48, //1959
0x7A,0xd5,0x3C, //1960
0x0A,0xB5,0x4f, //1961
0x04,0xB6,0x45, //1962
0x4A,0x57,0x39, //1963
0x0A,0x57,0x4d, //1964
0x05,0x26,0x42, //1965
0x3e,0x93,0x35, //1966
0x0d,0x95,0x49, //1967
0x75,0xAA,0xBe, //1968
0x05,0x6A,0x51, //1969
0x09,0x6d,0x46, //1970
0x54,0xAe,0xBB, //1971
0x04,0xAd,0x4f, //1972
0x0A,0x4d,0x43, //1973
0x4d,0x26,0xB7, //1974
0x0d,0x25,0x4B, //1975
0x8d,0x52,0xBf, //1976
0x0B,0x54,0x52, //1977
0x0B,0x6A,0x47, //1978
0x69,0x6d,0x3C, //1979
0x09,0x5B,0x50, //1980
0x04,0x9B,0x45, //1981
0x4A,0x4B,0xB9, //1982
0x0A,0x4B,0x4d, //1983
0xAB,0x25,0xC2, //1984
0x06,0xA5,0x54, //1985
0x06,0xd4,0x49, //1986
0x6A,0xdA,0x3d, //1987
0x0A,0xB6,0x51, //1988
0x09,0x37,0x46, //1989
0x54,0x97,0xBB, //1990
0x04,0x97,0x4f, //1991
0x06,0x4B,0x44, //1992
0x36,0xA5,0x37, //1993
0x0e,0xA5,0x4A, //1994
0x86,0xB2,0xBf, //1995
0x05,0xAC,0x53, //1996
0x0A,0xB6,0x47, //1997
0x59,0x36,0xBC, //1998
0x09,0x2e,0x50, //1999 294
0x0C,0x96,0x45, //2000 297
0x4d,0x4A,0xB8, //2001 300
0x0d,0x4A,0x4C, //2002 303
0x0d,0xA5,0x41, //2003 306
0x25,0xAA,0xB6, //2004 309
0x05,0x6A,0x49, //2005 312
0x7A,0xAd,0xBd, //2006 315
0x02,0x5d,0x52, //2007 318
0x09,0x2d,0x47, //2008 321
0x5C,0x95,0xBA, //2009 324
0x0A,0x95,0x4e, //2010 327
0x0B,0x4A,0x43, //2011
0x4B,0x55,0x37, //2012
0x0A,0xd5,0x4A, //2013
0x95,0x5A,0xBf, //2014
0x04,0xBA,0x53, //2015
0x0A,0x5B,0x48, //2016
0x65,0x2B,0xBC, //2017
0x05,0x2B,0x50, //2018
0x0A,0x93,0x45, //2019
0x47,0x4A,0xB9, //2020
0x06,0xAA,0x4C, //2021
0x0A,0xd5,0x41, //2022
0x24,0xdA,0xB6, //2023
0x04,0xB6,0x4A, //2024
0x69,0x57,0x3d, //2025
0x0A,0x4e,0x51, //2026
0x0d,0x26,0x46, //2027
0x5e,0x93,0x3A, //2028
0x0d,0x53,0x4d, //2029
0x05,0xAA,0x43, //2030
0x36,0xB5,0x37, //2031
0x09,0x6d,0x4B, //2032
0xB4,0xAe,0xBf, //2033
0x04,0xAd,0x53, //2034
0x0A,0x4d,0x48, //2035
0x6d,0x25,0xBC, //2036
0x0d,0x25,0x4f, //2037
0x0d,0x52,0x44, //2038
0x5d,0xAA,0x38, //2039
0x0B,0x5A,0x4C, //2040
0x05,0x6d,0x41, //2041
0x24,0xAd,0xB6, //2042
0x04,0x9B,0x4A, //2043
0x7A,0x4B,0xBe, //2044
0x0A,0x4B,0x51, //2045
0x0A,0xA5,0x46, //2046
0x5B,0x52,0xBA, //2047
0x06,0xd2,0x4e, //2048
0x0A,0xdA,0x42, //2049
0x35,0x5B,0x37, //2050
0x09,0x37,0x4B, //2051
0x84,0x97,0xC1, //2052
0x04,0x97,0x53, //2053
0x06,0x4B,0x48, //2054
0x66,0xA5,0x3C, //2055
0x0e,0xA5,0x4f, //2056
0x06,0xB2,0x44, //2057
0x4A,0xB6,0x38, //2058
0x0A,0xAe,0x4C, //2059
0x09,0x2e,0x42, //2060
0x3C,0x97,0x35, //2061
0x0C,0x96,0x49, //2062
0x7d,0x4A,0xBd, //2063
0x0d,0x4A,0x51, //2064
0x0d,0xA5,0x45, //2065
0x55,0xAA,0xBA, //2066
0x05,0x6A,0x4e, //2067
0x0A,0x6d,0x43, //2068
0x45,0x2e,0xB7, //2069
0x05,0x2d,0x4B, //2070
0x8A,0x95,0xBf, //2071
0x0A,0x95,0x53, //2072
0x0B,0x4A,0x47, //2073
0x6B,0x55,0x3B, //2074
0x0A,0xd5,0x4f, //2075
0x05,0x5A,0x45, //2076
0x4A,0x5d,0x38, //2077
0x0A,0x5B,0x4C, //2078
0x05,0x2B,0x42, //2079
0x3A,0x93,0xB6, //2080
0x06,0x93,0x49, //2081
0x77,0x29,0xBd, //2082
0x06,0xAA,0x51, //2083
0x0A,0xd5,0x46, //2084
0x54,0xdA,0xBA, //2085
0x04,0xB6,0x4e, //2086
0x0A,0x57,0x43, //2087
0x45,0x27,0x38, //2088
0x0d,0x26,0x4A, //2089
0x8e,0x93,0x3e, //2090
0x0d,0x52,0x52, //2091
0x0d,0xAA,0x47, //2092
0x66,0xB5,0x3B, //2093
0x05,0x6d,0x4f, //2094
0x04,0xAe,0x45, //2095
0x4A,0x4e,0xB9, //2096
0x0A,0x4d,0x4C, //2097
0x0d,0x15,0x41, //2098
0x2d,0x92,0xB5, //2099
};
/******************忙检测函数***************/
void CheckBusy(void)
{
LCD_RS=0;
LCD_RW=1;
LCD_E=1;
LCD_Data=0xff;
while((LCD_Data&0x80)==0x80);
LCD_E=0;
}
/**********************给LCD写入数据*****************/
void WriteDataLCD(unsigned char WDLCD)
{
CheckBusy(); //检测忙
LCD_RS = 1; //RS为高电平,DB7----DB0为数据
LCD_RW = 0; //RW为低电平,E从高电平到低电平,则是把DB7----DB0的数据写到DR或者IR
LCD_E = 1;
LCD_Data = WDLCD; //传送数据WDLCD
Delay(5);
LCD_E = 0; //E从 高电平 到 低电平
Delay(5);
}
/******************给LCD写入指令**********************/
void WriteCommandLCD(unsigned char WCLCD) //BuysC为0时忽略忙检测
{
CheckBusy(); //检测忙
LCD_RS = 0; //RS为低,DB7----DB0为指令
LCD_RW = 0; //RW为低,E从高电平到低电平,则是把DB7----DB0的数据写到DR或者IR
LCD_E = 1;
LCD_Data = WCLCD; //传送数据
Delay(5);
LCD_E = 0; //E从 高电平到低电平
Delay(5);
}
/***************LCD初始化******************/
void LCDInit(void)
{
WriteCommandLCD(0x30); //显示模式设置,开始要求每次检测忙信号
WriteCommandLCD(0x01); //显示清屏
WriteCommandLCD(0x06); // 显示光标移动设置
WriteCommandLCD(0x0C); // 显示开,无游标,不反白
}
/********************清屏***************************/
void LCDClear(void)
{
WriteCommandLCD(0x01); //显示清屏
WriteCommandLCD(0x34); // 显示光标移动设置
WriteCommandLCD(0x30); // 显示开及光标设置
}
/*****************************************/
void LCDSendWord(unsigned char *p) //向LCD发送一个字符串,
{
while(*p>0) //比如void LCDSendWord('你好');就是让LCD显示"你好"
{
WriteDataLCD(*p);
p++;
}
}
/************写数据或者指令***************/
void LCDTestWord(bit i,unsigned char word)
{
if(i==0)
{
WriteCommandLCD(word); //i=0;则写入指令
}
else
{
WriteDataLCD(word); //i=1;则写入数据
}
}
void DisplayYear(void) //往LCD上填写 年 数据
{
year=ReadDs1302(0x8d); //从1302的0X8D处读出年数据
LCDTestWord(0,0x81); //写指令 0X81 在第一行第二个字符位置显示 年 数据
LCDTestWord(1,(year/16)+0x30); //写数据
LCDTestWord(1,year%16+0x30); //写数据
LCDTestWord(0,0x82); //写指令 第一行第三个字符位置
LCDSendWord("年"); //显示 年 LCD DDRAM第一行地址为80-87,第二行为90-97,第三行为88-8F,第四行为98-9F
DisplayShengXiao();
}
void DisplayMonth(void) //往LCD上填写 月 数据
{
month=ReadDs1302(0x89); //从1302中读取月份数据
LCDTestWord(0,0x83); //写命令
if(month/16!=0)
{
LCDTestWord(1,(month/16)+0x30);//写数据
}
else
{
LCDTestWord(1,0x20); //写数据
}
LCDTestWord(1,month%16+0x30); //写数据
LCDTestWord(0,0x84); //写指令
LCDSendWord("月"); //显示 月
DisplayShengXiao();
}
void DisplayWeek(void) //往LCD上填写 星期 数据
{
week=(ReadDs1302(0x8b))%16; //从1302中读取星期数据
LCDTestWord(0,0x90);
LCDSendWord("星期");
LCDTestWord(0,0x92);
if(week==7) {LCDSendWord("日");}
if(week==6) {LCDSendWord("六");}
if(week==5) {LCDSendWord("五");}
if(week==4) {LCDSendWord("四");}
if(week==3) {LCDSendWord("叁");}
if(week==2) {LCDSendWord("二");}
if(week==1) {LCDSendWord("一");} //显示星期一到星期日
}
void DisplayDay(void) //往LCD上填写 日期 数据
{
day=ReadDs1302(0x87); //从1302中读取日期数据
LCDTestWord(0,0x85);
if(day/16!=0)
{ LCDTestWord(1,(day/16)+0x30); }
else
{ LCDTestWord(1,0x20);}
LCDTestWord(1,day%16+0x30);
LCDTestWord(0,0x86);
LCDSendWord("日");
DisplayShengXiao();
}
void DisplayHour(void) //往LCD上填写 小时数据
{
hour=ReadDs1302(0x85);
LCDTestWord(0,0x88);
LCDTestWord(1,(hour/16)+0x30);
LCDTestWord(1,hour%16+0x30);
}
void DisplayMin(void) //往LCD上填写分钟 数据
{
min=ReadDs1302(0x83);
LCDTestWord(0,0x89);
LCDTestWord(1,0x3a);
LCDTestWord(1,(min/16)+0x30);
LCDTestWord(1,min%16+0x30);
LCDTestWord(1,0x3a);
}
void DisplaySec(void) //住LCD上填写 秒钟 和温度 数据
{
unsigned char i=0;
unsigned int a=0,b=0,c=0;
sec=ReadDs1302(0x81);
LCDTestWord(0,0x8b);
LCDTestWord(1,(sec/16)+0x30);
LCDTestWord(1,sec%16+0x30);
}
void DisplayTemp(void)
{
unsigned int i;
unsigned char a,b,c;
WriteCommandLCD(0x8c);
LCDTestWord(0,0x8d);
TempChange();
i=GetTemp();
a=i/100;
LCDTestWord(1,a+0x30);
b=i/10-a*10;
LCDTestWord(1,b+0x30);
LCDTestWord(1,0x2e);
c=i-a*100-b*10;
LCDTestWord(1,c+0x30);
LCDSendWord("℃");
}
/***************************写入操作*********************/
void WriteDs1302Byte(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++) //循环8次 写入数据
{
DS1302_CLK=0;
DS1302_IO=temp&0x01; //每次传输低字节
temp>>=1; //右移一位
DS1302_CLK=1;
}
}
/***********************************写入数据*****************************/
void WriteDs1302( unsigned char address,unsigned char dat ) //先写地址,再写数据
{
DS1302_RST=0;
_nop_();
DS1302_CLK=0;
_nop_();
DS1302_RST=1;
_nop_(); //启动
WriteDs1302Byte(address); //发送地址
WriteDs1302Byte(dat); //发送数据
DS1302_RST=0; //恢复
}
/****************************************************************************/
unsigned char ReadDs1302(unsigned char address) //先送地址,再读数据
{
unsigned char i,temp=0x00;
DS1302_RST=0;
_nop_();
DS1302_CLK=0;
_nop_();
DS1302_RST=1;
_nop_();
WriteDs1302Byte(address); //送地址函数
for (i=0;i<8;i++) //循环8次 读取数据
{
DS1302_CLK=1;
_nop_();
if(DS1302_IO)
temp|=0x80; //每次传输低字节
DS1302_CLK=0;
temp>>=1; //右移一位
}
DS1302_RST=0;
_nop_();
DS1302_CLK=1;
DS1302_IO=0;
return (temp); //返回
}
/*****************DS1302初始化********************/
void InitDS1302() //DS1302中秒,分,时,日期,月份,星期,年的地址分别是0x80,0x82,0x84,0x86,0x88,0x8a,0x8c
{ //初始化写入的时间是2010年4月1日15点整,星期六
WriteDs1302(0x8e,0x00); //控制命令,WP位为0,允许写操作 控制位地址是0x8e
DelayMs(5);
WriteDs1302(0x8c,0x10); //写入年份10年
DelayMs(5);
WriteDs1302(0x8a,0x04); //写入星期6
DelayMs(5);
WriteDs1302(0x88,0x05); //定入月分 5月
DelayMs(5);
WriteDs1302(0x86,0x01); //写入日期 1日
DelayMs(5);
WriteDs1302(0x84,0x09); //写入小时 9点
DelayMs(5);
WriteDs1302(0x82,0x59); //写入分钟 59分
DelayMs(5);
WriteDs1302(0x80,0x30); //写入秒 30秒
DelayMs(5);
WriteDs1302(0x8e,0x80); //控制命令,WP为1,禁止写操作
}
/*************************************************************************/
void delayb(unsigned int count) //delay
{
unsigned char i;
while(count)
{
i=200;
while(i>0)
i--;
count--;
}
}
void DS18B20Init(void) //DS18B20初始化
{
unsigned int i;
DS18B20=0;
i=103;
while(i>0)i--;
DS18B20=1;
i=4;
while(i>0)i--;
}
bit TempReadBit(void) // 读一位
{
unsigned int i;
bit dat;
DS18B20=0;i++; //小延时一下
DS18B20=1;i++;i++;
dat=DS18B20;
i=8;while(i>0)i--;
return (dat);
}
unsigned char TempRead(void) //读一个字节
{
unsigned char i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=TempReadBit();
dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里
}
return(dat); //将一个字节数据返回
}
void TempWriteByte(unsigned char dat)
{ //写一个字节到DS18B20里
unsigned int i;
unsigned char j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) // 写1部分
{
DS18B20=0;
i++;i++;
DS18B20=1;
i=8;while(i>0)i--;
}
else
{
DS18B20=0; //写0部分
i=8;while(i>0)i--;
DS18B20=1;
i++;i++;
}
}
}
void TempChange(void) //发送温度转换命令
{
DS18B20Init(); //初始化DS18B20
delayb(1); //延时
TempWriteByte(0xcc); // 跳过序列号命令
TempWriteByte(0x44); //发送温度转换命令
}
int GetTemp() //获得温度
{
float tt;
unsigned char a,b;
DS18B20Init();
delayb(1);
TempWriteByte(0xcc);
TempWriteByte(0xbe); //发送读取数据命令
a=TempRead(); //连续读两个字节数据
b=TempRead();
temp=b;
temp<<=8;
temp=temp|a; //两字节合成一个整型变量。
tt=temp*0.0625; //得到真实十进制温度值,因为DS18B20 可以精确到0.0625度,所以读回数据的最低位代表的是0.0625度。
temp=tt*10+0.5; //放大十倍,这样做的目的将小数点后第一位 也转换为可显示数字,同时进行一个四舍五入操作。
return temp; //返回温度值
}
code unsigned char DayCode1[9]={0x00,0x1f,0x3b,0x5a,0x78,0x97,0xb5,0xd4,0xf3};
code unsigned int DayCode2[3]={0x111,0x130,0x14e};
//计算公历日离当年元旦的天数,为了减少运算,用了两个表 DayCode1[9],DayCode2[3]
//如果公历月在九月或前,天数会少于0xff,用表DayCode1[9],在九月后,天数大于0xff,用表DayCode2[3]
//如输入公历日为8月10日,则公历日离元旦天数为DayCode1[8-1]+10-1,如输入公历日为11月10日,则公历日离元旦天数为DayCode2[11-10]+10-1
/*读取数据表中农历月的大月或小月,如果该月为大返回1,为小返回0*/
bit GetMoonDay(unsigned char LunarMonth,unsigned int TableAddr)
{
unsigned char temp;
switch (LunarMonth) //LunarMonth指向农历月份
{
case 1:
{
temp=YearCode[TableAddr]&0x08; //1月,对应年份表里第一字节的BIT3位,如果是1,则月大,如果是0,则月小
if (temp==0) return(0); //为0,月小
else return(1); //为1,月大
}
case 2:
{
temp=YearCode[TableAddr]&0x04; //2月,对应年份表里第一字节的BIT2位,如果是1,则月大,如果是0,则月小
if (temp==0) return(0); //为0,月小
else return(1); //为1,月大
}
case 3:
{
temp=YearCode[TableAddr]&0x02; //3月,对应第一字节的BIT1位,如果是1,则月大,如果是0,则月小
if (temp==0) return(0); //为0,月小
else return(1); //为1,月大
}
case 4:
{
temp=YearCode[TableAddr]&0x01; //1月,对应第一字节的BIT0位,如果是1,则月大,如果是0,则月小
if (temp==0) return(0);
else return(1);
}
case 5:
{
temp=YearCode[TableAddr+1]&0x80; //5月,对应第二字节的BIT7位,如果是1,则月大,如果是0,则月小
if (temp==0) return(0);
else return(1);
}
case 6:
{
temp=YearCode[TableAddr+1]&0x40; //6月,对应第二字节的BIT6位,如果是1,则月大,如果是0,则月小
if (temp==0) return(0);
else return(1);
}
case 7:
{
temp=YearCode[TableAddr+1]&0x20; //7月,对应第二字节的BIT5位,如果是1,则月大,如果是0,则月小
if (temp==0) return(0);
else return(1);
}
case 8:
{
temp=YearCode[TableAddr+1]&0x10; //8月,对应第二字节的BIT4位,如果是1,则月大,如果是0,则月小
if (temp==0) return(0);
else return(1);
}
case 9:
{
temp=YearCode[TableAddr+1]&0x08; //9月,对应第二字节的BIT3位,如果是1,则月大,如果是0,则月小
if (temp==0) return(0);
else return(1);
}
case 10:
{
temp=YearCode[TableAddr+1]&0x04; //10月,对应第二字节的BIT2位,如果是1,则月大,如果是0,则月小
if (temp==0) return(0);
else return(1);
}
case 11:
{
temp=YearCode[TableAddr+1]&0x02; //11月,对应第二字节的BIT1位,如果是1,则月大,如果是0,则月小
if (temp==0) return(0);
else return(1);
}
case 12:
{
temp=YearCode[TableAddr+1]&0x01; //12月,对应第二字节的BIT0位,如果是1,则月大,如果是0,则月小
if (temp==0) return(0);
else return(1);
}
case 13:
{
temp=YearCode[TableAddr+2]&0x80; //13月,对应第三字节的BIT7位,如果是1,则月大,如果是0,则月小
if (temp==0) return(0);
else return(1);
}
}
}
void Conversion(bit cenbit,unsigned char year,unsigned char month,unsigned char day)
//cenbit=0为21世纪,cenbit=1为20世纪,输入输出数据均为BCD数据
{
unsigned char temp1,temp2,temp3,MonthP;//temp3,temp4分别表示春节距元旦的天数,公历日离元旦的天数
unsigned int temp4,TableAddr;
bit flag2,flag_y;
temp1=year/16; //BCD->hex 先把数据转换为十六进制 高位
temp2=year%16; //低位
year=temp1*10+temp2; //把 年 数据 转换成16进制
temp1=month/16; //月份 高位
temp2=month%16; //月份 低位
month=temp1*10+temp2; //把 月 数据 转换成16进制
temp1=day/16; //日期 高位
temp2=day%16; //日期 低位
day=temp1*10+temp2; //把 日 数据 转换成16进制
if(cenbit==0) //如果是21世纪
{
TableAddr=(year+0x64-1)*0x03; //定位数据表地址 year对应的年份表中的地址是(year+99)*3 如2010年 其地址是327
LCDTestWord(0,0x80);
LCDSendWord("20");
}
else //如果是20世纪
{
TableAddr=(year-1)*0x03; //定位数据表地址 year对应的年份表中的地址是(year-1)*3 如1901年 其地址是3
LCDTestWord(0,0x80);
LCDSendWord("19");
}
temp1=YearCode[TableAddr+2]&0x60; //取当年春节所在的公历月份 年份表中第三字节BIT6-5表示春节的公历月份
temp1=_cror_(temp1,5); //循环右移5位,得到 春节所在的公历月份
temp2=YearCode[TableAddr+2]&0x1f; //取当年春节所在的公历日 年份表中第三字节BIT4-0表示当年春节所在的公历日
if(temp1==0x01) // 计算当年春年离当年元旦的天数,春节只会在公历1月或2月
temp3=temp2-1; //假如春节在公历1月,则元旦离春节的天数为 temp2-1 天
else
temp3=temp2+0x1f-1; //假如春节在公历2月,则无理离春节的天数为 temp2+0x1f-1 天
if (month<10)
temp4=DayCode1[month-1]+day-1; //0到8月某日距元旦的天数
else
temp4=DayCode2[month-10]+day-1; //9月开始的某一天距元旦的天数
if ((month>0x02)&&(year%0x04==0)) //如果公历月大于2月并且该年的2月为闰月,天数加1
temp4+=1;
//计算机出公历日距元旦的天数和春节距元旦的天数,则是为了比较公历日是在春节前还是春节后
//如果temp3>temp4 则 公历日在春节之前
if (temp4>=temp3) //公历日在春节后或就是春节当日使用下面代码进行运算
{
temp4-=temp3; //公历日离春节的天数 因为公历日在春节后 所以为temp4-temp3
month=0x01;
MonthP=0x01; //LunarMonth为月份指向,公历日在春节前或就是春节当日LunarMonth指向首月
flag2=GetMoonDay(MonthP,TableAddr); //检查该农历月为大小还是小月,大月返回1,小月返回0
flag_y=0;
if(flag2==0) //GetMoonDay()函数返回的是0
{temp1=0x1d;} //小月29天
else //GetMoonDay()函数返回的是1
{temp1=0x1e;} //大月30天
temp2=YearCode[TableAddr]&0xf0; //年份数据表中第1字节BIT7-4为闰月,为0则这年无闰月,如为1,表示有闰月
temp2=_cror_(temp2,4); //从数据表中取该年的闰月月份,如为0,则该年无闰月 BIT3-0表示阴历1到4月的大小 1为大 0 为小
while(temp4>=temp1)
{
temp4-=temp1;
MonthP+=1;
if(month==temp2)
{
flag_y=~flag_y;
if(flag_y==0) {month+=1;}
}
else
{
month+=1;
}
flag2=GetMoonDay(MonthP,TableAddr);
if(flag2==0)
{
temp1=0x1d;
}
else
{
temp1=0x1e;
}
}
day=temp4+1;
}
else
{ //公历日在春节前使用下面代码进行运算
temp3-=temp4; //公历日离春节的天数 因为公历日在春节前 所以为temp3-temp4
if (year==0x00){year=0x63;cenbit=1;}
else year-=1;
TableAddr-=0x03;
month=0x0c;
temp2=YearCode[TableAddr]&0xf0; //格式第一字节BIT7-4位表示闰月月份,为0,则无闰月,BIT3-0对应阴历第1-4月的大小,
temp2=_cror_(temp2,4);
if (temp2==0)MonthP=0x0c;
else MonthP=0x0d; //
/* MonthP为月份指向,如果当年有闰月,一年有十三个月,月指向13,无闰月指向12*/
flag_y=0;
flag2=GetMoonDay(MonthP,TableAddr);
if(flag2==0)temp1=0x1d;
else temp1=0x1e;
while(temp3>temp1)
{
temp3-=temp1;
MonthP-=1;
if(flag_y==0)month-=1;
if(month==temp2)flag_y=~flag_y;
flag2=GetMoonDay(MonthP,TableAddr);
if(flag2==0)temp1=0x1d;
else temp1=0x1e;
}
day=temp1-temp3+1;
}
c_moon=cenbit;
temp1=year/10;
temp1=_crol_(temp1,4);
temp2=year%10;
LunarYear=temp1|temp2;
temp1=month/10;
temp1=_crol_(temp1,4);
temp2=month%10;
LunarMonth=temp1|temp2;
temp1=day/10;
temp1=_crol_(temp1,4);
temp2=day%10;
LunarDay=temp1|temp2;
}
void DisplayShengXiao(void)
{
unsigned char LunarYearD,ReYear; //农历年份的十进制数 和取模后的余数
if(cen==0x19) {cenbit=1;}
if(cen==0x20) {cenbit=0;}
Conversion(cenbit,year,month,day); //将公历日期转换成农历
LCDTestWord(0,0x94); //显示在LCD的0X94位置上
LCDTestWord(1,LunarYear/16+0x30); //农历年十位
LCDTestWord(1,LunarYear%16+0x30); //农历年个位
LCDTestWord(1,'-'); //用-隔开
LCDTestWord(1,LunarMonth/16+0x30); //农历月十位
LCDTestWord(1,LunarMonth%16+0x30); //农历月个位
LCDTestWord(1,'-');
LCDTestWord(1,LunarDay/16+0x30); //农历日十位
LCDTestWord(1,LunarDay%16+0x30); //农历日个位
LunarYearD=(LunarYear/16)*10+LunarYear%16; //农历年转换成10进制数
ReYear=LunarYearD%12; //农历年模12,取余运算
switch(ReYear)
{
case 0: LCDTestWord(0,0x93);LCDSendWord("龙");break; //余0即整除 农历 龙年
case 1: LCDTestWord(0,0x93);LCDSendWord("蛇");break; //蛇年
case 2: LCDTestWord(0,0x93);LCDSendWord("马");break;
case 3: LCDTestWord(0,0x93);LCDSendWord("羊");break;
case 4: LCDTestWord(0,0x93);LCDSendWord("猴");break;
case 5: LCDTestWord(0,0x93);LCDSendWord("鸡");break;
case 6: LCDTestWord(0,0x93);LCDSendWord("狗");break;
case 7: LCDTestWord(0,0x93);LCDSendWord("猪");break;
case 8: LCDTestWord(0,0x93);LCDSendWord("鼠");break;
case 9: LCDTestWord(0,0x93);LCDSendWord("牛");break;
case 10:LCDTestWord(0,0x93);LCDSendWord("虎");break;
case 11:LCDTestWord(0,0x93);LCDSendWord("兔");break;
}
}
/***************节假日提示********************/
void Holidays(void)
{
LCDTestWord(0,0x98);
if(LunarMonth==0x01 && LunarDay==0x01) {LCDSendWord("春节快乐 ");}
if(LunarMonth==0x01 && LunarDay==0x05) {LCDSendWord("姐姐的生日 ");}
if(LunarMonth==0x01 && LunarDay==0x15) {LCDSendWord("元宵节快乐 ");}
if(LunarMonth==0x05 && LunarDay==0x05) {LCDSendWord("端午节快乐 ");}
if(LunarMonth==0x06 && LunarDay==0x26) {LCDSendWord("佳燕的生日 ");}
if(LunarMonth==0x07 && LunarDay==0x07) {LCDSendWord("中国情人节 ");}
if(LunarMonth==0x08 && LunarDay==0x15) {LCDSendWord("中秋节快乐 ");}
if(LunarMonth==0x09 && LunarDay==0x01) {LCDSendWord("嘿嘿,又长大了 ");}
if(LunarMonth==0x09 && LunarDay==0x03) {LCDSendWord("侄子的生日 ");}
if(LunarMonth==0x09 && LunarDay==0x09) {LCDSendWord("重阳节 ");}
if(LunarMonth==0x09 && LunarDay==0x30) {LCDSendWord("妈妈的生日 ");}
if(LunarMonth==0x12 && LunarDay==0x08) {LCDSendWord("腊八节 ");}
if(LunarMonth==0x12 && LunarDay==0x15) {LCDSendWord("过小年啦 ");}
if(LunarMonth==0x12 && LunarDay==0x27) {LCDSendWord("爸爸的生日 ");}
if(LunarMonth==0x12 && LunarDay==0x29) {LCDSendWord("腊月二十九 ");}
if(LunarMonth==0x12 && LunarDay==0x30) {LCDSendWord("除夕夜到了 ");} //以上是农历节日,以下是公历节日
if(month==0x01 && day==0x01) {LCDSendWord("元旦节快乐 ");}
if(month==0x02 && day==0x02) {LCDSendWord("世界湿地日 ");}
if(month==0x02 && day==0x10) {LCDSendWord("世界气象日 ");}
if(month==0x03 && day==0x08) {LCDSendWord("国际妇女节 ");}
if(month==0x03 && day==0x12) {LCDSendWord("中国植树节 ");}
if(month==0x03 && day==0x15) {LCDSendWord("消费者权益日 ");}
if(month==0x03 && day==0x22) {LCDSendWord("世界水日 ");}
if(month==0x04 && day==0x01) {LCDSendWord("愚人节快乐 ");}
if(month==0x04 && day==0x05) {LCDSendWord("中国清明节 ");}
if(month==0x04 && day==0x22) {LCDSendWord("世界地球日 ");}
if(month==0x05 && day==0x01) {LCDSendWord("国际劳动节 ");}
if(month==0x05 && day==0x04) {LCDSendWord("中国青年节 ");}
if(month==0x05 && day==0x12) {LCDSendWord("世界护士节 ");}
if(month==0x06 && day==0x01) {LCDSendWord("国际儿童节 ");}
if(month==0x06 && day==0x05) {LCDSendWord("世界环境日 ");}
if(month==0x06 && day==0x06) {LCDSendWord("国际爱眼日 ");}
if(month==0x06 && day==0x25) {LCDSendWord("世界土地日 ");}
if(month==0x06 && day==0x26) {LCDSendWord("国际禁毒日 ");}
if(month==0x07 && day==0x01) {LCDSendWord("香港回归日 ");}
if(month==0x08 && day==0x01) {LCDSendWord("中国建军节 ");}
if(month==0x09 && day==0x10) {LCDSendWord("中国老师节 ");}
if(month==0x09 && day==0x18) {LCDSendWord("九一八事件纪念日");}
if(month==0x10 && day==0x01) {LCDSendWord("中国国庆节 ");}
if(month==0x10 && day==0x04) {LCDSendWord("世界动物日 ");}
if(month==0x10 && day==0x09) {LCDSendWord("世界邮政日 ");}
if(month==0x10 && day==0x10) {LCDSendWord("辛亥革命纪念日 ");}
if(month==0x12 && day==0x20) {LCDSendWord("澳门回归纪念日 ");}
if(month==0x12 && day==0x24) {LCDSendWord("平安夜 ");}
if(month==0x12 && day==0x25) {LCDSendWord("圣诞节 ");}
else LCDSendWord("入云龙小白");
}
void UpDate(void)
{
DisplayYear(); //显示年
DisplayMonth(); //显示月
DisplayDay(); //显示日
DisplayWeek(); //显示星期
DisplayHour(); //显示时
DisplayMin(); //显示分
DisplaySec(); //显示秒
DisplayShengXiao();
}
void SetTime(unsigned char count)
{
unsigned char address,item;
unsigned char max,mini;
LCDTestWord(0,0x98);
LCDSendWord("调整");
if(count==6) {LCDSendWord("秒钟 ");address=0x81; max=59;mini=0;}
if(count==5) {LCDSendWord("分钟 ");address=0x83; max=59;mini=0;}
if(count==4) {LCDSendWord("小时 ");address=0x85; max=23;mini=0;}
if(count==3) {LCDSendWord("星期 ");address=0x8b; max=7;mini=1;}
if(count==2) {LCDSendWord("日期 ");address=0x87; max=31; mini=1;}
if(count==1) {LCDSendWord("月份 ");address=0x89; max=12;mini=1;}
if(count==0) {LCDSendWord("年份 ");address=0x8d; max=99;mini=0;}
item=ReadDs1302(address);//读取DS1302某地址上的数值赋给item
item=(item/16)*10+item%16;
if(PlusKey==0) //PlusKey-加
item++; //数加 1
if(ReduceKey==0) //ReduceKey-减
item--; //数减 1
if(item>max)
item=mini; //查看数值有效范围
if(item<mini)
item=max;
WriteDs1302(0x8e,0x00);
item=(item/10)*16+item%10;
WriteDs1302(address-1,item); //将调整好的item值写入DS1302
UpDate();
}
void Key(void)
{
if (SetKey==0) // 设置时间
{
DelayMs(10); //按键消抖
if(SetKey==0&&w==0) //当是正常状态时就进入调时状态
{
w=1; //进入调时
SetTime(next); //调整
}
if(SetKey==0&&w==1) //当是调时状态 本键用于调整下一项
{
next++;
if(next>=7) {next= 0;}
SetTime(next); //调整
}
while(SetKey==0); //等待键松开
}
if(SureKey==0) // 当在调时状态时就退出调时
{
DelayMs(10); //按键消抖
if(SureKey==0&&w==1)
{
w=0;next=0;
Holidays();
}
while(SureKey==0); //等待键松开
}
if (PlusKey==0) //加调整
{
DelayMs(10); //按键消抖
if(PlusKey==0&&w==1)
{
SetTime(next); //调整
}
while(PlusKey==0); //等待键松开
}
if (ReduceKey==0) //减调整
{
DelayMs(10); //按键消抖
if(ReduceKey==0&&w==1)
{
SetTime(next); //调整
}
while(ReduceKey==0); //等待键松开
}
}
void DelayMs(unsigned int a) //延时 1MS/次
{
unsigned char i;
while(--a!=0)
{
for(i=0;i<125;i++)
;
}
}
void Delay(unsigned char num)
{
while(num--)
;
}
void main()
{
SetKey=1;
SureKey=1;
PlusKey=1;
ReduceKey=1;
PSB=1;
next=0;
LCDInit();
LCDClear();
//InitDS1302();
InitialSound();
while(1)
{
if(w==0)
{
DisplayYear(); //显示年
DisplayMonth(); //显示月
DisplayDay(); //显示日
DisplayWeek(); //显示星期
DisplayHour(); //显示时
DisplayMin(); //显示分
DisplaySec(); //显示秒
Holidays(); //显示节日
DisplayTemp(); //显示温度
}
Key();
if(min==0&&sec==0)
{
if(LunarMonth==9&&LunarDay==1)
{
PlayMusic(HappyBirthday,0,3,300);
}
else
{
SpeakerDiDi();
}
}
}
}
复制代码
作者:
1433633039
时间:
2016-3-19 17:42
可有仿真图?
作者:
whengfu
时间:
2016-3-31 14:38
谢谢楼主开源,这么完整的万年历代码,我等学习了
作者:
D_anJF00
时间:
2016-12-22 20:23
可有仿真图
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1