#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=P1if(temp!=0xfe)m=0
P1=0xfdtemp=P1 if(temp!=0xfd)m=1
P1=0xfbtemp=P1 if(temp!=0xfb)m=2
P1=0xf7temp=P1 if(temp!=0xf7)m=3
P1=0xeftemp=P1 if(temp!=0xef)n=0
P1=0xdftemp=P1 if(temp!=0xdf)n=1
P1=0xbftemp=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')*10else {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=0i<9i++)
{
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=zx>0x--)
for(y=110y>0y--)
}
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=0i<ni++)
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=8i>0i--)
{
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=8i>0i--)
{
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
DS_WriteBCDBata(0x80,second|0x80)这个函数应该是把秒写到DS1302芯片的秒寄存器中,秒的寄存器的地址上80和81两个地址(寄存器0)。寄存器0中最高位 CH 是一个时钟停止标志位。如果时钟电路有备用电源,上电后,我们要先检测一下这一位,如果这一位是 0,那说明时钟芯片在系统掉电后,由于备用电源的供给,时钟是持续正常运行的;如果这一位是 1,那么说明时钟芯片在系统掉电后,时钟部分不工作了。如果 Vcc1 悬空或者是电池没电了,当我们下次重新上电时,读取这一位,那这一位就是 1,我们可以通过这一位判断时钟在单片机系统掉电后是否还正常运行。剩下的7 位高 3 位是秒的十位,低 4 位是秒的个位,这里再提请注意一次,DS1302 内部是 BCD 码,而秒的十位最大是 5,所以 3 个二进制位就够了。second|0x80后面的这个数据使用 | 符号就是把最高位CH变成1.
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)