wasdpkj 发表于 2013-8-29 00:34:02

Microduino-RTC小应用:网络时钟+OLED显示

本帖最后由 wasdpkj 于 2013-8-29 00:41 编辑

[关于microduino上架问题:老张和tiki最近都很忙,过些天应该会陆续上架,需要模块的朋友耐心等等]

------------------------------------------------------------

关于Microduino-RTC模块:
Microduino-RTC模块是基于 PCF8563芯片的时钟模块,模块还附加AT24c32芯片,提供额外的EEPROM功能。I2C接口通信。 采用电容提供了一定的掉电计时能力。PCF8563使用一个外部晶体和电容,并有1个中断输出,可以定时触发中断。
更详细信息:http://wiki.microduino.net/wiki/Microduino-RTC

关于RTC等I2C模块适配Core+:
Core+的IIC接口和Core的不一样,不是A4和A5,而是D20(SDA)和D21(SCL),请注意引出。


先看看如何驱动RTC模块:
首先我们来设置时间,我在源程序“set_clock”的基础上加以修改,时间的两个格式都调用出来。(源程序setup里少了一行串口初始化 Serial.begin(9600);)


#include <Wire.h>
#include <Rtc_Pcf8563.h>

//init the real time clock
Rtc_Pcf8563 rtc;

void setup()
{
Serial.begin(9600);
//clear out the registers
rtc.initClock();
//set a time to start with.
//day, weekday, month, century(1=1900, 0=2000), year(0-99)
rtc.setDate(29, 4, 8, 0, 13);
//hr, min, sec
rtc.setTime(00, 21, 0);
}

void loop()
{
//both format functions call the internal getTime() so that the
//formatted strings are at the current time/date.
Serial.println("CODE_1:");
Serial.print(rtc.formatTime());
Serial.print("   ");
Serial.print(rtc.formatDate());
Serial.print("\r\n");

Serial.println("CODE_2:");
Serial.print("20");
Serial.print(rtc.getYear());
Serial.print("/");
Serial.print(rtc.getMonth());
Serial.print("/");
Serial.print(rtc.getDay());
Serial.print("   ");
Serial.print(rtc.getHour());
Serial.print(":");
Serial.print(rtc.getMinute());
Serial.print(":");
Serial.print(rtc.getSecond());
Serial.print("\r\n");

delay(1000);
Serial.print("\r\n");
}

}


运行效果:


===================================================

接下来简单介绍一下标题所指的应用:
主要功能:开机自动获取DHCP,获取网络NTP时间,如果成功则会将时间同步到Pcf8563里。加以OLED显示。

硬件用到了:
Microduino-Core+、Microduino-FT232R、【Microduino-ENC28J60】 + 【Microduino-RJ45】、Microduino-OLED、Microduino-RTC。



程序如下:
#include "U8glib.h"

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);        // HW SPI Com: CS = 10, A0 = 9 (Hardware Pins areSCK = 13 and MOSI = 11)
//-------字体设置,大、中、小
#define setFont_L u8g.setFont(u8g_font_7x13)
#define setFont_M u8g.setFont(u8g_font_fixed_v0r)
#define setFont_S u8g.setFont(u8g_font_chikitar)
/*
font:
u8g.setFont(u8g_font_7x13)
u8g.setFont(u8g_font_fixed_v0r);
u8g.setFont(u8g_font_chikitar);
u8g.setFont(u8g_font_osb21);
*/

#include <Wire.h>
#include <Rtc_Pcf8563.h>

Rtc_Pcf8563 rtc;
int time_nian,time_yue,time_ri,time_shi,time_fen,time_miao,time_zhou;

#include <EtherCard.h>

#define SECONDS_IN_DAY          86400
#define START_YEAR            1900
#define TIME_ZONE               +8
static int days_in_month[] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

static byte mymac[] = {
0x00,0x1A,0x4B,0x38,0x0C,0x5C};
byte Ethernet::buffer;

static byte ntpServer[] = {
193,204,114,232};
static byte srcPort = 0;

uint32_t timeStamp;

boolean NET_TIME_reply;

#define NET_TIME_INTERVAL    1000
#define TIME_OUT             10000
#define INTERVAL             100000
unsigned long lastTime = 0,TIME_cache = 0;


void setup () {
Serial.begin(57600);

volcdsetup("Load NETWORK",0,15);
delay(1000);
if (!ether.begin(sizeof Ethernet::buffer, mymac))
    Serial.println( "Failed to access Ethernet controller");
else
    Serial.println("Ethernet controller initialized");
if (!ether.dhcpSetup())
{
    Serial.println("Failed to get configuration from DHCP");
    volcdsetup("DHCP Error",0,15);
    delay(1000);
}
else
{
    Serial.println("DHCP configuration done");
    volcdsetup("DHCP Succeed",0,15);
    delay(1000);
}
ether.printIp("IP Address:\t", ether.myip);
ether.printIp("Netmask:\t", ether.mymask);
ether.printIp("Gateway:\t", ether.gwip);

//-------------------------------------------------------
volcdsetup("Load Net Time",0,15);
delay(1000);
NET_TIME_reply = true;
vonettime();
if(NET_TIME_reply)
{
    volcdsetup("Time Sync. Error",0,15);
    delay(1000);
}
else
{
    vosettime();
    volcdsetup("Time Sync. Succeed",0,15);
    delay(1000);
}

//-------------------------------------------------------
Serial.println();
}

void loop() {
if(millis() - lastTime > INTERVAL)
{
    NET_TIME_reply = true;
    vonettime();
    if(!NET_TIME_reply)
    {
      vosettime();
    }
    lastTime = millis();
}

volcd();

}

void volcd()
{
u8g.firstPage();
do {
    setFont_M;
    u8g.setPrintPos(0, 9);
    u8g.print("TIME:");
    u8g.print(rtc.formatDate());

    u8g.setPrintPos(0, 20);
    u8g.print(rtc.formatTime());

    //-----------------------------------------
    u8g.setPrintPos(0, 34);
    u8g.print("TIME:");
    u8g.print("20");
    u8g.print(rtc.getYear());
    u8g.print("/");
    u8g.print(rtc.getMonth());
    u8g.print("/");
    u8g.print(rtc.getDay());

    u8g.setPrintPos(0, 45);
    u8g.print(rtc.getHour());
    u8g.print(":");
    u8g.print(rtc.getMinute());
    u8g.print(":");
    u8g.print(rtc.getSecond());

    String WEEK="";
    switch(rtc.getWeekday())
    {
    case 1:
      WEEK="Monday";
      break;
    case 2:
      WEEK="Tuesday";
      break;
    case 3:
      WEEK="Wednesday";
      break;
    case 4:
      WEEK="Thursday";
      break;
    case 5:
      WEEK="Friday";
      break;
    case 6:
      WEEK="Saturday";
      break;
    case 7:
      WEEK="Sunday";
      break;
    }
    u8g.setPrintPos(60, 45);
    u8g.print(WEEK);

    setFont_S;
    u8g.drawFrame(0, 54,128,10);
    u8g.setPrintPos(3, 62);
    u8g.print("Microduino-RTC v1.0201307");
}
while( u8g.nextPage() );
}

void vosettime()
{
rtc.initClock();//set a time to start with.
rtc.setDate(time_ri, time_zhou, time_yue, 0, time_nian%100);//day, weekday, month, century(1=1900, 0=2000), year(0-99)
rtc.setTime(time_shi, time_fen, time_miao); //hr, min, sec

}

void volcdsetup(char* zi,unsigned int x,unsigned int y)
{
u8g.firstPage();
do {
    setFont_L;   
    u8g.setPrintPos(x, y);
    u8g.print(zi);
}
while( u8g.nextPage() );
}


void vonettime()
{
uint32_t timeout = millis();    //超时时间
while(NET_TIME_reply == true && millis() - timeout < TIME_OUT)   //采集到或者超时时跳出
{
    ether.packetLoop(ether.packetReceive());
    if(millis() - TIME_cache > NET_TIME_INTERVAL)   //发送请求间隔
    {
      ether.ntpRequest(ntpServer, srcPort);
      TIME_cache = millis();
      NET_TIME_reply = true;   //标记发送
    }

    if(NET_TIME_reply && ether.ntpProcessAnswer(&timeStamp, srcPort))    //发送后等待应答
    {
      printDate(timeStamp + 3600 * TIME_ZONE);    //开始计算
      TIME_cache = millis();
      NET_TIME_reply = false;    //接收到了
    }
}
}


void printDate(uint32_t timeStamp) {

unsigned long week = (((timeStamp/3600/24)+1)%7);

Serial.print("Current date and time:");
Serial.println(timeStamp);

unsigned int year = START_YEAR;
while(1) {
    uint32_t seconds;
    if(isLeapYear(year)) seconds = SECONDS_IN_DAY * 366;
    else seconds = SECONDS_IN_DAY * 365;
    if(timeStamp >= seconds) {
      timeStamp -= seconds;
      year++;
    }
    else break;
}

unsigned int month = 0;
while(1) {   
    uint32_t seconds = SECONDS_IN_DAY * days_in_month;
    if(isLeapYear(year) && month == 1) seconds = SECONDS_IN_DAY * 29;
    if(timeStamp >= seconds) {
      timeStamp -= seconds;
      month++;
    }
    else break;
}
month++;

unsigned int day = 1;
while(1) {
    if(timeStamp >= SECONDS_IN_DAY) {
      timeStamp -= SECONDS_IN_DAY;
      day++;
    }
    else break;
}

unsigned int hour = timeStamp / 3600;
unsigned int minute = (timeStamp - (uint32_t)hour * 3600) / 60;
unsigned int second = (timeStamp - (uint32_t)hour * 3600) - minute * 60;


Serial.print("week: ");
Serial.println(week);

if(day < 10) Serial.print("0");
Serial.print(day);
Serial.print("/");

if(month < 10) Serial.print("0");
Serial.print(month);
Serial.print("/");

Serial.println(year);


if(hour < 10) Serial.print("0");
Serial.print(hour);
Serial.print(":");

if(minute < 10) Serial.print("0");
Serial.print(minute);
Serial.print(":");

if(second < 10) Serial.print("0");
Serial.println(second);

Serial.println();

time_nian=year;
time_yue=month;
time_ri=day;
time_shi=hour;
time_fen=minute;
time_miao=second;
time_zhou=week;
}

boolean isLeapYear(unsigned int year) {

return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
}


运行效果:


本文用到的库:

更多资料见:http://wiki.microduino.net/

冰炭寒酒 发表于 2013-8-29 00:50:28

赞 本来就想抽空搞一下,内容几乎一样ntp取时间rtc保存呵呵这下可以挪用你的了

ogre_c 发表于 2013-8-29 04:58:00

看见了老潘风骚的3d打印板{:soso_e179:} 万事具备就差RTC了。

histamine 发表于 2013-8-29 09:00:49

很不错

等上架了,我也搞套microduino玩玩:lol

林定祥 发表于 2013-8-29 11:14:55

应该可以摞起来吧?

wasdpkj 发表于 2013-8-29 11:36:11

ogre_c 发表于 2013-8-29 04:58 static/image/common/back.gif
看见了老潘风骚的3d打印板 万事具备就差RTC了。

:lol偷懒,直接当oled扩展板用了

wyd1520 发表于 2013-8-29 13:55:20

:Q这小板,没得方买呀,哪里购的?

wasdpkj 发表于 2013-8-29 14:30:31

wyd1520 发表于 2013-8-29 13:55 static/image/common/back.gif
这小板,没得方买呀,哪里购的?

看文末链接

林定祥 发表于 2013-8-29 15:56:51

OLCD可以图形吧,可以将时钟显示大些就漂亮了.

504835618 发表于 2014-10-3 20:24:03

请问28J60网络模块怎么接线呢?

wasdpkj 发表于 2014-10-7 01:21:11

504835618 发表于 2014-10-3 20:24 static/image/common/back.gif
请问28J60网络模块怎么接线呢?

用Microduino模块 直接堆叠就行~不用连线
页: [1]
查看完整版本: Microduino-RTC小应用:网络时钟+OLED显示