C源程序,
main.rar
(3.36 KB, 下载次数: 49)
- #include <reg52.H>
- //--------数码管段选定义--------
- #define LEDPORT P0
- #define uchar unsigned char
- #define uint unsigned int
- //--------数码管位选定义--------
- sbit D1=P2^0;
- sbit D2=P2^1;
- sbit D3=P2^2;
- sbit D4=P2^3;
- sbit D5=P2^4;
- sbit D6=P2^5;
- //--------DS1302接口定义--------
- sbit CLK =P3^7;
- sbit IO =P3^6;
- sbit RST =P3^1;
- //--------状态标记--------
- sbit LED1=P2^6;
- sbit LED2=P2^7;
- sbit ACC0=ACC^0;
- sbit ACC7=ACC^7;
- unsigned char hour,min,sec; //小时、分钟、秒
- bit rev_start,rev_stop; //GPS接收开始、结束标志位
- unsigned char code tab[ ]={
- 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,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;
- /******************************************************************************************
- *函数名称:Timer_Init
- *功能描述:定时器初始化
- ******************************************************************************************/
- 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);
- }
- //--------DS1302初始化--------
- 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 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 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]˙ //最高位"0",消隐字符
- 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];
- D5=0;
- D1=D2=D3=D4=D6=1;
- break;
- case 5:
- LEDPORT=tab [c%16];
- D6=0;
- D1=D3=D4=D5=D2=1;
- break;
- }
- i++;
- if(i==6)i=0;
- }
- /******************************************************************************************
- *函数名称:main
- *功能描述:主函数
- ******************************************************************************************/
- 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
- {
- LED1=1;
- 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=0x7f;
- 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;
- }
- }
- /******************************************************************************************
- *函数名称:timer0
- *功能描述:红外解码计算脉冲宽度
- ******************************************************************************************/
- 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;
- if (ch == 'R') //如果收到字符'
- ,便开始接收
- {
- rev_start = 1;
- rev_stop = 0; //接收停止标志
- }
- if (rev_start == 1) //标志位为1,开始接收
- {
- buf[num++] = ch; //字符存到数组中
- if (ch == '.') //如果接收到换行
- {
- buf[num] = '\n';
- rev_start = 0;
- rev_stop = 1; //接收停止标志
- num = 0;
- }
- }
- }
- RI = 0; //RI清0,重新接收
- ES = 1; //串口1中断允许
- }
- /******************************************************************************************
- *函数名称:Timer2
- *功能描述:定时刷新显示
- ******************************************************************************************/
- void Timer2() interrupt 5 //2mS //用于刷新数码管的显示
- {
- TF2=0; //定时器2必须由软件对溢出标志位清零,硬件不能清零,这里与定时器0和定时器1不同!!!
- switch(set)
- {
- case 0:
- Display(hour,min,sec);
- LED1=0;
- LED2=0;
- break;
- case 1:
- Display(hour,0xaa,0xaa);
- LED1=0;
- LED2=1;
- break;
- case 2:
- Display(0xaa, min,0xaa);
- break;
- case 3:
- Display(0xaa, 0xaa,sec);
- LED1=1;
- LED2=0;
- break;
- }
- cnt++;
- }
复制代码
|