?? ds1302.c
字號:
/******************************
主程序:顯示分鐘和秒;
輔助程序:數碼管顯示;
指導:曾潔
制作人:卜凡濤
完成:2008.3.14
**********************************/
#include <iom16v.h> //包含型號頭文件
#include <macros.h> //包含"位"操作頭文件
#define uchar unsigned char
#define uint unsigned int
#define TRUE 1
#define FALSE 0
#include "xianshi.C" //包含1602液晶函數文件
/******************RTC常量******************/
#define RTC_CLK PC7
#define RTC_DATA PC6
#define RTC_CS PC1
//命令
#define RD 0x01
#define WR 0x00
#define C_SEC 0x80 //秒
#define C_MIN 0x82 //分
#define C_HR 0x84 //時
#define C_DAY 0x86 //日
#define C_MTH 0x88 //月
#define C_WK 0x8A //星期 DATE
#define C_YR 0x8C //年
#define C_WP 0x8E //控制(寫保護)
#define C_CHARGE 0x90 //涓流充電
#define C_BURST 0xBE //時鐘多字節
//配置
#define CLK_HALT 0x80 //停止時鐘控制位 SECOND bit7
#define CLK_START 0x00 //啟動時鐘
#define M12_24 0x80 //12/24小時值選擇位 HOUR bit7
#define PROTECT 0x80 //寫保護控制位 CONTROL bit7
#define UPROTECT 0x00 //寫保護控制位 CONTROL bit7
//涓流充電控制常量
#define TC_D1R2 0xA5 //high 1 Diode +2K Resistors
#define TC_D2R8 0xAB //low 2 Diodes+8K Resistors
#define TC_DISABLED 0x00 //Disabled(TCS<>1010 or DS=00 or RS=00)
//RAM 命令
#define C_RAMBASE 0xC0 //RAM0~RAM30<<1 地址需左移一位
void Delayus(uint US)
{
uint i;
US=US*5/4; //5/4是在8MHz晶振下,通過軟件仿真反復實驗得到的數值
for( i=0;i<US;i++);
}
void Delayms(uint MS)
{
uint i,j;
for( i=0;i<MS;i++)
for(j=0;j<1141;j++); //1141是在8MHz晶振下,通過軟件仿真反復實驗得到的數值
}
/*******************************************
函數名稱: DS1302_init
功 能: 初始化DS1302的數據接口
參 數: 無
返回值 : 無
/********************************************/
void DS1302_portinit(void)
{
DDRC|=BIT(RTC_CLK)|BIT(RTC_DATA)|BIT(RTC_CS);//將時鐘端(RTC_CLK)數據端(RTC_DATA)片選端(RTC_CS)設置為輸出
}
/*******************************************
函數名稱: DS1302_writeB
功 能: 向DS1302寫入一個字節數據(沒有RST操作)
參 數: byte--要寫入的數據
返回值 : 無
/********************************************/
void DS1302_writeB(uchar byte)
{
uchar i;
for(i=0;i<8;i++) //8位數據計數
{
PORTC&=~BIT(RTC_CLK); //拉低時鐘端
if(byte&0x01) //當前位是否是1
{
PORTC|=BIT(RTC_DATA); //當前位是1,拉高數據端
}
else
{
PORTC&=~BIT(RTC_DATA); //當前位是0,拉低數據端
}
Delayus(10); //調整時鐘和脈沖寬度
PORTC|=BIT(RTC_CLK); //時鐘上升沿(DS1302采樣數據)
byte>>=1; //數據右移1位,為送出新數據位做準備
}
}
/*******************************************
函數名稱: DS1302_readB
功 能: 從DS1302讀出一個字節數據(沒有RST操作)
參 數: 無
返回值 : byte--讀出的數據
/********************************************/
uchar DS1302_readB(void)
{
uchar i,byte=0;
DDRC&=~BIT(RTC_DATA); //將數據端口設置為輸入
PORTC&=~BIT(RTC_DATA); //無上拉電阻
for(i=0;i<8;i++) //8位數據計數
{
byte>>=1; //保存讀入的數據位
PORTC|=BIT(RTC_CLK); //時鐘上升沿
Delayus(10); //延時,調整時鐘脈沖寬度
PORTC&=~BIT(RTC_CLK); //時鐘下降沿,DS1302輸出數據位
Delayus(10); //等待數據變化(MEGA16太快,必須等待DS1302的數據位輸出,否則不能正確讀出)
if(PINC&BIT(RTC_DATA)) //當前位是否是高電平
{
byte|=BIT(PC7); //是高電平就將返回數據的當前位置1
}
else
{
byte&=~BIT(PC7); //是低電平就將返回數據的當前位置0
}
}
DDRC|=BIT(RTC_DATA); //最后將數據端口設置為輸出
byte=byte/16*10+byte%16; //BCD碼轉為二進制
return byte; //返回讀出的數據
}
/*******************************************
函數名稱: DS1302_writeD
功 能: 向DS1302的某個地址寫入一個字節數據
參 數: addr--地址值(寄存器或RAM)
data--要寫入的地址
返回值 : 無
/********************************************/
void DS1302_writeD(uchar addr,uchar data)
{
PORTC&=~BIT(RTC_CS); //拉低片選端
PORTC&=~BIT(RTC_CLK); //拉低時鐘端
Delayus(10);
PORTC|=BIT(RTC_CS); //拉高片選端
Delayus(10); //調整片選脈沖
DS1302_writeB(addr); //寫入操作命令(地址)
Delayus(10);
PORTC&=~BIT(RTC_CLK); //拉低時鐘端
Delayus(10);
DS1302_writeB(data); //寫入數據
PORTC&=~BIT(RTC_CLK); //拉低時鐘端
Delayus(10); //調整片選脈沖
PORTC&=~BIT(RTC_CS); //拉低片選端
}
/*******************************************
函數名稱: DS1302_readD
功 能: 從DS1302的某個地址讀出一個字節數據
參 數: addr--地址值(寄存器或RAM)
返回值 : data--讀出的數據
/********************************************/
uchar DS1302_readD(uchar addr)
{
uchar data;
PORTC&=~BIT(RTC_CS); //拉低片選端
PORTC&=~BIT(RTC_CLK); //拉低時鐘端
Delayus(10);
PORTC|=BIT(RTC_CS); //拉高片選端
Delayus(10); //調整片選脈沖
DS1302_writeB(addr); //寫入操作命令(地址)
Delayus(10);
data=DS1302_readB(); //讀出數據
Delayus(10);
PORTC&=~BIT(RTC_CLK); //拉低時鐘端
PORTC&=~BIT(RTC_CS); //拉低片選端
return data; //返回讀出的數據
}
/*******************************************
函數名稱: DS1302_setT
功 能: 設置DS1302的時間
參 數: ptTimeD--設置時間數組指針
返回值 : 無
/********************************************/
void DS1302_setT(uchar ptTimeD[])
{
uchar i;
uchar addr = 0x80; //寫入地址從秒寄存器開始
DS1302_writeD(C_WP|WR,UPROTECT); //控制命令,WP位為0,允許寫操作
Delayms(5);
for(i=0;i<2;i++)
{
DS1302_writeD(addr|WR,ptTimeD[i]); // 秒 分 時 日 月 星期 年
addr+=2;
Delayms(1);
}
DS1302_writeD(C_WP|WR,PROTECT); //控制命令,WP位為1,不允許寫操作
}
/*******************************************
函數名稱: DS1302_getT
功 能: 讀取DS1302的當前時間
參 數: time[]--讀取的時間數組
返回值 : 無
/********************************************/
void DS1302_getT(uchar time[])
{
uchar i;
PORTC&=~BIT(RTC_CS); //拉低片選端
Delayus(10);
PORTC|=BIT(RTC_CS); //拉高片選端
Delayus(10); //調整片選脈沖
DS1302_writeB(0xbf); // 0xbf:時鐘多字節讀取命令
for (i=0;i<2;i++) //時間數據的存放格式是:
{ //秒,分,時,日,月,星期,年,控制
time[i]=DS1302_readB(); //【7個數據(BCD格式)+1個控制】
}
PORTC&=~BIT(RTC_CS); //拉低片選端
PORTC&=~BIT(RTC_CLK); //拉低時鐘端(時鐘端在不操作時為低)
}
/*******************************************
函數名稱: DS1302_check
功 能: 檢測DS1302是否正常工作
參 數: 無
返回值 : 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;
}
/*******************************************
函數名稱: DS1302_init
功 能: 初始化DS1302
參 數: 無
返回值 : 無
/********************************************/
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,不允許寫操作
}
/*******************************************
函數名稱: BCD_ASCII
功 能: 將壓縮BCD碼轉換成ascii碼
參 數: BCD--將要轉換的壓縮BCD碼
ptasc--轉換后的ASCII碼數組指針
返回值 : 無
/********************************************/
void BCD_ASCII(uchar BCD,uchar ptasc[])
{
ptasc[0]=BCD/16|0x30; //0X58 35 38 //轉換十位
ptasc[1]=BCD&0x0F|0x30; //轉換個位
}
/*******************************************
函數名稱: Disp_time
功 能: 在1602液晶上顯示當前時間(第1行格式:年-月-日 星期;第2行格式:時-分-秒)
參 數: time[]--時間數組
返回值 : 無
/********************************************/
void Disp_time(uchar time[])
{ uint dm[4];
uchar i,m,n;
m=(uint)time[0];
n=(uint)time[1];
for(i=1;i<3;i++)
{ dm[4-i]=m%10;
m=m/10;
}
for(i=3;i<5;i++)
{ dm[4-i]=n%10;
n=n/10;
}
for(i=0;i<4;i++)
{ show(dm[i],i);
PORTD=0XFF;
}
}
/*******************************************
函數名稱: main
功 能: 1. 在1602液晶上顯示當前時間 2.可以設置時間(M1-M9為數字0-9,M13為設置模式和顯示模式選擇,M14為當前設置位選擇)
參 數: 無
返回值 : 無
/********************************************/
void main(void)
{
uchar setadd,setdat,shift; //setadd指定將當前數值送入DS1302的哪個寄存器
//setdat是當前設置的數值,即被送入DS1302指定寄存器的數
//shift來實現十位和各位的設置相互獨立(因為十位和個位是在一個寄存器里的)
//uchar dis_x,dis_y; //存儲1602液晶當前光標的位置
uchar settime[2]={0X59,0X50};//設置的秒,分,時,日,月,星期,年
uchar gettime[2]={0X00,0X00};//保存當前時間的數組
//LCD1602_initial(); //初始化1602液晶
DS1302_portinit(); //初始化DS1302的三根數據線
DS1302_init(); //啟動振蕩器,DS1302開始工作
DS1302_setT(settime); //設置初始時間
//以下程序完成顯示和設置時間
while(1)
{
DS1302_getT(gettime); //獲得當前時間
Disp_time(gettime); //顯示當前時間
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -