?? rtc.c
字號:
/*******************************************
文件:RTC.C
環(huán)境:編譯為ICC AVR6.25A,仿真為AVR Studio4.10
硬件:ATMEGA16芯片
日期:2006年12月10日
功能:驅(qū)動開發(fā)板上的DS1302時鐘芯片
備注:參考《AVR系列單片機C語言編程與應(yīng)用實例》(清華大學(xué)出版社)
/******************************************/
//#include <iom16v.h> //包含型號頭文件
//#include <macros.h> //包含"位"操作頭文件
//#include <stdio.h> //標準輸入輸出頭文件
//#include <AVR_PQ1A.h> //包含自定義常量頭文件
//#include "YJ12864.C"
//#include "YJ1602.C" //包含1602液晶函數(shù)文件
//#include "MKEY.C" //包含矩陣鍵盤函數(shù)文件
/*******************************************
函數(shù)名稱: DS1302_init
功 能: 初始化DS1302的數(shù)據(jù)接口
參 數(shù): 無
返回值 : 無
/********************************************/
void DS1302_portinit(void)
{
DDRB|=BIT(RTC_CLK)|BIT(RTC_DATA)|BIT(RTC_CS);//將時鐘端(RTC_CLK)數(shù)據(jù)端(RTC_DATA)片選端(RTC_CS)設(shè)置為輸出
}
/*******************************************
函數(shù)名稱: DS1302_writeB
功 能: 向DS1302寫入一個字節(jié)數(shù)據(jù)(沒有RST操作)
參 數(shù): byte--要寫入的數(shù)據(jù)
返回值 : 無
/********************************************/
void DS1302_writeB(uchar byte)
{
uchar i;
for(i=0;i<8;i++) //8位數(shù)據(jù)計數(shù)
{
PORTB&=~BIT(RTC_CLK); //拉低時鐘端
if(byte&0x01) //當前位是否是1
{
PORTB|=BIT(RTC_DATA); //當前位是1,拉高數(shù)據(jù)端
}
else
{
PORTB&=~BIT(RTC_DATA); //當前位是0,拉低數(shù)據(jù)端
}
Delayus(10); //調(diào)整時鐘和脈沖寬度
PORTB|=BIT(RTC_CLK); //時鐘上升沿(DS1302采樣數(shù)據(jù))
byte>>=1; //數(shù)據(jù)右移1位,為送出新數(shù)據(jù)位做準備
}
}
/*******************************************
函數(shù)名稱: DS1302_readB
功 能: 從DS1302讀出一個字節(jié)數(shù)據(jù)(沒有RST操作)
參 數(shù): 無
返回值 : byte--讀出的數(shù)據(jù)
/********************************************/
uchar DS1302_readB(void)
{
uchar i,byte=0;
DDRB&=~BIT(RTC_DATA); //將數(shù)據(jù)端口設(shè)置為輸入
PORTB&=~BIT(RTC_DATA); //無上拉電阻
for(i=0;i<8;i++) //8位數(shù)據(jù)計數(shù)
{
byte>>=1; //保存讀入的數(shù)據(jù)位
PORTB|=BIT(RTC_CLK); //時鐘上升沿
Delayus(10); //延時,調(diào)整時鐘脈沖寬度
PORTB&=~BIT(RTC_CLK); //時鐘下降沿,DS1302輸出數(shù)據(jù)位
Delayus(10); //等待數(shù)據(jù)變化(MEGA16太快,必須等待DS1302的數(shù)據(jù)位輸出,否則不能正確讀出)
if(PINB&BIT(RTC_DATA)) //當前位是否是高電平
{
byte|=BIT(PB7); //是高電平就將返回數(shù)據(jù)的當前位置1
}
else
{
byte&=~BIT(PB7); //是低電平就將返回數(shù)據(jù)的當前位置0
}
}
DDRB|=BIT(RTC_DATA); //最后將數(shù)據(jù)端口設(shè)置為輸出
return byte; //返回讀出的數(shù)據(jù)
}
/*******************************************
函數(shù)名稱: DS1302_writeD
功 能: 向DS1302的某個地址寫入一個字節(jié)數(shù)據(jù)
參 數(shù): addr--地址值(寄存器或RAM)
data--要寫入的地址
返回值 : 無
/********************************************/
void DS1302_writeD(uchar addr,uchar data)
{
PORTC&=~BIT(RTC_CS); //拉低片選端
PORTB&=~BIT(RTC_CLK); //拉低時鐘端
Delayus(10);
PORTC|=BIT(RTC_CS); //拉高片選端
Delayus(10); //調(diào)整片選脈沖
DS1302_writeB(addr); //寫入操作命令(地址)
Delayus(10);
PORTB&=~BIT(RTC_CLK); //拉低時鐘端
Delayus(10);
DS1302_writeB(data); //寫入數(shù)據(jù)
PORTB&=~BIT(RTC_CLK); //拉低時鐘端
Delayus(10); //調(diào)整片選脈沖
PORTC&=~BIT(RTC_CS); //拉低片選端
}
/*******************************************
函數(shù)名稱: DS1302_readD
功 能: 從DS1302的某個地址讀出一個字節(jié)數(shù)據(jù)
參 數(shù): addr--地址值(寄存器或RAM)
返回值 : data--讀出的數(shù)據(jù)
/********************************************/
uchar DS1302_readD(uchar addr)
{
uchar data;
PORTC&=~BIT(RTC_CS); //拉低片選端
PORTB&=~BIT(RTC_CLK); //拉低時鐘端
Delayus(10);
PORTC|=BIT(RTC_CS); //拉高片選端
Delayus(10); //調(diào)整片選脈沖
DS1302_writeB(addr); //寫入操作命令(地址)
Delayus(10);
data=DS1302_readB(); //讀出數(shù)據(jù)
Delayus(10);
PORTB&=~BIT(RTC_CLK); //拉低時鐘端
PORTC&=~BIT(RTC_CS); //拉低片選端
return data; //返回讀出的數(shù)據(jù)
}
/*******************************************
函數(shù)名稱: DS1302_setT
功 能: 設(shè)置DS1302的時間
參 數(shù): ptTimeD--設(shè)置時間數(shù)組指針
返回值 : 無
/********************************************/
void DS1302_setT(uchar ptTimeD[])
{
uchar i;
uchar addr = 0x80; //寫入地址從秒寄存器開始
DS1302_writeD(C_WP|WR,UPROTECT); //控制命令,WP位為0,允許寫操作
Delayms(5);
for(i=0;i<7;i++)
{
DS1302_writeD(addr|WR,ptTimeD[i]); // 秒 分 時 日 月 星期 年
addr+=2;
Delayms(1);
}
DS1302_writeD(C_WP|WR,PROTECT); //控制命令,WP位為1,不允許寫操作
}
/*******************************************
函數(shù)名稱: DS1302_getT
功 能: 讀取DS1302的當前時間
參 數(shù): time[]--讀取的時間數(shù)組
返回值 : 無
/********************************************/
void DS1302_getT(uchar time[])
{
uchar i;
uchar addr = 0x80; //讀取地址從秒寄存器開始
for(i=0;i<7;i++)
{
time[i]=DS1302_readD(addr|RD); // 秒 分 時 日 月 星期 年
addr+=2;
}
PORTB&=~BIT(RTC_CLK); //拉低時鐘端(時鐘端在不操作時為低)
}
/*******************************************
函數(shù)名稱: DS1302_check
功 能: 檢測DS1302是否正常工作
參 數(shù): 無
返回值 : exist--為TRUE為檢測到DS1302,為FALSE為沒檢測到
/********************************************/
uchar DS1302_check(void)
{
uchar exist;
DS1302_writeD(C_WP|WR,UPROTECT); //寫入寫允許命令
DS1302_writeD(C_RAMBASE|WR,0xA5); //RAM0寫入0xA5
exist=DS1302_readD(C_RAMBASE|RD); //讀取RAM0
if(exist==0xA5)
{
exist=TRUE; //如果讀取值與寫入值相等,返回TRUE
}
else
{
exist=FALSE; //如果讀取值與寫入值不相等,返回FALSE
}
return exist;
}
/*******************************************
函數(shù)名稱: DS1302_init
功 能: 初始化DS1302
參 數(shù): 無
返回值 : 無
/********************************************/
void DS1302_init(void)
{
DS1302_writeD(C_WP|WR,UPROTECT); //寫入寫允許命令
DS1302_writeD(C_SEC|WR,CLK_START); //啟動振蕩器,DS1302開始工作
DS1302_writeD(C_WP|WR,PROTECT); //控制命令,WP位為1,不允許寫操作
}
/*******************************************
函數(shù)名稱: BCD_ASCII
功 能: 將壓縮BCD碼轉(zhuǎn)換成ascii碼
參 數(shù): BCD--將要轉(zhuǎn)換的壓縮BCD碼
ptasc--轉(zhuǎn)換后的ASCII碼數(shù)組指針
返回值 : 無
/********************************************/
void BCD_ASCII(uchar BCD,uchar *ptasc)
{
*ptasc=BCD/16|0x30; //轉(zhuǎn)換十位
*(ptasc+1)=BCD&0x0F|0x30; //轉(zhuǎn)換個位
}
/*******************************************
函數(shù)名稱: Disp_time
功 能: 在1602液晶上顯示當前時間(第1行格式:年-月-日 星期;第2行格式:時-分-秒)
參 數(shù): time[]--時間數(shù)組
返回值 : 無
/********************************************/
void Disp_time(uchar time[])
{
uchar i,asc[2];
//uchar line1[11]={0,0,'-',0,0,'-',0,0,' ',0,'\0'};//顯示第1行的字符數(shù)組
// uchar line2[9]={0,0,':',0,0,':',0,0,'\0'}; //顯示第2行的字符數(shù)組
uchar linex1[5]={' ','0',' ','0','\0'};//顯示第1行的字符數(shù)組
uchar linex1_1[5]={' ','0',' ','0','\0'};//顯示第1行的字符數(shù)組
uchar linex2[5]={' ',0,' ',0,'\0'};//顯示第1行的字符數(shù)組
uchar linex2_2[3]={' ','0','\0'};//顯示第1行的字符數(shù)組
uchar linex3[17]={' ',0,' ',0,' ',':',' ','0',' ','0',' ',':',' ','0',' ','0','\0'};//顯示第1行的字符數(shù)組
// uchar linex4[11]={'\0'};//顯示第1行的字符數(shù)組
/*
for(i=0;i<3;i++) //為第2行的字符數(shù)組賦值
{
BCD_ASCII(time[2-i],asc);
line2[i*3]=asc[0]&0x7F;
line2[i*3+1]=asc[1];
} */
BCD_ASCII(time[0],asc); //秒 //為第1行的年賦值
linex3[13]=asc[0];
linex3[15]=asc[1];
BCD_ASCII(time[1],asc); //分 //為第1行的年賦值
linex3[7]=asc[0];
linex3[9]=asc[1];
BCD_ASCII(time[2],asc); //時 //為第1行的年賦值
linex3[1]=asc[0];
linex3[3]=asc[1];
BCD_ASCII(time[6],asc); //年 //為第1行的年賦值
linex1[1]=asc[0];
linex1[3]=asc[1];
BCD_ASCII(time[4],asc); //月 //為第1行的年賦值
linex1_1[1]=asc[0];
linex1_1[3]=asc[1];
BCD_ASCII(time[3],asc); //日 //為第1行的年賦值
linex2[1]=asc[0];
linex2[3]=asc[1];
BCD_ASCII(time[5],asc); //星期 //為第1行的年賦值
linex2_2[1]=asc[1];
while(LCD12864_readBF());
LCD12864_gotoXY(1,0); //第1行,第1列顯示
// Delayms(200);
LCD12864_sendstr(" 2 0");
LCD12864_sendstr(linex1);
LCD12864_sendstr("年");
LCD12864_sendstr(linex1_1);
LCD12864_sendstr("月");
// while(LCD12864_readBF());
LCD12864_gotoXY(2,0); //第2行,第3列顯示
// Delayms(200);
LCD12864_sendstr(linex2);
LCD12864_sendstr("號");
LCD12864_sendstr(" 星期");
LCD12864_sendstr(linex2_2);
// while(LCD12864_readBF());
LCD12864_gotoXY(3,0); //第2行,第3列顯示
// Delayms(200);
LCD12864_sendstr(linex3);
while(LCD12864_readBF());
LCD12864_gotoXY(4,2); //第2行,第3列顯示
// Delayms(200);
LCD12864_sendstr("4 取消");
/*
BCD_ASCII(time[6],asc); //為第1行的年賦值
line1[0]=asc[0];
line1[1]=asc[1];
BCD_ASCII(time[4],asc); //為第1行的月賦值
line1[3]=asc[0];
line1[4]=asc[1];
BCD_ASCII(time[3],asc); //為第1行的日賦值
line1[6]=asc[0];
line1[7]=asc[1];
BCD_ASCII(time[5],asc); //為第1行的星期賦值
line1[9]=asc[1];
while(LCD12864_readBF());
LCD12864_gotoXY(2,1); //第1行,第1列顯示
// Delayms(200);
LCD12864_sendstr("20");
LCD12864_sendstr(line1);
while(LCD12864_readBF());
LCD12864_gotoXY(3,2); //第2行,第3列顯示
// Delayms(200);
LCD12864_sendstr(line2);
LCD12864_gotoXY(4,2); //第2行,第3列顯示
// Delayms(200);
LCD12864_sendstr("4 取消");
*/
/*
while(LCD1602_readBF());
LCD1602_gotoXY(1,2); //第1行從第3個位置開始顯示
LCD1602_sendstr("20"); //將07年顯示為2007的形式
LCD1602_sendstr(line1); //第1行顯示
while(LCD1602_readBF());
LCD1602_gotoXY(2,4); //第2行從第5個位置開始顯示
LCD1602_sendstr(line2); //第2行顯示
*/
}
/*******************************************
函數(shù)名稱: main
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -