📄 clock.c
字号:
/*
单片机教学打铃控制器
芯 片:AT89S52
晶 振:频率12MHz
按键说明:
Ring_Set P1^0//时间设置
Time_Set P1^1//闹铃设置
Left_Move P1^2//向左移动
Add P1^3//数据增加
Sub P1^4//数据减小
Right_Move P1^5//向右移动
ESC P1^6//取消
Enter P1^7//确定
*/
#include "AT89X52.H"
#include "intrins.h"
#define uchar unsigned char
#define AddressWrite24C02 0xa0//24C02写地址
#define AddressRead24C02 0xa1//24C02读地址
uchar ClockData[]={0,0,12};//时钟数据
uchar RingDataH[40];//40个闹铃数据(时)
uchar RingDataL[40];//40个闹铃数据(分)
uchar RingCount=0;//闹铃总数
uchar counter=0;
uchar I2cStartByte=0xaa;//I2c开始标志字
uchar I2cEndByte=0x55;//I2c结束标志字
uchar S_Ray_Flag=0;//秒闪标志1
sbit S_Ray=P3^1;//秒闪
sbit s_ray=P3^0;//秒闪标志2
sbit Alarm=P3^4;//闹铃信号
sbit SDA=P3^2;//I2C BUS数据
sbit SCL=P3^3;//I2C BUS时钟
//---------------------T1中断,产生时钟-------------------------------
void Timer1(void)interrupt 3 using 1
{
TH1=0x3c;
TL1=0xb0;
if(counter%10==0)
{
s_ray=~s_ray;
if(S_Ray_Flag)S_Ray=0;
else S_Ray=~S_Ray;
}
if(counter==20)
{
counter=1;
if(ClockData[0]==59)
{
ClockData[0]=0;
if(ClockData[1]==59)
{
ClockData[1]=0;
if(ClockData[2]==23)
{
ClockData[2]=0;
}
else ClockData[2]++;//时
}
else ClockData[1]++;//分
}
else ClockData[0]++;//秒
}
else counter++;
}
//------------------BCD码转换成字形码的程序-----------------------------
uchar BCD_to_Grapheme(uchar Data)
{
switch(Data)
{
case 0:return 0x3f;
case 1:return 0x06;
case 2:return 0x5b;
case 3:return 0x4f;
case 4:return 0xe6;
case 5:return 0xed;
case 6:return 0xfd;
case 7:return 0x07;
case 8:return 0xff;
case 9:return 0xef;
}
}
//-----------------------------得到位地址的程序-------------------------
uchar GetClockBit(uchar ShowBit)
{
switch(ShowBit)
{
case 0:return 0xdf;
case 1:return 0xef;
case 2:return 0xf7;
case 3:return 0xfb;
case 4:return 0xfd;
case 5:return 0xfe;
}
}
//---------------------延时count个ms的程序-------------------------
void Delay(uchar count)
{
uchar i;
while(count--)
{
for(i=0;i<123;i++)
;
}
}
//-----------------------动态扫描的程序-------------------------------
void Display(uchar *ShowAddress,uchar FlagBit)
{
uchar ShowBit;
uchar Show;
for(ShowBit=0;ShowBit<6;ShowBit++)
{
if(FlagBit!=5)
{
switch(ShowBit)
{
case 0:Show=BCD_to_Grapheme((*ShowAddress)%10);break;
case 1:Show=BCD_to_Grapheme((*ShowAddress)/10);break;
case 2:Show=BCD_to_Grapheme((*(ShowAddress+1))%10);break;
case 3:Show=BCD_to_Grapheme((*(ShowAddress+1))/10);break;
case 4:Show=BCD_to_Grapheme((*(ShowAddress+2))%10);break;
case 5:Show=BCD_to_Grapheme((*(ShowAddress+2))/10);break;
}
}
P2=0xff;
switch(FlagBit)
{
case 0:P0=Show;break;
case 1://设秒闪动
if(s_ray && (ShowBit==0||ShowBit==1))P0=0x40;
else P0=Show;
break;
case 2://设分闪动
if(s_ray && (ShowBit==2||ShowBit==3))P0=0x40;
else P0=Show;
break;
case 3://设时闪动
if(s_ray && (ShowBit==4||ShowBit==5))P0=0x40;
else P0=Show;
break;
case 4://调闹铃时的闪动
if(s_ray)P0=0x40;
else P0=Show;
break;
case 5://调闹铃时的显示
P0=*(ShowAddress+ShowBit);
break;
}
P2=GetClockBit(ShowBit);
Delay(1);
}
}
//----------------得到键盘值的程序----------------------------------
uchar GetKey()
{
switch(P1)
{
case 0xff:return 0;
case 0xfe:return 1;
case 0xfd:return 2;
case 0xfb:return 3;
case 0xf7:return 4;
case 0xef:return 5;
case 0xdf:return 6;
case 0xbf:return 7;
case 0x7f:return 8;
}
}
//--------------------------定义I2C接口子程序-------------------------
/*
I2C特殊字节定义
*/
void I2cWait()//等待
{
_nop_();
_nop_();
}
void I2cStart()//开始
{
SDA=1;
SCL=1;
I2cWait();
SDA=0;
I2cWait();
SCL=0;
}
void I2cStop()//停止
{
SDA=0;
I2cWait();
SCL=1;
I2cWait();
SDA=1;
}
void I2cSendByte(uchar ByteData)//发送
{
uchar i;
for(i=0;i<8;i++)
{
if(ByteData&0x80)
SDA=1;
else
SDA=0;
ByteData<<=1;
I2cWait();
SCL=1;
I2cWait();
SCL=0;
I2cWait();
}
SDA=1;
I2cWait();
SCL=1;
I2cWait();
SCL=0;
I2cWait();
}
uchar I2cReceiveByte()//接收
{
uchar i;
uchar ByteData=0;
for(i=0;i<8;i++)
{
SCL=1;
I2cWait();
ByteData<<=1;
if(SDA)ByteData++;
SCL=0;
I2cWait();
}
SDA=1;
I2cWait();
SCL=1;
I2cWait();
SCL=0;
I2cWait();
return ByteData;
}
//--------------------------声明AT24C02的读写子程序-------------------
void I2cWrite24C02(uchar I2c24C02Addr,uchar I2c24C02Data)//写
{
I2cStart();
I2cSendByte(AddressWrite24C02);
I2cSendByte(I2c24C02Addr);
I2cSendByte(I2c24C02Data);
I2cStop();
}
uchar I2cRead24C02(uchar I2c24C02Addr)//读
{
uchar Data;
I2cStart();
I2cSendByte(AddressWrite24C02);
I2cSendByte(I2c24C02Addr);
I2cStart();
I2cSendByte(AddressRead24C02);
Data=I2cReceiveByte();
I2cStop();
return Data;
}
//-------------------------初始化24C02-----------------------------
void Initializtion(void)
{
uchar i,j;
uchar StartByte=I2cRead24C02(0);
j=1;
if(StartByte==I2cStartByte)
for(i=0;i<40;i++)
{
if(I2cRead24C02(j)==I2cEndByte)break;
RingDataH[i]=I2cRead24C02(j++);
RingDataL[i]=I2cRead24C02(j++);
RingCount++;
}
else
{
I2cWrite24C02(0,I2cStartByte);
I2cWrite24C02(1,I2cEndByte);
}
}
//-------------------排序的程序------------------------------------
void Taxis(void)
{
uchar i,j,t;
for(i=0;i<RingCount;i++)
for(j=0;j<RingCount-i-1;j++)
{
if(RingDataH[j]>RingDataH[j+1])
{
t=RingDataH[j];
RingDataH[j]=RingDataH[j+1];
RingDataH[j+1]=t;
t=RingDataL[j];
RingDataL[j]=RingDataL[j+1];
RingDataL[j+1]=t;
}
else if(RingDataH[j]==RingDataH[j+1])
if(RingDataL[j]>RingDataL[j+1])
{
t=RingDataL[j];
RingDataL[j]=RingDataL[j+1];
RingDataL[j+1]=t;
}
}
}
//---------------------------闹铃设置--------------------------------
void Control_Ring_Set_Key(void)
{
uchar Null[]={0x00,0x38,0x38,0x3e,0x37,0x00};//"Null"的字形码
uchar ShowRing[3];
uchar NowKey;
uchar i,j=1;
uchar BeforKey=0xff;
uchar KeyCount=0;
uchar FlagBit=3;
uchar ShowRingCount=0;
uchar count1=0x40;//无操作时的时间控制
uchar count2=0xff;//无操作时的时间控制
S_Ray_Flag=1;
ShowRing[0]=RingDataL[ShowRingCount];
ShowRing[1]=RingDataH[ShowRingCount];
ShowRing[2]=ShowRingCount;
while(1)
{
if(RingCount==0)
Display(Null,5);
else
Display(ShowRing,FlagBit);
if(KeyCount==2)
{
KeyCount=0;
NowKey=GetKey();
if(NowKey!=BeforKey)
{
count1=0x40;
count2=0xff;
switch(NowKey)
{
case 1://增加一个闹铃
if(RingCount!=40 && FlagBit==4)
{
RingDataH[RingCount]=RingDataL[RingCount]=0;
ShowRingCount=RingCount++;
}
if(RingCount==0)
{
RingDataH[0]=RingDataL[0]=0;
RingCount++;
}
ShowRing[0]=RingDataL[ShowRingCount];
ShowRing[1]=RingDataH[ShowRingCount];
ShowRing[2]=ShowRingCount;
break;
case 2://删除一个闹铃
if(RingCount!=0 && FlagBit==4)
{
if(RingCount==1)
{
RingDataH[0]=RingDataL[0]=0;
}
else
{
for(i=ShowRingCount;i<RingCount;i++)
{
RingDataH[i]=RingDataH[i+1];
RingDataL[i]=RingDataL[i+1];
}
RingDataH[i]=RingDataL[i]=0;
}
RingCount--;
if(RingCount==ShowRingCount)
ShowRingCount--;
ShowRing[0]=RingDataL[ShowRingCount];
ShowRing[1]=RingDataH[ShowRingCount];
ShowRing[2]=ShowRingCount;
}
break;
case 3://左移
if(RingCount!=0)
{
if(FlagBit==4)FlagBit=1;
else FlagBit++;
}
break;
case 4://闹铃时间增
switch(FlagBit)
{
case 1:
if(ShowRing[0]==59)
ShowRing[0]=0;
else
ShowRing[0]++;
RingDataL[ShowRingCount]=ShowRing[0];
break;
case 2:
if(ShowRing[1]==23)
ShowRing[1]=0;
else
ShowRing[1]++;
RingDataH[ShowRingCount]=ShowRing[1];
break;
case 3:
if(ShowRingCount==RingCount-1)
ShowRingCount=0;
else
ShowRingCount++;
ShowRing[0]=RingDataL[ShowRingCount];
ShowRing[1]=RingDataH[ShowRingCount];
ShowRing[2]=ShowRingCount;
break;
}
break;
case 5://闹铃时间减
switch(FlagBit)
{
case 1:
if(ShowRing[0]==0)
ShowRing[0]=59;
else
ShowRing[0]--;
break;
case 2:
if(ShowRing[1]==0)
ShowRing[1]=23;
else
ShowRing[1]--;
break;
case 3:
if(ShowRingCount==0)
ShowRingCount=RingCount-1;
else
ShowRingCount--;
ShowRing[0]=RingDataL[ShowRingCount];
ShowRing[1]=RingDataH[ShowRingCount];
ShowRing[2]=ShowRingCount;
break;
}
break;
case 6://右移
if(RingCount!=0)
{
if(FlagBit==1)FlagBit=4;
else FlagBit--;
}
break;
case 7://取消
L3: j=1;
RingCount=0;
EA=0;
for(i=0;i<40;i++)
{
if(I2cRead24C02(j)==I2cEndByte)break;
RingDataH[i]=I2cRead24C02(j++);
RingDataL[i]=I2cRead24C02(j++);
RingCount++;
}
EA=1;
goto L2;
case 8://确定
j=1;
RingDataL[ShowRingCount]=ShowRing[0];
RingDataH[ShowRingCount]=ShowRing[1];
Taxis();//排序
for(i=0;i<RingCount;i++)
{
EA=0;
I2cWrite24C02(j++,RingDataH[i]);
EA=1;
Display(ShowRing,FlagBit);
EA=0;
I2cWrite24C02(j++,RingDataL[i]);
EA=1;
Display(ShowRing,FlagBit);
}
EA=0;
I2cWrite24C02(j,I2cEndByte);
EA=1;
if(RingCount==0)
Display(Null,5);
else
Display(ShowRing,FlagBit);
goto L2;
}
}
BeforKey=NowKey;
count2--;
if(count2==0)
{
count2=0x40;
count1--;
if(count1==0)
goto L3;
}
}
else KeyCount++;
}
L2:S_Ray_Flag=0;
}
//-------------时间设置的程序--------------------------------------------
void Control_Time_Set_Key()
{
uchar S_Flag=1;
uchar M_Flag=1;
uchar H_Flag=1;
uchar count1=0x40;//无操作时的时间控制
uchar count2=0xff;//无操作时的时间控制
uchar NowKey=0xff;
uchar BeforKey=0xff;
uchar KeyCount=0;
uchar FlagBit=1;
uchar LS_ClockData[3];
LS_ClockData[2]=ClockData[2];
LS_ClockData[1]=ClockData[1];
LS_ClockData[0]=ClockData[0];
while(1)
{
if(S_Flag)LS_ClockData[0]=ClockData[0];
if(M_Flag)LS_ClockData[1]=ClockData[1];
if(H_Flag)LS_ClockData[2]=ClockData[2];
Display(LS_ClockData,FlagBit);//动态扫描显示
if(KeyCount==2)
{
KeyCount=0;
NowKey=GetKey();
if(NowKey!=BeforKey)
{
count1=0x40;
count2=0xff;
switch(GetKey())
{
case 3://向左移动
if(FlagBit==3)FlagBit=1;
else FlagBit++;
break;
case 4://增加
switch(FlagBit)
{
case 1://秒增加
if(LS_ClockData[0]==59)
LS_ClockData[0]=0;
else LS_ClockData[0]++;
S_Flag=0;
break;
case 2://分增加
if(LS_ClockData[1]==59)
LS_ClockData[1]=0;
else LS_ClockData[1]++;
M_Flag=0;
break;
case 3://时增加
if(LS_ClockData[2]==23)
LS_ClockData[2]=0;
else LS_ClockData[2]++;
H_Flag=0;
break;
}
break;
case 5://减小
switch(FlagBit)
{
case 1://秒减小
if(LS_ClockData[0]==0)
LS_ClockData[0]=59;
else LS_ClockData[0]--;
S_Flag=0;
break;
case 2://分减小
if(LS_ClockData[1]==0)
LS_ClockData[1]=59;
else LS_ClockData[1]--;
M_Flag=0;
break;
case 3://时减小
if(LS_ClockData[2]==0)
LS_ClockData[2]=23;
else LS_ClockData[2]--;
H_Flag=0;
break;
}
break;
case 6://向右移动
if(FlagBit==1)FlagBit=3;
else FlagBit--;
break;
case 7://取消
goto L1;
case 8://确定
ClockData[2]=LS_ClockData[2];
ClockData[1]=LS_ClockData[1];
ClockData[0]=LS_ClockData[0];
goto L1;
}
}
BeforKey=NowKey;
count2--;
if(count2==0)
{
count2=0x40;
count1--;
if(count1==0)
goto L1;
}
}
else KeyCount++;
}
L1:;
}
//----------------------主程序-----------------------------------------------
void main()
{
uchar NowKey;
uchar BeforKey=0xff;
uchar KeyCount=0;
uchar i=1;
Alarm=0;
S_Ray=1;
s_ray=1;
Initializtion();//读24C02
TMOD=0x10;//设置T1
EA=1;
ET1=1;
PT1=1;
TH1=0x3c;
TL1=0xb0;
TR1=1;
while(1)
{
Display(ClockData,0);//动态扫描
//闹铃监视
for(i=0;i<RingCount;i++)
{
if((RingDataH[i]==ClockData[2]) && (RingDataL[i]==ClockData[1]))
{
Alarm=1;
break;
}
else Alarm=0;
}
//按键控制
if(KeyCount==2)
{
KeyCount=0;
NowKey=GetKey();
if(NowKey!=BeforKey)
{
switch (NowKey)
{
case 1:
Control_Time_Set_Key();
break;
case 2:
Alarm=0;
Control_Ring_Set_Key();
break;
default:
break;
}
}
BeforKey=NowKey;
}
else KeyCount++;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -