0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何利用DS3231構(gòu)建一個基于Atmega16的數(shù)字掛鐘

科技觀察員 ? 來源:circuitdigest ? 作者:薩達(dá)姆 ? 2022-09-08 15:34 ? 次閱讀

每個數(shù)字時鐘內(nèi)部都有一個晶體來跟蹤時間。這種晶體不僅存在于時鐘中,而且存在于所有計算實(shí)時系統(tǒng)中。該晶體產(chǎn)生時鐘脈沖,這是時序計算所必需的。雖然還有其他一些方法可以獲得更高的精度和頻率的時鐘脈沖,但最首選的方法是使用晶體來跟蹤時間。在這里,我們將DS3231 RTC IC 構(gòu)建一個基于 Atmega16 的數(shù)字掛鐘。DS3231 RTC 內(nèi)部有一個高精度晶體,因此不需要外部晶體振蕩器

在這個數(shù)字時鐘項(xiàng)目中,十個 0.8 英寸的共陽極 7 段顯示器用于顯示時間和日期。這里使用七段顯示器來顯示小時、分鐘、日期、月份和年份。我們的 PCB 設(shè)計還具有顯示秒數(shù)和溫度的選項(xiàng),可以通過添加更多顯示單元來顯示。

所需組件

ATmega16 AVR 微控制器

DS3231 實(shí)時時鐘集成電路

共陽極0.8寸七段顯示器(比普通尺寸顯示器(0.56寸)大)

按鈕

紐扣電池 3v

7805穩(wěn)壓器

1000uf電容

蜂鳴器(可選)

晶體管 BC547 和 BC557

10uf電容

100 歐姆電阻

1k電阻

10k電阻

PCB板

跳線

小貼士

電源適配器

用戶也可以使用 Atmega32,它需要在生成十六進(jìn)制之前在編譯器中進(jìn)行配置。

電路圖及說明

這個數(shù)字掛鐘電路有兩個部分,一個是顯示部分,在五個不同的 PCB 板上有 5 對 7 段,另一個是控制單元部分,負(fù)責(zé)從 RTC 芯片獲取時間并將數(shù)據(jù)和時間發(fā)送到7段顯示。由于我們使用了 10 個七段顯示器,因此我們無法將每個顯示器連接到單獨(dú)的 IO 端口。因此,這里使用了多路復(fù)用技術(shù),使用較少的微控制器引腳連接多個七段。

poYBAGMZmsKATJwjAAARItgKMP0899.png

七段顯示器的 LED 引腳 a、b、c、d、e、f、g、h 與 atmega16 的 PORTB 并聯(lián)。這里我們使用了 10 個七段顯示器,所以我們需要 10 個控制引腳連接在 PORTD、PORTA 和 PORTC。

具有內(nèi)部晶體的 RTC DS3231 連接到 PORTC 的 SDA 和 SCL 引腳,因?yàn)樵撔酒ぷ髟?I2C 通信上。該芯片的接口方法與 DS1307 相同。我們已經(jīng)將DS1307 與 Arduino、Raspberry Pi和8051 MCU一起使用。DS3231 和 DS1307 可以使用相同的代碼。

兩個 10k 上拉電阻連接在 SDA 和 SCL 線上。一個 3v 紐扣電池用于為 RTC 芯片供電,即使在主電源關(guān)閉時也能跟蹤時間。每當(dāng)電源再次恢復(fù)時,時間將開始顯示在七段顯示器上?,F(xiàn)在我們在 PORT A 有一些設(shè)置時間的按鈕,完整的過程在最后給出的視頻中解釋。5v 穩(wěn)壓器用于將輸入電壓轉(zhuǎn)換為 5v。所有連接都顯示在下面的電路圖中:

poYBAGMZmr6AHcCtAAKWIdhrQ_Q507.png

對于一個顯示板,使用兩個七段顯示器和 2 個 LED。所以這里我們有五個不同的顯示板來顯示小時和分鐘 (HH-MM) 中的時間,以及 DD-MM-YY 中的日期。

pYYBAGMZmrqAOmv-AADHhpTZcx0647.png

poYBAGMZmreAP5iBAANcsU0PB3k991.png

數(shù)字時鐘的 PCB 設(shè)計和制造

對于這個基于 Atmega16 的掛鐘項(xiàng)目,我們設(shè)計了兩個 PCB。一是控制單元,用于控制項(xiàng)目的所有操作,二是用于在七段顯示器上顯示時間和日期。顯示部分包含五對0.8英寸七段顯示器。因此,通過組裝 5 個零件,我們就擁有了完整的數(shù)字時鐘。多路復(fù)用 7 段顯示器,5 塊 PCB 的數(shù)據(jù)線將連接到控制單元的同一個端口,控制線連接到控制單元的不同引腳。

下面是一個顯示板的 PCB 布局的頂視圖和底視圖,該顯示板由兩個七段顯示器組成:

poYBAGMZmrKAVChJAAFpzC3WlLo095.png

下面是控制單元 PCB 的頂視圖和底視圖

poYBAGMZmq2AR1CTAAF2hUo2ETA374.png

焊接后的幾張電路板圖片 如下所示。

pYYBAGMZmqqAH_LLAARLL_am00c714.png

pYYBAGMZmqaAIhf4AAXGzGJrEqU912.png

測試數(shù)字時鐘

教程末尾給出了完整的代碼,只需按照電路圖連接PCB并將代碼上傳到Atmega16。您將在十個七段顯示屏上看到時間和日期。

pYYBAGMZmqKAU6R_AASuKdpT6Qk540.png

可以使用控制單元上的四個按鈕設(shè)置時間??和日期。

/*

* 數(shù)字時鐘.c

#include

#define F_CPU 8000000UL

#include

#include

int day=6,dd=1,mm=3,yy=19;

無符號整數(shù)秒,分鐘=13,小時=4;

常量無符號整數(shù)[]={0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0X10};

詮釋 d0,d1,d2,d3,d4,d5,d6,d7,d8,d9;

易失的無符號整數(shù)計數(shù),計數(shù)1;

#定義數(shù)字13

#define 數(shù)據(jù)端口 PORTB

#define controlPortD 端口

#define controlPortC PORTC

#define controlPortA PORTA

#define controlPortD_Mask 0x83

#define controlPortC_Mask 0x03

#define controlPortA_Mask 0x7F

#define 段關(guān)閉 -1

#define sw PINA

#定義集 4

#定義好 3

#向上定義2

#向下定義 1

#define setEvent (sw & (1<))<>

#define okEvent (sw & (1<))<>

#define upEvent (sw & (1<))<>

#define downEvent (sw & (1<))<>

#define LEDPORT PORTA

#define secLed 5

#define BUZPORT 端口

#定義蜂鳴器 7

字符閃爍標(biāo)志;

易失性字符 onFlag=0x00;

#define timeFormat 24

枚舉

{

小時=1,

分鐘,

日期,

月,

年,

};

字符 segOn[12]={0x04,0x08,0x10,0x20,0x40,0x80,0x40,0x80,0x10,0x20,0x04,0x08};

無效顯示();

無效更新時間();

ISR(TIMER1_OVF_vect)

{

展示();

TCNT1 = 64000;

}

無效選擇段(整數(shù)計數(shù))

{

如果(計數(shù) < 5)

{

controlPortA&=controlPortA_Mask;

controlPortC&=controlPortC_Mask;

controlPortD&=controlPortD_Mask;

controlPortD|=segOn[計數(shù)];

}

否則如果(計數(shù) == 5)

{

controlPortA|=segOn[計數(shù)];

controlPortC&=controlPortC_Mask;

controlPortD&=controlPortD_Mask;

}

否則如果(計數(shù) == -1)

{

controlPortA&=controlPortA_Mask;

controlPortC&=controlPortC_Mask;

controlPortD&=controlPortD_Mask;

}

別的

{

controlPortA&=controlPortA_Mask;

controlPortC&=controlPortC_Mask;

controlPortD&=controlPortD_Mask;

controlPortC|=segOn[計數(shù)];

}

}

無效段(整數(shù)計數(shù),整數(shù)段)

{

如果(閃爍標(biāo)志 == 段)

{

如果(onFlag)

選擇段(段關(guān)閉);

別的

選擇段(計數(shù));

}

別的

{

選擇段(計數(shù));

}

}

無效顯示()

{

計數(shù)1++;

如果(計數(shù) 1>400)

{

計數(shù)1=0;

onFlag=!onFlag;

}

計數(shù)++;

如果(計數(shù)>數(shù)字)

計數(shù)=0;

開關(guān)(count%digit)

{

案例0:

段(計數(shù),分鐘);

數(shù)據(jù)端口=num[d0];

休息;

情況1:

段(計數(shù),分鐘);

數(shù)據(jù)端口=num[d1];

休息;

案例2:

段(計數(shù),小時);

數(shù)據(jù)端口=num[d2];

休息;

案例3:

段(計數(shù),小時);

數(shù)據(jù)端口=數(shù)字[d3];

休息;

案例4:

段(計數(shù),日期);

數(shù)據(jù)端口=num[d4];

休息;

案例5:

段(計數(shù),日期);

數(shù)據(jù)端口=數(shù)字[d5];

休息;

案例6:

段(計數(shù),月);

數(shù)據(jù)端口=數(shù)字[d6];

休息;

案例7:

段(計數(shù),月);

數(shù)據(jù)端口=數(shù)字[d7];

休息;

案例8:

段(計數(shù),年份);

數(shù)據(jù)端口=數(shù)字[d8];

休息;

案例9:

段(計數(shù),年份);

數(shù)據(jù)端口=num[d9];

休息;

}

}

無效 timer1_init()

{

// 使用預(yù)分頻器 = 8 設(shè)置定時器

TCCR1B |= (1 << CS11);

//TCCR1B &= ~(1 << CS10);

//TCCR1B &= (1 << CS11);

//TCCR1B &= ~(1 << CS12);

TCNT1 = 63500;

TIMSK |= (1 << TOIE1);

sei();

}

int bcdtochar(字符數(shù))

{

返回 ((num/16 * 10) + (num % 16));

}

int decobcd(字符數(shù))

{

返回 ((num/10)<<4) + (num % 10);

}

無效 RTC_start()

{

TWCR=(1<)|(1<

而((TWCR&0x80)==0x00);

}

無效設(shè)備()

{

TWDR=0xD0;//RTC寫入(從地址)

TWCR=(1<)|(1<

而(!(TWCR&(1<)));<>

TWDR=0x00;// 字地址寫入

TWCR=(1<)|(1<

而(!(TWCR&(1<)));<>

}

無效 RTC_stp()

{

TWCR=(1<)|(1<

}

無效 RTC_read()

{

TWCR=(1<)|(1<

而((TWCR&0x80)==0x00);

TWDR=0xD0;//RTC寫入(從地址)

TWCR=(1<)|(1<

而(!(TWCR&(1<)));<>

TWDR=0x00;//RTC寫入(字地址)

TWCR=(1<)|(1<

而(!(TWCR&(1<)));<>

TWCR=(1<)|(1<

而 ((TWCR&0x80)==0x00);

TWDR=0xD1;// RTC 命令讀取

TWCR=(1<)|(1<

而(!(TWCR&(1<)));<>

}

無效 sec_init(無符號字符 d)

{

TWDR=d; //第二次初始化

TWCR=(1<)|(1<

而(!(TWCR&(1<)));<>

}

void min_init(unsigned char d)

{

TWDR=d; //分鐘初始化

TWCR=(1<)|(1<

而(!(TWCR&(1<)));<>

}

無效 hr_init(無符號字符 d)

{

TWDR=d; //小時初始化

TWCR=(1<)|(1<

而(!(TWCR&(1<)));<>

}

void day_init(unsigned char d)

{

TWDR=d; //天數(shù)初始化

TWCR=(1<)|(1<

而(!(TWCR&(1<)));<>

}

無效日期初始化(無符號字符 d)

{

TWDR=d; //日期初始化

TWCR=(1<)|(1<

而(!(TWCR&(1<)));<>

}

無效month_init(無符號字符d)

{

TWDR=d; //月份初始化

TWCR=(1<)|(1<

而(!(TWCR&(1<)));<>

}

無效 yr_init(無符號字符 d)

{

TWDR=d; //年份初始化

TWCR=(1<)|(1<

而(!(TWCR&(1<)));<>

}

int sec_rw()

{

詮釋克[3];

TWCR|=(1<)|(1<

而((TWCR & 0x80)==0x00);

返回 bcdtochar(TWDR)??;

}

int min_rw()

{

TWCR|=(1<);>

TWCR|=(1<);<>

而((TWCR & 0x80)==0x00);

返回 bcdtochar(TWDR)??;

}

int hr_rw()

{

TWCR|=(1<)|(1<

而((TWCR & 0x80)==0x00);

返回 bcdtochar(TWDR)??;

}

int day_rd()

{

TWCR|=(1<)|(1<

而((TWCR&0x80)==0x00);

返回 bcdtochar(TWDR)??;

}

int date_rw()

{

TWCR|=(1<)|(1<

而((TWCR & 0x80)==0x00);

返回 bcdtochar(TWDR)??;

}

int month_rw()

{

TWCR|=(1<)|(1<

而((TWCR & 0x80)==0x00);

返回 bcdtochar(TWDR)??;

}

int yr_rw()

{

TWCR|=(1<);>

TWCR&=(~(1<));<>

而((TWCR & 0x80)==0x00);

返回 bcdtochar(TWDR)??;

}

無效的設(shè)置時間()

{

RTC_start();

設(shè)備();

sec_init(0);

min_init(dectobcd(min));

hr_init(dectobcd(hr));

day_init(dectobcd(天));

date_init(dectobcd(dd));

month_init(dectobcd(mm));

yr_init(dectobcd(yy));

RTC_stp();

}

無效 RTC()

{

RTC_read();

sec=sec_rw();

min=min_rw();

hr=hr_rw();

day=day_rd();

dd=date_rw();

mm=month_rw();

yy=yr_rw();

RTC_stp();

}

char getPara(字符數(shù))

{

而(1)

{

更新時間();

如果(!upEvent)

{

計數(shù)1=0;

onFlag=0x00;

計數(shù)++;

如果(閃爍標(biāo)志 == 小時)

{

如果(時間格式 == 12)

{

如果(計數(shù)>12)

計數(shù)=0;

}

別的

{

如果(計數(shù) > 23)

計數(shù)=0;

}

小時=計數(shù);

}

否則如果(blinkFlag == 分鐘)

{

如果(計數(shù)> 59)

計數(shù)=0;

分鐘=計數(shù);

}

否則如果(blinkFlag == 月)

{

如果(計數(shù) > 12)

計數(shù)=1;

毫米=計數(shù);

}

否則如果(blinkFlag == 日期)

{

if(mm == 4 || mm == 6 || mm == 9 || mm == 11)

{

如果(計數(shù) > 30)

計數(shù)=1;

}

否則 if(mm == 1 || mm == 3 || mm == 5 || mm == 7 || mm == 8 || mm == 10 || mm == 12)

{

如果(計數(shù) >31)

計數(shù)=1;

}

別的

{

int y=2000+yy;

如果(y/4 == 0 && y/400 == 0)

{

如果(計數(shù) > 29)

計數(shù)=1;

}

別的

{

如果(計數(shù) > 28)

計數(shù)=1;

}

}

dd=計數(shù);

}

否則如果(blinkFlag == 年)

{

如果(計數(shù) >99)

計數(shù)=0;

YY=計數(shù);

}

_delay_ms(200);

}

否則如果(!(downEvent))

{

數(shù)數(shù) - ;

如果(閃爍標(biāo)志 == 年)

{

如果(計數(shù)<0)

計數(shù)=99;

}

_delay_ms(100);

}

否則如果(!okEvent)

{

_delay_ms(1000);

返回計數(shù);

}

}

}

無效設(shè)置時間()

{

閃爍標(biāo)志=1;

hr=getPara(hr);

閃爍標(biāo)志++;

min=getPara(min);

閃爍標(biāo)志++;

dd=getPara(dd);

閃爍標(biāo)志++;

mm=getPara(mm);

閃爍標(biāo)志++;

yy=getPara(yy);

閃爍標(biāo)志=0;

}

無效更新時間()

{

d0=min%10;

d1=分鐘/10;

d2=hr%10;

d3=小時/10;

d4=dd%10;

d5=dd/10;

d6=mm%10;

d7=mm/10;

d8=yy%10;

d9=yy/10;

}

詮釋主要(無效)

{

無符號長整數(shù)時間;

DDRB=0xff;

DDRA=0xE0;

端口=0x1E;

DDRD=0xff;

DDRC=0xff;

timer1_init();

而(1)

{

實(shí)時時鐘();

更新時間();

_delay_ms(500);

LEDPORT|=1<;<>

_delay_ms(500);

LEDPORT&=~(1<);<>

如果(!setEvent)

{

設(shè)置時間();

設(shè)置時間();

}

}

}

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • ATmega16
    +關(guān)注

    關(guān)注

    5

    文章

    154

    瀏覽量

    45740
  • DS3231
    +關(guān)注

    關(guān)注

    2

    文章

    51

    瀏覽量

    23811
  • 數(shù)字時鐘
    +關(guān)注

    關(guān)注

    2

    文章

    149

    瀏覽量

    20287
收藏 人收藏

    評論

    相關(guān)推薦

    基于DS3231的高精度時鐘接口設(shè)計

    、工作原理以及引腳功能,設(shè)計其與微控制器進(jìn)行通信時的軟件、硬件接口,并給出相應(yīng)的原理圖與流程圖,此方案對DS3231般的電路系統(tǒng)設(shè)計中具有通用性。由于DS3231是目前精度最高,并集成有溫補(bǔ)振蕩器
    發(fā)表于 04-24 09:01

    實(shí)時時鐘芯片DS3231應(yīng)用筆記,使用指南,F(xiàn)AQ全集

    ,并采用低成本、標(biāo)準(zhǔn)型、16引腳SOIC封裝。在-40°C至+85°C溫度范圍內(nèi),計時精度為±2分鐘/年。這出色性能使DS3231成為當(dāng)前要求高計時精度應(yīng)用的最佳解決方案。而RTC的其它集成功能也
    發(fā)表于 03-14 11:05

    【以前的小制作分享】基于ATMEGA16,DS3231,DS18B20的高精度日歷溫度顯示

    最近論壇申請板子,聽說分享帖可以為申請加分。這是很早之前完成的日歷溫度顯示,ATMEGA16為8位AVR單片機(jī),DS3231,DS18B20分為是DALLAS公司的高精度RTC和高精度溫度芯片。1.
    發(fā)表于 11-04 22:06

    DS3231的接線方法及源代碼

    3.DS3231的接線方法 DS3231時鐘模塊,通信用的是IIC接口在這只用到DS3231時鐘模塊的SCL,SDA,VCC,GND四針腳即可設(shè)定讀出時間和溫度,下面是接線方法。
    發(fā)表于 08-17 14:43

    DS3231時鐘星期不對

    做了DS3231時鐘,可是星期每次都不對,加上autoweek函數(shù)后,按鍵的的值就寫不到DS3231中了,不加autoweek可以挑時間,可以走,就是星期不對。求解答?
    發(fā)表于 06-20 04:35

    DS3231時鐘芯片結(jié)構(gòu)

    目錄、模塊簡介DS3231時鐘芯片結(jié)構(gòu)原理引腳圖內(nèi)部結(jié)構(gòu)圖DS3231典型應(yīng)用電路DS3231時鐘芯片結(jié)構(gòu)二、與stm32通信1、配置IO2、初始化與函數(shù)3、主函數(shù)調(diào)用4、使用源碼
    發(fā)表于 08-09 06:31

    DS3231時鐘芯片讀寫程序分享

    @[TOC](咚咚咚————【封裝驅(qū)動】DS3231時鐘芯片讀寫程序,分享交流自己編寫的程序。/********************************************主控芯片
    發(fā)表于 12-13 07:14

    如何將DS3231 RTC模塊與NodeMCU連接

    ESP8266智能燈項(xiàng)目?viadean.com接口如何將DS3231 RTC模塊與NodeMCU連接。學(xué)習(xí)在串行監(jiān)視器上設(shè)置和顯示DS3231的時間。首先,讓我們從DS3231實(shí)時時鐘模塊的基礎(chǔ)知識...
    發(fā)表于 01-25 07:23

    DS3231與8051微控制器的接口

    摘要:本應(yīng)用筆記提供了DS3231與8051微控制器接口的硬件電路和軟件例程。 圖1. DS3231
    發(fā)表于 04-21 11:16 ?2021次閱讀
    <b class='flag-5'>DS3231</b>與8051微控制器的接口

    采用DS3231設(shè)計的高精度時鐘接口

    采用DS3231設(shè)計的高精度時鐘接口 DS3231是Maxim/Dallas公司生產(chǎn)的款低成本、超高精度的I2C實(shí)時時鐘
    發(fā)表于 04-20 15:23 ?3347次閱讀
    采用<b class='flag-5'>DS3231</b>設(shè)計的高精度時鐘接口

    DS3231芯片手冊中文版

    DS3231芯片手冊中文版,內(nèi)部存儲BCD碼
    發(fā)表于 12-11 11:00 ?0次下載

    ds3231時鐘模塊怎么用_DS3231的操作與使用

    DS3231款高精度I2C實(shí)時時鐘器件,具有集成的溫度補(bǔ)償晶體振蕩器。該器件包含電池輸入端,斷開主電源時仍可保持精確計時。集成的晶體振蕩器可提高器件的長期精確度。DS3231的寄存器能保存秒、分、時、星期、日期、月、年和鬧鐘
    發(fā)表于 01-29 11:23 ?10.4w次閱讀
    <b class='flag-5'>ds3231</b>時鐘模塊怎么用_<b class='flag-5'>DS3231</b>的操作與使用

    ATmega8單片機(jī)與時鐘器件DS3231的接口設(shè)計

    軟件設(shè)計中,首先要對AVR單片機(jī)ATmega8與實(shí)時鐘器件DS3231進(jìn)行初始化,給DS3231準(zhǔn)確的日期和時間。不論主控模式還是被控模式,都應(yīng)當(dāng)將TWI控制寄存器TWCR的TWEN位置為1,從而使能TWI模塊
    發(fā)表于 01-29 14:54 ?4776次閱讀
    <b class='flag-5'>ATmega</b>8單片機(jī)與時鐘器件<b class='flag-5'>DS3231</b>的接口設(shè)計

    ds3231中文資料匯總(ds3231引腳圖及特性參數(shù)_應(yīng)用電路)

    精確的計時。集成晶振提高了器件的長期精確度,并減少了生產(chǎn)線的元件數(shù)量。DS3231提供商用級和工業(yè)級溫度范圍,采用16引腳300mil的SO封裝。
    發(fā)表于 04-10 17:02 ?8.1w次閱讀
    <b class='flag-5'>ds3231</b>中文資料匯總(<b class='flag-5'>ds3231</b>引腳圖及特性參數(shù)_應(yīng)用電路)

    基于Arduino Mege 2560的數(shù)字掛鐘

    使用 Arduino Mega 2560、5054 LED 燈條、DS3231 RTC、IRFZ44N MOSFET 晶體管和鋁型材制作大型數(shù)字掛鐘。
    發(fā)表于 12-08 17:50 ?3次下載