c8051f020单片机数字时钟.docx
《c8051f020单片机数字时钟.docx》由会员分享,可在线阅读,更多相关《c8051f020单片机数字时钟.docx(20页珍藏版)》请在冰点文库上搜索。
c8051f020单片机数字时钟
/*
本程序只是为了应付课程设计而用
据我所知其中至少含有3处bug
使用环境c8051f020使用通过
*/
#include
#include
//*****软件仿真I2C总线与HD7279A连接的两根并行口线*****//
sbitHD7279_DAT=P1^7;
sbitHD7279_CLK=P1^6;
//*****宏定义,HD7279A片选信号、数据信号和时钟信号定义*****//
#defineNOSELECT7279P5|=0x80//P5^7接片选信号,选种
#defineSELECT7279P5&=~(0x80)//未选种
#defineSet7279DATHD7279_DAT=1//数据线置1
#defineClr7279DATHD7279_DAT=0//数据线置0
#defineSet7279CLKHD7279_CLK=1//时钟高电平
#defineClr7279CLKHD7279_CLK=0//时钟底电平
unsignedcharCount1ms;
unsignedcharxdataNowTime[3];//当前时间,用于当前时间的设置
unsignedcharxdataHourH,HourL,MinuteH,MinuteL,SecondH,SecondL;
unsignedcharxdatamHourH,mHourL,mMinuteH,mMinuteL,mSecondH,mSecondL;
unsignedcharxdatasetHourH,setHourL,setMinuteH,setMinuteL,setSecondH,setSecondL;
//*****对所调用其它文件中函数的声明*****//
voidDelay1ms(unsignedcharT);//延时T毫秒
voidDelay1s(unsignedcharT);//延时T秒
voidDelay1us(unsignedcharT);//延时T微秒
//*****仿真I2C总线时序发送一字节*****//
voidSYSCLK_Init(void)
{
inti;
OSCXCN=0x67;//外部晶振22.1184MHz
for(i=0;i<256;i++);
while(!
(OSCXCN&0x80));//等待外部晶振稳定
OSCICN=0x88;//选择外部晶振作系统时钟源,允许时钟丢失检测
}
//*****端口初始化*****//
voidPORT_Init(void)
{
XBR0=0x07;//允许SMBus、SPI0和UART0
XBR1=0x00;
XBR2=0x44;//使能交叉开关和弱上拉
}
//*****定时器T0初始化*****//
voidTimer0_Init(void)
{
CKCON|=0x8;//T0按系统时钟频率计数
TMOD|=0x1;//T0方式1
Count1ms=10;
TR0=0;//停止T0
TH0=(-SYSCLK/1000)>>8;//定时1ms的时间常数
TL0=-SYSCLK/1000;
TR0=1;//启动T0
IE|=0x2;//开T0中断
}
//*****定时器T0中断服务程序(每隔1ms中断1次)*****//
voidTimer0_ISR(void)interrupt1
{
TH0=(-SYSCLK/1000)>>8;//重新装入初值
TL0=-SYSCLK/1000;
if(Count1ms)Count1ms--;//定时时间减1
}
//******延时Tμs(软件实现)******//
voidDelay1us(unsignedcharT)
{
while(T)
{
_nop_();_nop_();_nop_();_nop_();_nop_();
--T;
}
}
//******延时Tms(定时器T0实现)******//
voidDelay1ms(unsignedcharT)
{
Count1ms=T;
while(Count1ms);//在T0中断服务程序中减1
}
//*****延时Ts(定时器T0实现)******//
voidDelay1s(unsignedcharT)
{
while(T)
{
Delay1ms(200);
Delay1ms(200);
Delay1ms(200);
Delay1ms(200);
Delay1ms(200);
T--;
}
}
voidSend7279Byte(unsignedcharch)
{
chari;
SELECT7279;//置CS低电平
Delay1us(50);//延时50μ
for(i=0;i<8;i++)
{
if(ch&0x80)//输出1位到HD7279A的DATA端
Set7279DAT;
else
Clr7279DAT;
Set7279CLK;
ch=ch<<1;//待发数据左移
Delay1us(8);
Clr7279CLK;
Delay1us(8);
}
Clr7279DAT;//发送完毕,DATA端置低,返回
}
//*****仿真I2C总线时序接收一字节*****//
unsignedcharReceive7279Byte(void)
{
unsignedchari,ch=0;
Set7279DAT;//DATA端置为高电平(输入状态)
Delay1us(50);
for(i=0;i<8;i++)
{
Set7279CLK;
Delay1us(8);
ch=ch<<1;//接收数据左移1位
if(HD7279_DAT)ch+=1;//接收1位数据
Clr7279CLK;
Delay1us(8);
}
Clr7279DAT;//接收完毕,DATA端重新置成低电平(输出状态)
returnch;
}
//*****让第No(0到5)位LED闪烁*****//
voidFlashLED(unsignedcharNo)
{
unsignedchari;
Send7279Byte(0x88);//发闪烁指令
i=0x01;
while(No)//将1移到第No位
{
i=i<<1;
No--;
}
Send7279Byte(~i);//0闪烁、1不闪烁
NOSELECT7279;
}
//******HD7279A左移命令*****//
voidMoveLeft(void)
{
Send7279Byte(0xA1);//发左移指令
NOSELECT7279;
}
//******采用不译码方式显示时数字0到F的段码******//
unsignedcharcodeBdSeg[]={
0x7e,0x30,0x6d,0x79,//0123
0x33,0x5b,0x5f,0x70,//4567
0x7f,0x7b,0x77,0x1f,//89ab
0x4e,0x3d,0x4f,0x47,//cdef
0x00,0x01};
//*显示指针DispBuf所指6个单元数据,点亮第ShowDot(1到6)个LED的小数点*//
voidDispLED(unsignedchar*DispBuf,unsignedcharShowDot)
{
chari,ch;
ShowDot--;
for(i=0;i<6;i++)
{
ch=DispBuf[i];//取一字符
if((ch>='a')&&(ch<='f'))//转换成数字
{
ch-='a';ch+=0xa;
}
if((ch>='A')&&(ch<='F'))
{
ch-='A';ch+=0xa;
}
Send7279Byte(0x90+5-i);//用不译码方式显示在第i位
if(ch=='')//发送不译码方式显示命令的第2字节
Send7279Byte(0x00);
else
if(ch=='-')
Send7279Byte(0x01);
else
{
if(ShowDot==i)//查表显示,同时点亮小数点
Send7279Byte(0x80|BdSeg[ch&0x0f]);
else
Send7279Byte(BdSeg[ch&0x0f]);
}
}
NOSELECT7279;//置CS高电平
}
//*****读取按键值*****//
unsignedcharGetKeyValue(void)
{
unsignedcharKeyValue;
if(CPT1CN&0x40)return-1;//if(P17==1)return-1;//无键按下
Send7279Byte(0x15);//发读键盘命令
KeyValue=Receive7279Byte();
NOSELECT7279;
returnKeyValue;
}
//***等待按键释放,用C8051F020的比较器硬件检测,也可以用软件延时实现***//
voidWaitKeyOff(void)
{
while(!
(CPT1CN&0x40));
}
//*****显示任意长整型数据*****//
voidDispValue(unsignedlongxx)
{
unsignedcharbuf[6];
buf[0]=(xx%1000000)/100000;//最高位
buf[1]=(xx%100000)/10000;
buf[2]=(xx%10000)/1000;
buf[3]=(xx%1000)/100;
buf[4]=(xx%100)/10;
buf[5]=(xx%10);//最低位
DispLED(buf,0);//调用显示函数,所有小数点都不点亮
}
//**从键盘读取6位数据,用于存储时间,格式是HHMMSS,所读数据转换成长整型**//
unsignedlongInputNum(void)
{
unsignedlongNum=0;
unsignedchari=0,KeyValue;
DispLED("-",0);//输入提示
FlashLED(0);//第一位闪烁
Delay1s
(1);
while
(1)
{
KeyValue=GetKeyValue();
if(i==6)//6位数据输入完,返回
{
FlashLED(8);//关闪烁
returnNum;
}
if((KeyValue>=0)&&(KeyValue<=9))//只接收十进制的0到9
{
i++;
Send7279Byte(0xC8);//发送键码值,按方式1译码下载显示
Send7279Byte(KeyValue);
MoveLeft();//显示并左移一位,仍使低位显示并闪烁。
Send7279Byte(0x90);
Send7279Byte(0x01);
NOSELECT7279;
WaitKeyOff();
Num*=10;//转换成十进制
Num+=KeyValue;
}
Delay1ms(500);
}
}
voidDispTime(void)
{
Send7279Byte(0x85);//在最高位(第5位)LED显示小时的高位
Send7279Byte(HourH);
Send7279Byte(0x84);//在第4位LED显示小时的低位
Send7279Byte(HourL);
Send7279Byte(0x83);//在第3位LED显示分钟的高位
Send7279Byte(MinuteH);
Send7279Byte(0x82);//在第2位LED显示分钟的低位
Send7279Byte(MinuteL);
Send7279Byte(0x81);//在第1位LED显示秒钟的高位
Send7279Byte(SecondH);
Send7279Byte(0x80);//在第0位LED显示秒钟的低位
Send7279Byte(SecondL);
}
voidmDispTime(void)
{
Send7279Byte(0x85);//在最高位(第5位)LED显示小时的高位
Send7279Byte(mHourH);
Send7279Byte(0x84);//在第4位LED显示小时的低位
Send7279Byte(mHourL);
Send7279Byte(0x83);//在第3位LED显示分钟的高位
Send7279Byte(mMinuteH);
Send7279Byte(0x82);//在第2位LED显示分钟的低位
Send7279Byte(mMinuteL);
Send7279Byte(0x81);//在第1位LED显示秒钟的高位
Send7279Byte(mSecondH);
Send7279Byte(0x80);//在第0位LED显示秒钟的低位
Send7279Byte(mSecondL);
}
voidset_time()
{
unsignedlongCurrentTime=0;
do{//从键盘输入时间,格式HHMMSS
CurrentTime=InputNum();
DispValue(CurrentTime);
NowTime[0]=(unsignedchar)((CurrentTime/100000)<<4);//时
CurrentTime=CurrentTime%100000;
NowTime[0]=NowTime[0]|(CurrentTime/10000);
CurrentTime=CurrentTime%10000;
NowTime[1]=(unsignedchar)((CurrentTime/1000)<<4);//分
CurrentTime=CurrentTime%1000;
NowTime[1]=NowTime[1]|(CurrentTime/100);
CurrentTime=CurrentTime%100;
NowTime[2]=(unsignedchar)((CurrentTime/10)<<4);//秒
CurrentTime=CurrentTime%10;
NowTime[2]=NowTime[2]|CurrentTime;
}while((NowTime[0]>0x24)|(NowTime[1]>0x59)|(NowTime[2]>0x59));
HourH=NowTime[0]/16;//转换成10进制
HourL=NowTime[0]%16;
MinuteH=NowTime[1]/16;
MinuteL=NowTime[1]%16;
SecondH=NowTime[2]/16;
SecondL=NowTime[2]%16;
}
unsignedlongset_InputNum(void)
{
unsignedlongNum=0;
unsignedchari=0,KeyValue;
intc=0;
DispLED("-",0);//输入提示
FlashLED(0);//第一位闪烁
while
(1)
{
KeyValue=GetKeyValue();
if(i==6)//6位数据输入完,返回
{
FlashLED(8);//关闪烁
returnNum;
}
if((KeyValue>=0)&&(KeyValue<=9))//只接收十进制的0到9
{
i++;
Send7279Byte(0xC8);//发送键码值,按方式1译码下载显示
Send7279Byte(KeyValue);
MoveLeft();//显示并左移一位,仍使低位显示并闪烁。
Send7279Byte(0x90);
Send7279Byte(0x01);
NOSELECT7279;
WaitKeyOff();
Num*=10;//转换成十进制
Num+=KeyValue;
}
if(SecondL>9){SecondH++,SecondL=0;}
if(SecondH>5){SecondH=0,MinuteL++;}
if(MinuteL>9){MinuteH++,MinuteL=0;}
if(MinuteH>5){MinuteH=0,HourL++;}
if(HourL>9){HourH++;HourL=0;}
if(HourH>2)HourH=0;
if((HourH==2)&&(HourL>3)){HourH=0;HourL=0;}
c++;Delay1ms(500);
if(c%2==0)SecondL++;
}
}
voidset_ring()
{
unsignedlongCurrentTime=0;
do{//从键盘输入时间,格式HHMMSS
CurrentTime=set_InputNum();
DispValue(CurrentTime);
NowTime[0]=(unsignedchar)((CurrentTime/100000)<<4);//时
CurrentTime=CurrentTime%100000;
NowTime[0]=NowTime[0]|(CurrentTime/10000);
CurrentTime=CurrentTime%10000;
NowTime[1]=(unsignedchar)((CurrentTime/1000)<<4);//分
CurrentTime=CurrentTime%1000;
NowTime[1]=NowTime[1]|(CurrentTime/100);
CurrentTime=CurrentTime%100;
NowTime[2]=(unsignedchar)((CurrentTime/10)<<4);//秒
CurrentTime=CurrentTime%10;
NowTime[2]=NowTime[2]|CurrentTime;
}while((NowTime[0]>0x24)|(NowTime[1]>0x59)|(NowTime[2]>0x59));
setHourH=NowTime[0]/16;//转换成10进制
setHourL=NowTime[0]%16;
setMinuteH=NowTime[1]/16;
setMinuteL=NowTime[1]%16;
setSecondH=NowTime[2]/16;
setSecondL=NowTime[2]%16;
}
voidm()
{
unsignedlongCurrentTime=0;
unsignedcharcontrol_keyvalue;
intma=0;
inta=1;
DispValue(CurrentTime);
NowTime[0]=(unsignedchar)((CurrentTime/100000)<<4);//时
CurrentTime=CurrentTime%100000;
NowTime[0]=NowTime[0]|(CurrentTime/10000);
CurrentTime=CurrentTime%10000;
NowTime[1]=(unsignedchar)((CurrentTime/1000)<<4);//分
CurrentTime=CurrentTime%1000;
NowTime[1]=NowTime[1]|(CurrentTime/100);
CurrentTime=CurrentTime%100;
NowTime[2]=(unsignedchar)((CurrentTime/10)<<4);//秒
CurrentTime=CurrentTime%10;
NowTime[2]=NowTime[2]|CurrentTime;
mHourH=NowTime[0]/16;//转换成10进制
mHourL=NowTime[0]%16;
mMinuteH=NowTime[1]/16;
mMinuteL=NowTime[1]%16;
mSecondH=NowTime[2]/16;
mSecondL=NowTime[2]%16;
while
(1)
{
Delay1ms(200);ma++;
if(ma%5==0)
mSecondL++;
if(mSecondL>9){mSecondH++,mSecondL=0;}
if(mSecondH>5){mSecondH=0,mMinuteL++;}
if(mMinuteL>9){mMinuteH++,mMinuteL=0;}
if(mMinuteH>5){mMinuteH=0,mHourL++;}
if(mHourL>9){mHourH++;mHourL=0;}
if(mHourH>2)mHourH=0;
if((mHourH==2)&&(mHourL>3)){mHourH=0;mHourL=0;}
control_keyvalue=GetKeyValue();
if(control_keyvalue==14)break;
if(control_keyvalue==10)a=-a;
if(a==-1&&ma%5==0)mSec