啥也别唠了,给你看一下最简单的六位时钟的一部分程序
#include <reg52.H> //为了布线方便用到了P4口,故包含了STC专用的头文件,可以在STC-ISP软件中下载
#define LEDPORT P0
#define uchar unsigned char
#define uint unsigned int
sbit D1=P3^3;
sbit D2=P3^4;
sbit D3=P3^5;
sbit D4=P3^6;
sbit D5=P3^7;
sbit D6=P4^0;
sbit LED1=P2^5;
sbit LED2=P2^6;
sbit CLK =P2^1;
sbit IO =P2^2;
sbit RST =P2^3;
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
unsigned char hour,min,sec; //小时、分钟、秒
bit rev_start,rev_stop; //GPS接收开始、结束标志位
unsigned char code tab[ ]={0xA0,0xBE,0x64,0x2C,0x3A,0x29,0x21,0xBC,0x20,0x28,0xFF};//0-9,灭
unsigned char buf[10]; //GPS数据接收缓冲
unsigned char irtime;//红外用全局变量,用于计算2个下降沿之间的时间
bit decode_ok,irok;
static unsigned char ircode[4];
unsigned char irdata[33];
uchar set,temp,dot;
bit flag,test;
uint cnt;
void Timer_Init()
{
TMOD=0x22;
TH0=0x00; //重载值
TL0=0x00; //初始化值
ET0=1; //开中断
TR0=1;
IT0 = 1; //指定外部中断0下降沿触发,INT0 (P3.2)
EX0 = 1; //使能外部中断
TL2 = 0xCD; //设置定时初值
TH2 = 0xF8; //设置定时初值
RCAP2L = 0xCD; //设置定时重载值
RCAP2H = 0xF8; //设置定时重载值
ET2=1;
TR2=1;
TH1 = 0xFD; //9600波特率的初值
TL1 = TH1; //9600波特率的初值
TR1 = 1;
SCON = 0x50; //使用串行工作方式1,10位异步收发8位数据,波特率可变(由T1的溢出率控制)
// ES = 1;
EA=1;
}
void inputbyte(unsigned char ucDa)
{
unsigned char i;
ACC = ucDa;
for(i=8; i>0; i--)
{
IO = ACC0; //相当于汇编中的 RRC
CLK = 1;
CLK = 0;
ACC = ACC >> 1;
}
}
unsigned char outputbyte(void)
{
unsigned char i;
for(i=8; i>0; i--)
{
ACC = ACC >>1; //相当于汇编中的 RRC
ACC7 = IO;
CLK = 1;
CLK = 0;
}
return(ACC);
}
void write(unsigned char ucAddr, unsigned char ucDa)
{
RST = 0;
CLK = 0;
RST = 1;
inputbyte(ucAddr); //地址,命令
inputbyte(ucDa); //写1Byte数据
CLK = 1;
RST =0;
}
unsigned char read(unsigned char ucAddr)
{
unsigned char ucDa;
RST = 0;
CLK = 0;
RST = 1;
inputbyte(ucAddr); //地址,命令
ucDa = outputbyte(); //读1Byte数据
CLK = 1;
RST =0;
return(ucDa);
}
void DS1302_init()
{
if(read(0xc1)!=0x82) //如果1302掉电,写入下面的初始值
{
write(0x8e,0x00);//关闭写保护
write(0x80,0x22); //设置秒
write(0x82,0x22);//设置分钟
write(0x84,0x22); // 小时
write(0x90,0xa5);//涓流充电
write(0xc0,0x82);//掉电标志位
}
}
void decode(void)//红外码值处理函数
{
unsigned char i, j, k;
unsigned char cord,value;
k=1;
for(i=0;i<4;i++) //处理4个字节
{
for ( j=1; j<=8; j++) //处理1个字节8位
{
cord=irdata[k];
if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差
{
value=value|0x80;
}
else
{
value=value;
}
if(j<8)
{
value=value>>1;
}
k++;
}
ircode[i]=value;
value=0;
}
if(ircode[2]==~ircode[3])
decode_ok=1;//解码完毕后标志位置1
}
void Display(unsigned char a,b,c) //数码管显示
{
static unsigned char i;
LEDPORT=0xff;
switch (i)
{
case 0: if(a/16) LEDPORT=tab[a/16]˙ else LEDPORT=tab[10]˙D1=0;D2=D3=D4=D5=D6=1; break;
case 1: LEDPORT=tab [a%16]; D2=0;D1=D3=D4=D5=D6=1; break;
case 2: LEDPORT=tab [b/16]; D3=0;D1=D2=D4=D5=D6=1; break;
case 3: LEDPORT=tab [b%16]; D4=0;D1=D2=D3=D5=D6=1; break;
case 4: LEDPORT=tab [c/16]; D6=0;D1=D2=D3=D4=D5=1; break;
case 5: LEDPORT=tab [c%16]; D5=0;D1=D3=D4=D6=D2=1; break;
}
i++;
if(i==6)i=0;
}
void ir_work()
{
if(ircode[2]==0x1e)
test=!test;
if(ircode[2]==0x05)
{
set++;
if(set==4)
set=0;
}
if(set==1)
{
if(ircode[2]==0x02|ircode[2]==0x06) //hour
{
temp=(read(0x85)/16)*10+read(0x85)%16;
temp++;if(temp==24)temp=0;
write(0x84,(temp/10)*16+temp%10);
}
if(ircode[2]==0x08|ircode[2]==0x04)
{
temp=(read(0x85)/16)*10+read(0x85)%16;
temp--;if(temp==-1)temp=23;
write(0x84,(temp/10)*16+temp%10);
}
}
if(set==2) //min
{
if(ircode[2]==0x02|ircode[2]==0x06)
{
temp=(read(0x83)/16)*10+read(0x83)%16;
temp++;if(temp==60)temp=0;
write(0x82,(temp/10)*16+temp%10);
}
if(ircode[2]==0x08|ircode[2]==0x04)
{
temp=(read(0x83)/16)*10+read(0x83)%16;
temp--;if(temp==-1)temp=59;
write(0x82,(temp/10)*16+temp%10);
}
}
if(set==3) //sec
{
if(ircode[2]==0x02|ircode[2]==0x06)
{
temp=(read(0x81)/16)*10+read(0x81)%16;
temp++;if(temp==60)temp=0;
write(0x80,(temp/10)*16+temp%10);
}
if(ircode[2]==0x08|ircode[2]==0x04)
{
temp=(read(0x81)/16)*10+read(0x81)%16;
temp--;if(temp==-1)temp=59;
write(0x80,(temp/10)*16+temp%10);
}
}
decode_ok=0;
}
void main()
{
Timer_Init();
DS1302_init();
dot=0xff;
flag=1;
while(1)
{
hour= read(0x85);
min = read(0x83);
sec = read(0x81);
/* if((hour==0x08)&&(min==0x00) ) //可以设置为每天的某个时间打开GPS对一下时间再关掉,这里设置的是8:00
ES=1;
else
ES=0;*/
if(flag==1&&cnt>500) //上电稍做延时再打开串口,防止数码管显示出错
{
flag=0;
cnt=0;
ES=1;
}
if((rev_stop==1)&&(buf[1]=='M')&&(buf[2]=='C')&&(buf[3]==','))//如果接收到GPRMC 就把GPS接收到的时间写入DS1302
{
ES=0;
hour= (buf [4]-0x30)* 16+ buf[5] -0x30;
min= (buf [6]-0x30)* 16+ buf[7]-0x30;
sec= (buf[8]-0x30)* 16+ buf[9]-0x30;
hour= hour / 16 * 10 + hour % 16;
hour= (hour+8) % 24; //UTC Time换算成北京时间
hour=hour/10*16+hour%10;
write(0x84,hour);
write(0x82,min);
write(0x80,sec);
ES=1;
rev_stop=0;
}
if( sec== (buf[8]-0x30)* 16+ buf[9]-0x30) //用左上角的小点显示有无GPS信号
dot=0xdf;
else
dot=0xff;
if(irok) //如果接收到正确的红外信号后进行红外处理
{
decode();
irok=0;
}
if(decode_ok) //如果解码正确就进入调时程序
{
ir_work();
}
if(test) //需要时可以遥控关闭屏幕
{
ET2=0;
P0=0xff;
LED1=LED2=1;
}
else
{
ET2=1;
}
}
}
void int0 (void) interrupt 0 //外部中断0服务函数 用于红外解码
{
static unsigned char i; //接收红外信号处理
static bit startflag; //是否开始处理标志位
if(startflag)
{
if(irtime<63&&irtime>=33)//引导码 TC9012的头码,9ms+4.5ms
i=0;
irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1
irtime=0;
i++;
if(i==33)
{
irok=1;
i=0;
}
}
else
{
irtime=0;
startflag=1;
}
}
void timer0 (void) interrupt 1 //定时器0中断服务函数 ,红外解码
{
irtime++; //计算2个下降沿之间的时间
}
void Uart_Receive(void) interrupt 4 //串口中断,用于GPS数据接收
{
unsigned char ch,num;
ES = 0;
if (RI) //如果接收完成则进入
{
ch = SBUF;
|