DS3231在單片機系統中的應用

在單片機系統中,有時我們需要顯示時間與日期,那麼我們該怎麼實現呢?

  1. 用單片機的定時器每一秒進入一次中斷,獲得秒時間,分時間當然就是對秒進行是否等於60進行判斷,隨即計算時間期。這種方法的缺點是單片機需要一直進入中斷,對單片機資源來說是一種浪費。

  2. 一些高端的單片機例如STM32 內置了RTC模塊,我們只需要接上32.768khz的外置晶振並且在程序中打開RTC就可以讀取時間,STM32的RTC是一個獨立模塊,所以不存在浪費資源問題,但是我們知道想要買到高精度的32.768KHZ晶振並不是一件容易得事情,雖然我們可以在程序中對誤差進行修正但是始終不是很理想。

  3. 使用時鐘芯片,常用的時鐘芯片有DS1302 ,DS12C887,還有我們要講的ds3231.等橫多芯片。我想學過單片機的人都用過DS1302這款時鐘芯片,他的確點也是由於需要外界32768KHZ晶振所以誤差較大。由其在溫差較大的場合更是明顯有時候一天內達到十幾秒的誤差。而DS12C887 這款芯片雖然精度高,內置鋰電池但是體積較大,控制方式較為複雜所以我們也較少使用。

而ds3231這款芯片卻不一樣,它採用iic接口,只需要兩根線就可以對其進行控制,它不需要外接晶振,自己內置了帶有溫度補償的高精度晶振年誤差一秒以內,而且成本低用在單片機系統中最合適不過。


DS3231在單片機系統中的應用

DS3231模塊

下面我們來看一下如何驅動這款時鐘芯片。應為它採用IIC接口那就少不了開始、停止、度、寫這些時序。

DS3231在單片機系統中的應用

配置STM32的IO口

/產生IIC起始信號

void IIC_Start(void)

{

SDA_OUT(); //sda線輸出

IIC_SDA=1;

IIC_SCL=1;

delay_us(4);

IIC_SDA=0;//START:when CLK is high,DATA change form high to low

delay_us(4);

IIC_SCL=0;//鉗住I2C總線,準備發送或接收數據

}

//產生IIC停止信號

void IIC_Stop(void)

{

SDA_OUT();//sda線輸出

IIC_SCL=0;

IIC_SDA=0;//STOP:when CLK is high DATA change form low to high

delay_us(4);

IIC_SCL=1;

IIC_SDA=1;//發送I2C總線結束信號

delay_us(4);

}

//等待應答信號到來

//返回值:1,接收應答失敗

// 0,接收應答成功

u8 IIC_Wait_Ack(void)

{

u8 ucErrTime=0;

SDA_IN(); //SDA設置為輸入

IIC_SDA=1;delay_us(1);

IIC_SCL=1;delay_us(1);

while(READ_SDA)

{

ucErrTime++;

if(ucErrTime>250)

{

IIC_Stop();

return 1;

}

}

IIC_SCL=0;//時鐘輸出0

return 0;

}

//產生ACK應答

void IIC_Ack(void)

{

IIC_SCL=0;

SDA_OUT();

IIC_SDA=0;

delay_us(2);

IIC_SCL=1;

delay_us(2);

IIC_SCL=0;

}

//不產生ACK應答

void IIC_NAck(void)

{

IIC_SCL=0;

SDA_OUT();

IIC_SDA=1;

delay_us(2);

IIC_SCL=1;

delay_us(2);

IIC_SCL=0;

}

//IIC發送一個字節

//返回從機有無應答

//1,有應答

//0,無應答

void IIC_Send_Byte(u8 txd)

{

u8 t;

SDA_OUT();

IIC_SCL=0;//拉低時鐘開始數據傳輸

for(t=0;t<8;t++)

{

IIC_SDA=(txd&0x80)>>7;

txd<<=1;

delay_us(2); //對TEA5767這三個延時都是必須的

IIC_SCL=1;

delay_us(2);

IIC_SCL=0;

delay_us(2);

}

}

//讀1個字節,ack=1時,發送ACK,ack=0,發送nACK

u8 IIC_Read_Byte(unsigned char ack)

{

unsigned char i,receive=0;

SDA_IN();//SDA設置為輸入

for(i=0;i<8;i++ )

{

IIC_SCL=0;

delay_us(2);

IIC_SCL=1;

receive<<=1;

if(READ_SDA)receive++;

delay_us(1);

}

if (!ack)

IIC_NAck();//發送nACK

else

IIC_Ack(); //發送ACK

return receive;

}

上面是IIC讀寫函數。有了這些函數我們就可以驅動DS3231了。

DS3231在單片機系統中的應用

DS3231地址分配表

有了驅動函數有了地址分配表就OK了,例如我們要讀取秒那麼我們就讀取00H寄存器就可以獲得當前秒值。

需要注意的是DS3231輸出是BCD碼,我們還需要將BCD轉換為十進制當然也很簡單。

DS3231在單片機系統中的應用

讀取時間並且轉換十進制

這樣我們就可以利用數碼管或者LCD來顯示時間了,精度相當高。喜歡的關注我吧。。。。微信:w445144


分享到:


相關文章: