#include<iom16v.h>
#include<macros.h>
#define uchar unsigned char
#define uint unsigned int
#define DB PORTB
#define EN_CLR PORTD &= ~(1 << PD7)
#define EN_SET PORTD |= (1 << PD7)
#define RW_CLR PORTD &= ~(1 << PD6)
#define RW_SET PORTD |= (1 << PD6)
#define RS_CLR PORTD &= ~(1 << PD5)
#define RS_SET PORTD |= (1 << PD5)
//下面的都是写寄存器,要变成读只需加1,即或上0x01
#define SECOND 0x80 //秒
#define MINUTE 0x82 //分鍾
#define HOUR 0x84 //小時
#define DAY 0x86 //天
#define MONTH 0x88 //月
#define WEEK 0x8a //星期
#define YEAR 0x8c //年
#define WRITE_PROTECT 0x8e //写保护
#define SCLK_CLR PORTD &= ~(1 << PD0)
#define SCLK_SET PORTD |= (1 << PD0)
#define IO_CLR PORTD &= ~(1 << PD1)
#define IO_SET PORTD |= (1 << PD1)
#define RST_SET PORTD &= ~(1 << PD2) //因为复位键是低电平有效
#define RST_CLR PORTD |= (1 << PD2)
char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; //秒,分,时到日,月,年位闪的计数
uchar week_value[2];
typedef struct systime
{
unsigned char Second;
unsigned char Minute;
unsigned char Hour;
unsigned char Week;
unsigned char Day;
unsigned char Month;
unsigned char Year;
unsigned char DateString[11];
unsigned char TimeString[9];
}SYSTIME;
SYSTIME CurrentTime; //系统日期
/*12864函数*/
void delay_ms(uint m) //延时程序ms ,频率为8MHz时
{ uint i,j;
for(i=0;i<m;i++)
for(j=0;j<1141;j++);
}
void delay_us(uint u) //延时程序us
{ uint i,j;
for(i=0;i<u;i++)
for(j=0;j<141;j++);
}
uchar check_busy(void)
{
char r;
DDRB = 0x00; //端口B设为输入方式
EN_CLR;RS_CLR;RW_SET; //E=0(致能),RS=0(命令),RW=1(读)
delay_us(2); //液晶延时子程序
EN_SET;
delay_us(2); //液晶延时子程序
r = PINB & 0x80; //读取lcd_data第八位
EN_CLR;
DDRB=0xff; //端口B设为输出方式
return r; //读取结果返回
}
void write_com(uchar cmdcode) //写指令
{
while(check_busy());
RS_CLR; //指令
RW_CLR; //写
EN_CLR;
delay_us(2);//delay_us(1);
EN_SET;
DB=cmdcode;
delay_us(2);//delay_us(1);delay_us(1);
EN_CLR;
}
void write_data(uchar datacode) //写数据
{
while(check_busy());
RS_SET;
RW_CLR;
EN_CLR;
delay_us(2);//delay_us(1);
EN_SET;
DB=datacode;
delay_us(2);//delay_us(1);delay_us(1);
EN_CLR;
}
uchar read_data(void) //读数据
{
uchar dat;
while(check_busy());
RS_SET;
RW_SET;
EN_CLR;
delay_us(2);
EN_SET;
dat=DB;
delay_us(2);
EN_CLR;
return dat;
}
void Initial_LCD(void)
{
write_com(0x38); //8位并行口,基本指令集
write_com(0x38);
write_com(0x08); //令显示器off
write_com(0x01); //清除显示器
write_com(0x06); //令LCD每接收到1Byte数据后,AC自动加1
write_com(0x0E); //令光标,0x0c=不显示,0x0d=显示闪动.
}
void Location_XY(uchar x,uchar y)
{
switch(y) //y取值0~3
{
case 0:
y=0x80;break;
case 1:
y=0x90;break;
case 2:
y=0x88;break;
case 3:
y=0x98;break;
default:
y=0x80;
}
x=x&0x07; //x取值0~7
write_com(x+y);
}
void Write_String(unsigned char *asc)
{
while((*asc) != 0) //判断字是否结束
{
write_data(*asc); //向lcd写入字符串
asc++; //移下一个字符
}
}
void Write_String_atXY(uchar x,uchar y,uchar string[])
{
Location_XY(x,y);
Write_String(string);
}
/*ds1302函数*/
void DS1302_Write(uchar D) //向1302写入一个字节
{
uchar i;
DDRD|=0X07;
for(i=0;i<8;i++)
{
if(D&0x01) IO_SET;
else IO_CLR;//DS1302_IO=D&0x01; //取最低位
SCLK_SET; //DS1302_SCLK=1;
SCLK_CLR; //DS1302_SCLK=0;
D=D>>1;
}
}
uchar DS1302_Read(void) //向1302读取一个字节
{
uchar TempDat=0,i,t;
DDRD&=~BIT(1); //1302的IO口设为输入
t=PIND;
t&=BIT(1);
for(i=0;i<8;i++)
{
TempDat>>=1; //移位,以便下次存放读出的数据
if(t) TempDat=TempDat|0x80; //如果IO口为1,则把1存到TempDat的最高位
SCLK_SET; //DS1302_SCLK=1;
SCLK_CLR; //DS1302_SCLK=0;
}
return TempDat;
}
void WDS1302(uchar ucAddr, uchar ucDat) //写1302寄存器
{
RST_SET; //DS1302_RST = 0; //复位
SCLK_CLR; //DS1302_SCLK = 0;
RST_CLR;//DS1302_RST = 1; //开始读写
DS1302_Write(ucAddr); // 地址,命令
DS1302_Write(ucDat); // 写1Byte数据
SCLK_SET; //DS1302_SCLK = 1; //SCLK上升沿
RST_SET; //DS1302_RST = 0;
}
uchar RDS1302(uchar ucAddr) //读1302寄存器内容
{
uchar ucDat;
RST_SET; //DS1302_RST = 0;
SCLK_CLR; //DS1302_SCLK = 0;
RST_CLR; //DS1302_RST = 1;
DS1302_Write(ucAddr); // 地址,命令
ucDat=DS1302_Read();
SCLK_SET; //DS1302_SCLK = 1;
RST_SET; //DS1302_RST = 0;
return ucDat;
}
/*void GetTime(SYSTIME *sys)
{
uchar uiTempDat;
uiTempDat=RDS1302(YEAR|0x01); //读取年
(*sys).Year=(uiTempDat>>4)*10+(uiTempDat&0x0f);
uiTempDat=RDS1302(MONTH|0x01); //读取月
(*sys).Month=((uiTempDat&0x1f)>>4)*10+(uiTempDat&0x0f);
uiTempDat=RDS1302(DAY|0x01); //读取日
(*sys).Day=((uiTempDat&0x3f)>>4)*10+(uiTempDat&0x0f);
uiTempDat=RDS1302(HOUR|0x01);
(*sys).Hour=((uiTempDat&0x3f)>>4)*10+(uiTempDat&0x0f);
uiTempDat=RDS1302(MINUTE|0x01);
sys->Minute=((uiTempDat&0x7f)>>4)*10+(uiTempDat&0x0f);
uiTempDat=RDS1302(SECOND|0x01);
sys->Second=((uiTempDat&0x7f)>>4)*10+(uiTempDat&0x0f);
uiTempDat=RDS1302(MONTH|0x01);
(*sys).Month=uiTempDat&0x17;
uiTempDat=RDS1302(WEEK|0x01);
sys->Week=uiTempDat&0x07;
}
*/
void GetTime(SYSTIME *Time) //获取时钟芯片的时钟数据到自定义的结构型数组
{
unsigned char ReadValue;
ReadValue = RDS1302(SECOND);
Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = RDS1302(MINUTE);
Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = RDS1302(HOUR);
Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = RDS1302(DAY);
Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = RDS1302(WEEK);
Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = RDS1302(MONTH);
Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = RDS1302(YEAR);
Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
}
void DateToStr(SYSTIME *Time) //将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]
{ if(hide_year<2) //这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为 2007/07/22
{
Time->DateString[0] = '2';
Time->DateString[1] = '0';
Time->DateString[2] = Time->Year/10 + '0';
Time->DateString[3] = Time->Year%10 + '0';
}
else
{
Time->DateString[0] = ' ';
Time->DateString[1] = ' ';
Time->DateString[2] = ' ';
Time->DateString[3] = ' ';
}
Time->DateString[4] = '/';
if(hide_month<2)
{
Time->DateString[5] = Time->Month/10 + '0';
Time->DateString[6] = Time->Month%10 + '0';
}
else
{
Time->DateString[5] = ' ';
Time->DateString[6] = ' ';
}
Time->DateString[7] = '/';
if(hide_day<2)
{
Time->DateString[8] = Time->Day/10 + '0';
Time->DateString[9] = Time->Day%10 + '0';
}
else
{
Time->DateString[8] = ' ';
Time->DateString[9] = ' ';
}
if(hide_week<2)
{
week_value[0] = Time->Week%10 + '0'; //星期的数据另外放到 week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示
}
else
{
week_value[0] = ' ';
}
week_value[1] = '\0';
Time->DateString[10] = '\0'; //字符串末尾加 '\0' ,判断结束字符
}
void TimeToStr(SYSTIME *Time) //将时,分,秒数据转换成液晶显示字符放到数组 TimeString[];
{ if(hide_hour<2)
{
Time->TimeString[0] = Time->Hour/10 + '0';
Time->TimeString[1] = Time->Hour%10 + '0';
}
else
{
Time->TimeString[0] = ' ';
Time->TimeString[1] = ' ';
}
Time->TimeString[2] = ':';
if(hide_min<2)
{
Time->TimeString[3] = Time->Minute/10 + '0';
Time->TimeString[4] = Time->Minute%10 + '0';
}
else
{
Time->TimeString[3] = ' ';
Time->TimeString[4] = ' ';
}
Time->TimeString[5] = ':';
if(hide_sec<2)
{
Time->TimeString[6] = Time->Second/10 + '0';
Time->TimeString[7] = Time->Second%10 + '0';
}
else
{
Time->TimeString[6] = ' ';
Time->TimeString[7] = ' ';
}
Time->DateString[8] = '\0';
}
void show_time(void) //液晶显示程序
{
GetTime(&CurrentTime); //获取时钟芯片的时间数据
TimeToStr(&CurrentTime); //时间数据转换液晶字符
DateToStr(&CurrentTime); //日期数据转换液晶字符
Write_String_atXY(0,1,CurrentTime.TimeString);
// Location_XY(0,1);
// write_data(CurrentTime.TimeString); //显示时间
Write_String_atXY(0,0,CurrentTime.DateString);
// GotoXY(0,0);
// write_data(CurrentTime.DateString); //显示日期
Write_String_atXY(4,2,week_value);
Write_String_atXY(0,2,"Week");
//Location_XY(4,2);
//write_data(week_value); //显示星期
//Location_XY(0,2);
//write_data("Week"); //在液晶上显示 字母 week
delay_ms(400); //扫描延时
}
void Initial_DS1302(void) //时钟芯片初始化
{
unsigned char Second=RDS1302(SECOND);
if(Second&0x80) //判断时钟芯片是否关闭
{
WDS1302(0x8e,0x00); //写入允许
WDS1302(0x8c,0x07); //以下写入初始化时间 日期:07/07/25.星期: 3. 时间: 23:59:55
WDS1302(0x88,0x07);
WDS1302(0x86,0x25);
WDS1302(0x8a,0x07);
WDS1302(0x84,0x23);
WDS1302(0x82,0x59);
WDS1302(0x80,0x55);
WDS1302(0x8e,0x80); //禁止写入
}
}
void main(void)
{
DDRB = 0xff; //端口B设为输出方式
DDRD = 0xff; //端口D设为输出方式
Initial_LCD();
Initial_DS1302();
// SetTime(CurrentTime);
// GUI_Init();
while(1)
{
show_time();
// Time_Set(); //时间设置
}
}