📄 12887(调试).c
字号:
#include<AT89X51.h>
#include<absacc.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define nop() _nop_()
#define DATA_PORT P0
#define mca XBYTE[0Xdf0a] //寄存器A的地址
#define mcb XBYTE[0Xdf0b] //寄存器B的地址
#define mcc XBYTE[0Xdf0c] //寄存器C的地址
#define mcd XBYTE[0Xdf0d] //寄存器D的地址
sbit ACC7=ACC^7; //判断DS12887是否处于更新周期
uchar code settime[7]={7,8,24,5,19,44,0}; //07年8月23日星期四,14:29:00 //////////////////////1
uchar idata gettime[7]; //存储读出的时间
uchar ad[7]= {9,8,7,6,4,2,0}; //年、月、日、星期、时、分、秒地址 //////////////////////6
uchar xdata *addr=0xdf00; //片选地址
uchar Time_Data[9];
uchar Time_T[9];
uchar Time_XQ[5];
bit flag=0; //闪烁标志
bit add_flag=0;
bit dec_flag=0;
uchar p;
uchar count=0;
uchar count1=0;
#define COM8255 XBYTE[0x8003] //命令口地址
#define PA XBYTE[0x8000] //PA口地址
#define PB XBYTE[0x8001] //PB口地址
#define PC1 XBYTE[0x0002] //PC口地址 //读操作
#define PC2 XBYTE[0x8002] //PC口地址 //写操作
bit key_start=0; //键扫描标志位
/********************************************************
LCD函数声明
********************************************************/
uchar scan_key(void);
void shanshuo(void);
void writetime(uchar p,uchar add_flag,uchar dec_flag);
/****************************函数定义**************************************/
/********************************************************
LCD引脚定义
********************************************************/
#define RS P1_5
#define RW P1_6
#define EN P1_7
/********************************************************
LCD程序声明
********************************************************/
void WriteCom(uchar CMD);
void WriteDat(uchar DAT);
void Delay(uint ms);
uchar CheckBusy(void);
void Picture_Set_XY(uchar x, uchar y);
void Char_Set_XY(uchar x, uchar y, uchar *p);
void Lcd_Init(void);
void clear(void);
void Timer0_Init(void);
/************************************************
DS12887函数声明
************************************************/
void Initial_12887(void);
void readtime (void);
void DateToStr(uchar *gettime);
void TimeToStr(uchar *gettime);
void XQToStr(uchar *gettime);
void Timer0(void) interrupt 1 //定时器1中断入口:50MS中断一次
{
TR0=0;
TH0=(65535-50000)/256; //初值高字节
TL0=(65535-50000)%256; //定时初值低字节
count++;
count1++;
if(count1==5)
{ readtime(); //读DS12887时间
DateToStr(gettime);
TimeToStr(gettime);
XQToStr(gettime);
Char_Set_XY(3,1,Time_Data); //显示年、月、日
Char_Set_XY(3,2,Time_T); //显示时、分、秒
//Delay(150);
count1=0;
}
Delay(100);
if(flag==1) //&&count==20
shanshuo();
TR0=1; //开中断
}
/***********************************************************
闪烁
***********************************************************/
void shanshuo(void)
{
//Char_Set_XY(0,0,"DS12887 时钟测试");
//Char_Set_XY(0,1,"Date:");
//Char_Set_XY(0,2,"Time:");
// Delay(1000);
if(count==20)
{
WriteCom(0x93);
WriteDat(0x20);
WriteDat(0x20);
count=0;
//if(count==20);
Delay(2000);
}
}
void int0() interrupt 0
{
key_start=1;
}
/***************************主函数*********************************/
void main(void)
{
uchar x=0;
COM8255=0x81;
EX0=1; //外部中断0允许控制位
IT0=1; //外部中断0触发方式选择位:IT0=0为低电平触发,IT0=1为下降沿触发
EA=1; //开总中断
Lcd_Init(); //LCD初始化
clear();
Char_Set_XY(0,0,"DS12887 时钟测试");
Char_Set_XY(0,1,"Date:");
Char_Set_XY(0,2,"Time:");
//writetime(); //设置时间___需要校正时间时才用
Initial_12887(); //DS12887初始化
Timer0_Init(); //定时器1初始化
while(1)
{
PC2=0x0f; //键盘初始化
if(key_start==1)
{
EA=0;
x=scan_key();
EA=1;
WriteCom(0x98);
WriteDat((x/10)+0x30);
WriteDat((x%10)+0x30);
if(x==1) {flag=1; mcb=0x80;} //SET=1,芯片停止工作,可初始化所有时标寄存器 ///进入数据设置模式
Delay(100);
if(x==2) { flag=0; mcb=0x00;} //SET=1,芯片停止工作,可初始化所有时标寄存器 ///退出数据设置模式
if(flag==1)
{ Delay(100);
if(x==3)
{ add_flag=1;
dec_flag=0;
p=0;
writetime(p,add_flag,dec_flag);
}
Delay(100);
if(x==4)
{
add_flag=1;
dec_flag=1;
p=1;
writetime(p,add_flag,dec_flag);
}
Delay(100);
if(x==5)
{
add_flag=1;
dec_flag=1;
p=2;
writetime(p,add_flag,dec_flag);
}
Delay(100);
if(x==6)
{
add_flag=1;
dec_flag=1;
p=3;
writetime(p,add_flag,dec_flag);
}
Delay(100);
if(x==7)
{
add_flag=1;
dec_flag=1;
p=4;
writetime(p,add_flag,dec_flag);
}
Delay(100);
}
}///if
/////////////////////////////////////////
}//while
}
/*******************************LCD程序区****************************/
/*************************************************
初始化函数
*************************************************/
void Lcd_Init(void)
{
WriteCom(0x30); //写指令:功能设置 8位数据,基本指令
WriteCom(0x0c); //写指令:显示状态 ON,游标OFF,反白OFF
WriteCom(0x01); //写指令:清除显示
WriteCom(0x02); //写指令:地址归位
WriteCom(0x80); //写指令:设置DDRAM地址
Delay(100); //延时
}
/*************************************************
延时函数
*************************************************/
void Delay(uint ms) //延时ms毫秒
{
uchar j;
for(; ms>0; ms--)
for(j=100; j>0; j--)
{
nop();
nop();
}
}
/*************************************************
写控制字函数
*************************************************/
void WriteCom(uchar CMD)
{
while(CheckBusy()); //测忙,若忙则等待
RS = 0; //写控制字
RW = 0; //写操作
DATA_PORT = CMD;
EN = 1;
nop();
nop();
EN = 0; //下降沿写入
}
/*************************************************
写数据函数
*************************************************/
void WriteDat(uchar DAT)
{
while(CheckBusy()); //测忙,若忙则等待
RS = 1; //写数据
RW = 0; //写操作
DATA_PORT = DAT;
EN = 1;
nop();
nop();
EN = 0; //下降沿写入
}
/*************************************************
测忙函数
*************************************************/
uchar CheckBusy(void)
{
uchar temp;
DATA_PORT =0xff; //P0口置高,准备接收数据
RS = 0; //读控制字
RW = 1; //读操作
EN = 1;
nop();
nop();
temp = DATA_PORT;
nop();
nop();
EN = 0; //下降沿读入
temp &= 0x80;
return(temp); //若忙则返回1
}
/*************************************************
置x,y坐标函数——写汉字
*************************************************/
void Char_Set_XY(uchar x, uchar y, uchar *p)
{
if(y == 0)
WriteCom((0x80+x));
if(y == 1)
WriteCom((0x90+x));
if(y == 2)
WriteCom((0x88+x));
if(y == 3)
WriteCom((0x98+x));
while(*p != 0)
WriteDat(*p++);
}
/*************************************************
清屏函数
*************************************************/
void clear(void)
{
WriteCom(0x01); //写指令:清除显示
}
/***********************************DS12887程序区****************************************/
/*************************************************
DS12887初始化函数
*************************************************/
void Initial_12887(void)
{
mca=0x2f; //中断周期50ms,SQW输出2HZ的方波
ACC=mcc; //读C寄存器,清零中断请求标志
ACC=mcd; //读d寄存器, VRT=1,数据有效
mcb=0x7f; //允许中断,时标为二进制码,24小时方式 ,允许方波输出
//EA=1; //开中断
//EX0=1;
}
/*************************************************
DS12887时间设置函数
*************************************************/
void writetime(uchar p,bit add_flag,bit dec_flag) //设置时间
{
uchar max;
uchar xdata *address;
mcb=0x80; //SET=1,芯片停止工作,可初始化所有时标寄存器
//*(addr+ad[p])+=1;
switch(p)
{ case 0:
{ address=addr+ad[p];
if(add_flag==1) *address-=1; } break;
//else *address-=1;
case 1:
{ address=addr+ad[p];*address+=1; max=12;} break;
case 2:
{ address=addr+ad[p];*address+=1; max=31;} break;
case 3:
{ address=addr+ad[p]; *address+=1;max=7;} break;
case 4:
{ address=addr+ad[p];*address+=1; max=24;} break;
case 5:
{ address=addr+ad[p]; *address+=1;max=59;} break;
}
/* if(p==0){address=addr+ad[p];max=99;}
if(p==1){address=addr+ad[p];max=12;}
if(p==2){address=addr+ad[p];max=31;}
if(p==3){address=addr+ad[p];max=7;}
if(p==4){address=addr+ad[p];max=24;}
if(p==5){address=addr+ad[p];max=59;}
address=addr+ad[p];*/
*address+=1;
// if(add_flag==1) //依次写入 年、月、日、星期 、时、分、秒 的数据//////
// {
//if(*address>99) *address=0;
// else *address+=1;
// }
//else //if(dec_flag)
// {*address-=1;
// if(*address<0) *address=max;
// else *address-=1;
//}
}
/*************************************************
读DS12887时间
*************************************************/
void readtime(void)
{
uchar i;
do{ //判断DS12887是否处于更新周期
ACC=mca;
}while(ACC7); //判断UIP位,若UIP为1,则处于更新周期,等待更新完
for(i=0;i<7;i++) /////////////////////////////6
gettime[i]=*(addr+ad[i]); //读时间,依次读入 年、月、日 、时、分、秒 的数据////////////
}
/*************************************************
DS12887 年、月、日数据转换字符函数
*************************************************/
void DateToStr(uchar *gettime)
{
Time_Data[0] = gettime[0]/10 + '0';
Time_Data[1] = gettime[0]%10 + '0';
Time_Data[2] = '-';
Time_Data[3] = gettime[1]/10 + '0';
Time_Data[4] = gettime[1]%10 + '0';
Time_Data[5] = '-';
Time_Data[6] = gettime[2]/10 + '0';
Time_Data[7] = gettime[2]%10 + '0';
Time_Data[8] = '\0';
}
/*************************************************
DS12887 年、月、日数据转换字符函数
*************************************************/
void XQToStr(uchar *gettime)
{
switch(gettime[3])
{ case 0x01: Char_Set_XY(3,3,"星期一"); break; //显示星期
case 0x02: Char_Set_XY(3,3,"星期二"); break;
case 0x03: Char_Set_XY(3,3,"星期三"); break;
case 0x04: Char_Set_XY(3,3,"星期四"); break;
case 0x05: Char_Set_XY(3,3,"星期五"); break;
case 0x06: Char_Set_XY(3,3,"星期六"); break;
case 0x07: Char_Set_XY(3,3,"星期日"); break;
}
}
/*************************************************
DS12887 时、分、秒数据转换字符函数
*************************************************/
void TimeToStr(uchar *gettime)
{
Time_T[0] = gettime[4]/10 +'0';
Time_T[1] = gettime[4]%10 + '0';
Time_T[2] = ':';
Time_T[3] = gettime[5]/10 + '0';
Time_T[4] = gettime[5]%10 + '0';
Time_T[5] = ':';
Time_T[6] = gettime[6]/10 +'0';
Time_T[7] = gettime[6]%10 +'0';
Time_T[8] = '\0';
}
/*************************************************
定时器0:每秒从DS12887中读取20次数据,更新显示
*************************************************/
void Timer0_Init(void) //定时器1初始化:50毫秒定时,预分频256
{
TR0=0; //停止定时器
TMOD = 0x01; //工作方式1
TH0 = (65535-50000)/256; //初值高字节
TL0=(65535-50000)%256; //定时初值低字节
EA = 1;
ET0=1;
TR0=1; //启动定时器
}
/****************************键盘扫描程序区****************************/
/************************************************
键盘扫描子程序
************************************************/
uchar scan_key(void)
{
uchar i,j,temp_i,temp_j,key_value;
uchar a,b; //中间变量
temp_i=0x10;
temp_j=0x01;
PC2=0x0f;
a=PC1;
if((a&0x0f)!=0x0f)
{
Delay(10);//////////////////////////////////////////////20
a=PC1;
if((a&0x0f)!=0x0f)
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
b=~(temp_i<<i);
PC2=b;
a=PC1;
if((a&(temp_j<<j))==0)
key_value=i*4+j+1;
}
}
key_start=0; ///////////////////////////键标志位清零
return key_value;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -