Rtc._c
上传用户:rbltsz
上传日期:2007-09-19
资源大小:2509k
文件大小:12k
- //***************************FileName:RTC.C************************//
- //***************************ICCAVR V6.30编译**********************//
- #include <io8535v.h> //寄存器定义文件
- #include <macros.h> //使用到宏
- #define uchar unsigned char //数据类型定义
- #define uint unsigned char //数据类型定义
- #define SD2303 0x64 //SD2303器件IIC识别码
- uchar Table[12]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x38,0x76};
- //显示数据表 0 1 2 3 4 5 6 7 8 9 L H
- uchar Data[4]={0,0,0,0}; //DS1722
- uchar Enter_Flag; //确定
- uchar F_Flag; //数据应答标志
- void DelayMs(uint i) //延时函数1
- {uchar j;
- for(;i!=0;i--)
- {for(j=2000;j!=0;j--) {;}}
- }
- void Display(uchar *p)
- {uchar i,sel=0x00;
- for(i=0;i<16;i++)
- {PORTC=sel;
- PORTA=Table[p[i]];
- DelayMs(10);
- sel=sel<<1;
- }
- }
-
- void NOPNOP(uchar i) //延时函数2
- {for(;i!=0;i--) NOP();}
- void SetSCL(uchar i) //IIC时钟线SCL设置
- {if(i==1) PORTB=PORTB|0x01;
- else PORTB=PORTB&0xFE;}
-
- void SetSDA(uchar i) //IIC数据线SDA设置
- {if(i==1) PORTB=PORTB|0x02;
- else PORTB=PORTB&0xFD;}
-
- //SCL=PB^0; SD2303时钟线
- //SDA=PB^1; SD2303数据线
- //INTRB=PB^3; SD2303中断线A
- //INTRA=PB^2; SD2303中断线B
- void Start() //IIC总线开始信号
- {SetSDA(1);
- SetSCL(1);
- NOPNOP(50);
- SetSDA(0);
- NOPNOP(50);
- SetSCL(0);
- }
- void Stop() //IIC总线停止信号
- {SetSDA(0);
- SetSCL(1);
- NOPNOP(50);
- SetSDA(1);
- NOPNOP(50);
- SetSCL(0);
- }
- void Ack() //单片机应答信号
- {SetSDA(0);
- SetSCL(1);
- NOPNOP(50);
- SetSCL(0);
- SetSDA(1);
- }
- void Nack() //单片机非应答信号
- {SetSDA(1);
- SetSCL(1);
- NOPNOP(50);
- SetSCL(0);
- SetSDA(0);
- }
- void Check_Ack() //器件应答信号检查
- {SetSDA(1);
- SetSCL(1);
- F_Flag=0;
- DDRB=DDRB&0xFD;
- if((PINB&0x02)==0)
- {SetSCL(0);
- NOPNOP(50);}
- else
- {F_Flag=1;
- SetSCL(0);
- NOPNOP(50);}
- DDRB=DDRB|0x02;
- }
- void Write_Bit0() //向IIC总线写0
- {SetSDA(0);
- SetSCL(1);
- NOPNOP(50);
- SetSCL(0);
- }
- void Write_Bit1() //向IIC总线写1
- {SetSDA(1);
- SetSCL(1);
- NOPNOP(50);
- SetSCL(0);
- SetSDA(0);
- }
- void Write_Byte(uchar Data) //向IIC总线写一字节数据
- {uchar i;
- for(i=0;i<8;i++)
- {if((Data&0x80)>0)
- Write_Bit1();
- else
- Write_Bit0();
- Data<<=1;
- }
- }
- uchar Read_Byte() //从IIC总线读一字节数据
- {uchar nn=0xff;
- uchar j;
- for (j=0;j<8;j++)
- {SetSDA(1);
- SetSCL(1);
- DDRB=DDRB&0xFB;
-
- if((PINB&0x02)==0)
- {nn<<=1;
- nn=(nn&0xfe);
- SetSCL(0);}
- else
- {nn<<=1;
- nn=(nn|0x01);
- SetSCL(0);}
- }
- DDRB=DDRB|0x02;
- return(nn);
- }
- //****************************写N个字节子程序**********************//
- //函数参数说明:
- //Slave:IIC器件地址,如上文定义的SD2303
- //Address:起始地址
- //Array:读数据存放的数组
- //Number:读取的字节数
- void Write_Nbyte(uchar Slave,uchar Address,uchar *Array,uchar Number)
- {uchar k;
- writ:do //开始->写IIC器件地址->检查应答位
- {Start();
- Write_Byte(Slave);
- Check_Ack();
- }while(F_Flag==1);
- do
- {Write_Byte(Address<<4); //送起始地址->检查应答位
- Check_Ack();
- }while(F_Flag==1);
- for(k=0;k<Number;k++) //写Number个数据
- {Write_Byte(*Array);
- Array++;
- Check_Ack();} //检查应答位
- Stop();
- }
- //****************************写一个字节子程序**********************//
- //函数参数说明:
- //Slave:IIC器件地址,如上文定义的SD2303
- //Address:IIC器件寄存器地址
- //Data:数据
- void Write_1byte(uchar Slave,uchar Address,uchar Data)
- {writ:do //开始->写IIC器件地址->检查应答位
- {Start();
- Write_Byte(Slave);
- Check_Ack();
- }while(F_Flag==1);
- do
- {Write_Byte(Address<<4); //送起始地址->检查应答位
- Check_Ack();
- }while(F_Flag==1);
- Write_Byte(Data);
- Check_Ack(); //检查应答位
- Stop(); //停止信号
- }
- //***************************读N个字节子程序***********************//
- //函数参数说明:
- //Slave:IIC器件地址,如上文定义的SD2303
- //Address:起始地址
- //Array:读数据存放的数组
- //Number:读取的字节数
- void Read_Nbyte(uchar Slave,uchar Address,uchar *Array,uchar Number)
- {uchar data0,x;
- //第一步:开始信号->写IIC器件地址->检查应答位
- do{Start();Write_Byte(Slave);Check_Ack();}while(F_Flag==1);
- //第二步:写起始地址->检查应答位
- do {Write_Byte(Address<<4);Check_Ack();}while(F_Flag==1);
- //第三步:开始信号->写IIC器件地址+1(表示读)->检查应答位
- do{Start();Write_Byte(Slave+1);Check_Ack();}while(F_Flag==1);
- //第四步:读N字节,每读完一字节发一个Ack应答,最后一字节发Nack
- for(x=0;x<Number;x++)
- {data0=Read_Byte();*Array=data0;Array++;
- if(x<(Number-1)) { Ack(); }}
- Nack();
- //第五步:发停止信号,结束读操作
- Stop();
- }
- //***************************按键处理程序**************************//
- //说明:为简化程序设计,此程序不保证输入的时间数据的合理性。
- void Key_Process(void)
- {uchar temp1[17]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
- //输入数据格式依次为年、月、日、星期、小时和分钟
- uchar temp2[7]={0,0,0,0,0,0,0,};
- uchar temp3[3]={0,0,0xff};
- //输入数据格式依次为小时和分钟
- uchar Key;
- uchar *Flag;
- uchar i;
- Flag=temp1;
- if(PIND!=0xff)
- {DelayMs(20); //延时去抖
- if(PIND!=0xff)
- Key=PINB;
- if(Key==0xfe) //"时间设置"键按下
- {temp1[0]|=0x80; //年高位设置提示
- while(!Enter_Flag) //直到按下确定键方停止
- {for(i=0;i<50;i++)
- Display(temp1); //显示和延时
- Key=~PIND;
- switch(Key)
- {case 0x04: //"+"键处理
- (*Flag)++;
- if(((*Flag)&0x7f)==10) *Flag=0|0x80;
- break;
- case 0x08: //"-"键处理
- if(((*Flag)&0x7f)==0) *Flag=10|0x80;
- (*Flag)--;
- break;
- case 0x10: //"下一位"键处理
- Flag++;
- (*(Flag-1))&=0x7f; //上一位去掉小数点显示
- (*Flag)|=0x80; //当前位加上小数点显示
- if(Flag==temp1+13)
- {Flag=temp1;
- (*Flag)|=0x80;
- (*(Flag+13))&=0x7f;}
- break;
- case 0x20: //"上一位"键处理
- if(Flag==temp1)
- {(*Flag)&=0x7f;
- Flag=temp1+13;
- (*Flag)|=0x80;}
- else Flag--;
- (*Flag)|=0x80; //当前位加上小数点显示
- (*(Flag+1))&=0x7f; //下一位去掉点小数点显示
- break;
- case 0x40:Enter_Flag=1;break;//"确定"键处理
- // case 0x80:Enter_Flag=1;break; //测试用
- default:break;}
-
- }
- Enter_Flag=0; //按键状态恢复
- temp2[0]=0x00; //秒,默认从00开始计时
- temp2[1]=(temp1[11]<<4)|temp1[12];//分
- temp2[2]=(temp1[9]<<4)|temp1[10]; //时
- temp2[3]=temp1[8]; //周
- temp2[4]=(temp1[6]<<4)|temp1[7]; //日
- temp2[5]=(temp1[4]<<4)|temp1[5]; //月
- temp2[6]=(temp1[2]<<4)|temp1[3]; //年
- Write_Nbyte(SD2303,0x00,temp2,7); //初始化设定时间
- }
- if(Key==0xfd) //"闹铃设置"键按下
- {temp1[9]|=0x80;
- Flag=temp1+9; //定时小时高位设置提示
- while(!Enter_Flag) //直到按下确定键方停止
- {for(i=0;i<50;i++)
- Display(temp1);
- Key=~PINB;
- switch(Key)
- {case 0x04: //"+"按键处理
- (*Flag)++;
- if(((*Flag)&0x7f)==10) *Flag=0|0x80;
- break;
- case 0x08: //"-"按键处理
- if(((*Flag)&0x7f)==0) *Flag=10|0x80;
- (*Flag)--;
- break;
- case 0x10: //"下一位"按键处理
- Flag++;
- (*(Flag-1))&=0x7f; //上一位去掉小数点显示
- (*Flag)|=0x80; //当前位加上小数点显示
- if(Flag==temp1+13)
- {(*Flag)&=0x7f;
- Flag=temp1+9;
- (*Flag)|=0x80;}
- break;
- case 0x20: //"上一位"按键处理
- if(Flag==temp1+9)
- {(*Flag)&=0x7f;
- Flag=temp1+13;
- (*Flag)|=0x80;}
- else Flag--;
- (*Flag)|=0x80; //当前位加上小数点显示
- (*(Flag+1))&=0x7f; //下一位去掉小数点显示
- break;
- case 0x40:Enter_Flag=1;break;//"确定"键处理
- // case 0x80:Enter_Flag=1;break;//测试用
- default:break;}
-
- }
- Enter_Flag=0;
- temp3[0]=((temp1[11]<<4)|temp1[12])&0x7f; //分数据处理,去掉小数点
- temp3[1]=((temp1[9]<<4)|temp1[10])&0x7f; //时数据处理,去掉小数点
- if((temp3[0]<0x60)&&(temp3[1]<0x24)) //判断是否为合法时间
- {Write_1byte(SD2303,0x0e,0b10110000); //开启闹铃使能
- Write_1byte(SD2303,0x0f,0b00101000); //开始中断使能
- Write_Nbyte(SD2303,0x08,temp3,3);} //初始化闹铃设置
- else
- Write_1byte(SD2303,0x0e,0b00110000); //取消闹铃功能
- }
- }
- }
-
-
- //***************************DS1722函数开始************************//
- void Convert(uchar p1,uchar *p2)
- {uchar temp;
- if(p1&0x80)
- {p2[13]=10; //零下温度用10表示
- p1=0xff-p1;} //温度绝对值
- else
- p2[13]=11; //零上温度用11表示
- p2[14]=p1/10; //温度十位
- p2[15]=p1-p2[14]*10; //温度个位
- }
- //***************************通过SPI接口写数据函数*****************//
- //函数参数说明:
- //Address:DS1722寄存器地址
- //Data:写入的数据
- void DSWrite_Byte(uchar Address,uchar Data)
- {uchar clear;
- PORTB=PORTB|0x10; //使能SPI器件
- SPDR=Address;
- while(!(SPSR&0x80)) {;}
- clear=SPSR;
- clear=SPDR;
- SPDR=Data;
- while(!(SPSR&0x80)) {;}
- clear=SPSR;
- clear=SPDR;
- PORTB=PORTB&0xef;
- }
- //***************************通过SPI接口读数据函数*****************//
- //函数参数说明:
- //Address:DS1722寄存器地址
- //返回值:读取的温度数据
- uchar DSRead_Byte(uchar Address)
- {uchar clear;
- uchar Data;
- PORTB=PORTB|0x10;
- SPDR=Address;
- while(!(SPSR&0x80)) {;}
- clear=SPSR;
- clear=SPDR;
- SPDR=Address; //发空数据
- while(!(SPSR&0x80)) {;}
- clear=SPSR;
- Data=SPDR;
- PORTB=PORTB&0xef;
- return(Data);
- }
-
- void main(void)
- {uchar i;
- uchar time[16]={2,0,0,4,1,2,2,7,1,1,7,3,0,0,0,0};
- uchar Set_Time[7]={0x50,0x30,0x20,0x03,0x05,0x01,0x05};
- //初始化时间 2005-01-05 Wed 20-30-50
- uchar SD,DS;
- uchar SD2303_Controller1=0x00; //禁止中断
- uchar SD2303_Controller2=0x20; //时间格式:24小时制
- DDRA=0xff; //A口输出
- DDRC=0xff; //C口输出
- DDRD=0x80; //D口最高位输出,其他带上拉输入
- PORTD=0x7F;
- DDRB=0xF3; //B口带第2、3位带上拉输入,其他输出
- PORTB=0xF3;
- Write_1byte(SD2303,0x0e,SD2303_Controller1);//写控制字
- Write_1byte(SD2303,0x0f,SD2303_Controller2);//写控制字
- Write_Nbyte(SD2303,0x00,Set_Time,7); //初始化时间
- SPCR=0b01011100;
- DSWrite_Byte(0x80,0xf0); //DS1722 8位分辨率自由转换模式
- while(1)
- {Key_Process(); //按键处理
- Read_Nbyte(SD2303,0x00,Set_Time,7); //读取时间
- time[2]=Set_Time[6]>>4; //年高位;
- time[3]=Set_Time[6]&0x0f; //年低位;
- time[4]=Set_Time[5]>>4; //月高位;
- time[5]=Set_Time[5]&0x0f; //月低位;
- time[6]=Set_Time[4]>>4; //日高位;
- time[7]=Set_Time[4]&0x0f; //日低位;
- time[8]=Set_Time[3]; //星期;
- time[9]=Set_Time[2]>>4; //时高位;
- time[10]=Set_Time[2]&0x0f; //时低位;
- time[11]=Set_Time[1]>>4; //分高位;
- time[12]=Set_Time[1]&0x0f; //分低位;
- time[13]=Set_Time[0]>>4; //秒高位;
- time[14]=Set_Time[0]&0x0f; //秒低位;
- Read_Nbyte(SD2303,0x0f,&SD,1); //读取中断标志位
- if(SD&0x02) PORTD=PORTD|0x80; //响铃1分钟
- else PORTD=PORTD&0x7F; //关闭闹铃
- DS=DSRead_Byte(0x02); //读取温度值
- Convert(DS,time);
- Display(time); //时间显示
- }
- }