?? rtc.c
字號:
//***************************FileName:RTC.C************************//
//***************************ICCAVR V6.30編譯**********************//
#include <io8535v.h> //寄存器定義文件
#include <macros.h> //使用到宏
#define uchar unsigned char //數(shù)據(jù)類型定義
#define uint unsigned char //數(shù)據(jù)類型定義
#define SD2303 0x64 //SD2303器件IIC識別碼
uchar Table[12]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x38,0x76};
//顯示數(shù)據(jù)表 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; //數(shù)據(jù)應(yīng)答標(biāo)志
void DelayMs(uint i) //延時函數(shù)1
{uchar j;
for(;i!=0;i--)
{for(j=2000;j!=0;j--) {;}}
}
void Display(uchar *p) //顯示函數(shù)
{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) //延時函數(shù)2
{for(;i!=0;i--) NOP();}
void SetSCL(uchar i) //IIC時鐘線SCL設(shè)置
{if(i==1) PORTB=PORTB|0x01;
else PORTB=PORTB&0xFE;}
void SetSDA(uchar i) //IIC數(shù)據(jù)線SDA設(shè)置
{if(i==1) PORTB=PORTB|0x02;
else PORTB=PORTB&0xFD;}
//SCL=PB^0; SD2303時鐘線
//SDA=PB^1; SD2303數(shù)據(jù)線
//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() //單片機應(yīng)答信號
{SetSDA(0);
SetSCL(1);
NOPNOP(50);
SetSCL(0);
SetSDA(1);
}
void Nack() //單片機非應(yīng)答信號
{SetSDA(1);
SetSCL(1);
NOPNOP(50);
SetSCL(0);
SetSDA(0);
}
void Check_Ack() //器件應(yīng)答信號檢查
{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總線寫一字節(jié)數(shù)據(jù)
{uchar i;
for(i=0;i<8;i++)
{if((Data&0x80)>0)
Write_Bit1();
else
Write_Bit0();
Data<<=1;
}
}
uchar Read_Byte() //從IIC總線讀一字節(jié)數(shù)據(jù)
{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個字節(jié)子程序**********************//
//函數(shù)參數(shù)說明:
//Slave:IIC器件地址,如上文定義的SD2303
//Address:起始地址
//Array:讀數(shù)據(jù)存放的數(shù)組
//Number:讀取的字節(jié)數(shù)
void Write_Nbyte(uchar Slave,uchar Address,uchar *Array,uchar Number)
{uchar k;
writ:do //開始->寫IIC器件地址->檢查應(yīng)答位
{Start();
Write_Byte(Slave);
Check_Ack();
}while(F_Flag==1);
do
{Write_Byte(Address<<4); //送起始地址->檢查應(yīng)答位
Check_Ack();
}while(F_Flag==1);
for(k=0;k<Number;k++) //寫Number個數(shù)據(jù)
{Write_Byte(*Array);
Array++;
Check_Ack();} //檢查應(yīng)答位
Stop();
}
//****************************寫一個字節(jié)子程序**********************//
//函數(shù)參數(shù)說明:
//Slave:IIC器件地址,如上文定義的SD2303
//Address:IIC器件寄存器地址
//Data:數(shù)據(jù)
void Write_1byte(uchar Slave,uchar Address,uchar Data)
{writ:do //開始->寫IIC器件地址->檢查應(yīng)答位
{Start();
Write_Byte(Slave);
Check_Ack();
}while(F_Flag==1);
do
{Write_Byte(Address<<4); //送起始地址->檢查應(yīng)答位
Check_Ack();
}while(F_Flag==1);
Write_Byte(Data);
Check_Ack(); //檢查應(yīng)答位
Stop(); //停止信號
}
//***************************讀N個字節(jié)子程序***********************//
//函數(shù)參數(shù)說明:
//Slave:IIC器件地址,如上文定義的SD2303
//Address:起始地址
//Array:讀數(shù)據(jù)存放的數(shù)組
//Number:讀取的字節(jié)數(shù)
void Read_Nbyte(uchar Slave,uchar Address,uchar *Array,uchar Number)
{uchar data0,x;
//第一步:開始信號->寫IIC器件地址->檢查應(yīng)答位
do{Start();Write_Byte(Slave);Check_Ack();}while(F_Flag==1);
//第二步:寫起始地址->檢查應(yīng)答位
do {Write_Byte(Address<<4);Check_Ack();}while(F_Flag==1);
//第三步:開始信號->寫IIC器件地址+1(表示讀)->檢查應(yīng)答位
do{Start();Write_Byte(Slave+1);Check_Ack();}while(F_Flag==1);
//第四步:讀N字節(jié),每讀完一字節(jié)發(fā)一個Ack應(yīng)答,最后一字節(jié)發(fā)Nack
for(x=0;x<Number;x++)
{data0=Read_Byte();*Array=data0;Array++;
if(x<(Number-1)) { Ack(); }}
Nack();
//第五步:發(fā)停止信號,結(jié)束讀操作
Stop();
}
//***************************按鍵處理程序**************************//
//說明:為簡化程序設(shè)計,此程序不保證輸入的時間數(shù)據(jù)的合理性。
void Key_Process(void)
{uchar temp1[17]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//輸入數(shù)據(jù)格式依次為年、月、日、星期、小時和分鐘
uchar temp2[7]={0,0,0,0,0,0,0,};
uchar temp3[3]={0,0,0xff};
//輸入數(shù)據(jù)格式依次為小時和分鐘
uchar Key;
uchar *Flag;
uchar i;
Flag=temp1;
if(PIND!=0xff)
{DelayMs(20); //延時去抖
if(PIND!=0xff)
Key=PINB;
if(Key==0xfe) //"時間設(shè)置"鍵按下
{temp1[0]|=0x80; //年高位設(shè)置提示
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; //上一位去掉小數(shù)點顯示
(*Flag)|=0x80; //當(dāng)前位加上小數(shù)點顯示
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; //當(dāng)前位加上小數(shù)點顯示
(*(Flag+1))&=0x7f; //下一位去掉點小數(shù)點顯示
break;
case 0x40:Enter_Flag=1;break;//"確定"鍵處理
// case 0x80:Enter_Flag=1;break; //測試用
default:break;}
}
Enter_Flag=0; //按鍵狀態(tài)恢復(fù)
temp2[0]=0x00; //秒,默認(rèn)從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); //初始化設(shè)定時間
}
if(Key==0xfd) //"鬧鈴設(shè)置"鍵按下
{temp1[9]|=0x80;
Flag=temp1+9; //定時小時高位設(shè)置提示
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; //上一位去掉小數(shù)點顯示
(*Flag)|=0x80; //當(dāng)前位加上小數(shù)點顯示
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; //當(dāng)前位加上小數(shù)點顯示
(*(Flag+1))&=0x7f; //下一位去掉小數(shù)點顯示
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; //分?jǐn)?shù)據(jù)處理,去掉小數(shù)點
temp3[1]=((temp1[9]<<4)|temp1[10])&0x7f; //時數(shù)據(jù)處理,去掉小數(shù)點
if((temp3[0]<0x60)&&(temp3[1]<0x24)) //判斷是否為合法時間
{Write_1byte(SD2303,0x0e,0b10110000); //開啟鬧鈴使能
Write_1byte(SD2303,0x0f,0b00101000); //開始中斷使能
Write_Nbyte(SD2303,0x08,temp3,3);} //初始化鬧鈴設(shè)置
else
Write_1byte(SD2303,0x0e,0b00110000); //取消鬧鈴功能
}
}
}
//***************************DS1722函數(shù)開始************************//
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接口寫數(shù)據(jù)函數(shù)*****************//
//函數(shù)參數(shù)說明:
//Address:DS1722寄存器地址
//Data:寫入的數(shù)據(jù)
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接口讀數(shù)據(jù)函數(shù)*****************//
//函數(shù)參數(shù)說明:
//Address:DS1722寄存器地址
//返回值:讀取的溫度數(shù)據(jù)
uchar DSRead_Byte(uchar Address)
{uchar clear;
uchar Data;
PORTB=PORTB|0x10;
SPDR=Address;
while(!(SPSR&0x80)) {;}
clear=SPSR;
clear=SPDR;
SPDR=Address; //發(fā)空數(shù)據(jù)
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位分辨率自由轉(zhuǎn)換模式
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); //讀取中斷標(biāo)志位
if(SD&0x02) PORTD=PORTD|0x80; //響鈴1分鐘
else PORTD=PORTD&0x7F; //關(guān)閉鬧鈴
DS=DSRead_Byte(0x02); //讀取溫度值
Convert(DS,time);
Display(time); //時間顯示
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -