Fireduino 网络万年历
更新时间:2017-09-26 阅读:16006
前言
Fireduino 网络万年历是一个可以通过wifi联网,通过NTP协议获取到网络时间,并且使用RTC运行时钟以及万年历显示的示例,其中万年历可以显示从1583开始的公历以及星期,并且可以通过按键翻阅日历。
操作流程
上电后进行TFT初始化和WIFI初始化,进行WIFI连接并且在TFT上进行提示。
通过网络NTP协议获取网络时间,并且写入到RTC中,如果NTP获取失败,将在星期右侧显示字符“-_-||”表示同步失败,下次同步成功后可以消除该状态。
进入“时钟”界面,在TFT上显示表盘、星期、日期以及时间。
短按按Mode键同步NTP网络时间。
长按Mode键后循环切换主显示界面,主要有"时钟"界面、"本月日历"界面以及"翻阅万年历"界面。
"本月日历"界面显示年份、月份以及本月日历(包含星期)以及高亮显示今日位置,无切换界面外的按键响应。
“翻阅万年历”界面可以通过按键翻阅日历。短按MODE 切换位,短按UP、DOWN调相应值,长按快速UP、DOWN调相应值。
硬件连接
Fireduino
Fireduino 作为主MCU,为驱动TFT、RTC、KEY等提供逻辑运行环境。
TFT
TFT 为显示设备,主要提供显示表盘以及时间字符、日历显示。
RTC
RTC 是板载的RTC独立单元,用于保存和获取实时时间,使用的为HYM8563,挂载在I2C1 接口,Fireduino 为此提供了专门的RTC库可供直接使用。
按键
软件逻辑
界面
网络万年历主要分为如下几个界面
// status of display#define MODE_DISPLAY_TIME 0 //显示表盘、今日星期、日期以及时间#define MODE_DISPLAY_CAL 1 //显示本月日历#define MODE_BROWSE_CAL 2 //翻阅日历
事件
事件由按键触发,为事件处理提供依据
#define EVENT_MODE 1 //模式键抬起事件#define EVENT_UP 2 // UP事件 #define EVENT_DOWN 3 // DOWN事件#define EVENT_MODE_CHANG 4 // 模式改变时间#define EVENT_MODE_CLICK 5 //模式键按下事件
按键处理
本示例使用了3个按键,使用了pin 5、6、7,每20ms 扫描一次按键状态,支持长按和短按。
按键扫描
每20ms扫描一次。
void key_sacn(void){unsigned char pin_level = 0;if(digitalRead(5) == HIGH){ pin_level |= KEY_MODE;}if(digitalRead(6) == HIGH){ pin_level |= KEY_UP;}if(digitalRead(7) == HIGH){ pin_level |= KEY_DOWN;} key_trg = pin_level&(pin_level^key_count); key_count = pin_level;}
按键处理
根据状态,生成事件
void key_proc(void){if(key_trg & KEY_UP){ event_key = EVENT_UP ;} if(key_count & KEY_UP){ up_count++;if(up_count > 100){ up_count = 80 + up_count_i;if(up_count_i++ >100){ up_count_i = 100;} event_key = EVENT_UP;}}else{ up_count = 0; up_count_i = 0;} }
显示处理
根据不同模式,显示不同界面。
MODE_DISPALY_TIME 模式显示时钟表盘及今日星期、日期和时间。
MODE_DISPALY_CAL 模式显示本月日历,显示年份、月份、星期以及高亮显示今日日期位置。
MODE_BROWSE_CAL 模式显示可翻阅的日历,可修改年份和月份,修改的位会相应的闪烁。
事件处理
事件处理在按键处理之后,根据时间对于不同的处理。
void event_proc(void){if(event_key){switch(event_key){case EVENT_MODE :.....break;case EVENT_UP :..... break;case MODIFY_HOUR :..... break;case EVENT_DOWN :..... break;case EVENT_MODE_CHANG :..... break;} event_key = 0;}}
绘图处理
void clear_all(void); //清除整个屏幕void clear_dial(void); //清除表盘void clear_time_pointer(void); //清除表指针void clear_time_txt(unsigned char flash_bit); //清除时钟界面显示的文本void draw_dial(void); //绘制表盘void draw_time_pointer(RTCTime *time); //绘制表指针void draw_time_txt(RTCTime *time); //绘制时钟界面显示文本void draw_cal(RTCTime *time); //绘制今日日历void draw_browse_cal(RTCTime *time); //绘制可翻阅日历
Arduino 程序结构
setup
// initialize the serial port Serial.begin(115200); // initialize the TFT Screen delay(1); TFTscreen.begin(); Serial.println("TFTscreen init success"); delay(1); // clear the screen with a pretty color TFTscreen.background(0, 0, 0); TFTscreen.setTextSize(1); TFTscreen.stroke(255,255,255); // attempt to connect to Wifi network: while (status != WL_CONNECTED) { Serial.print("Attempting to connect to SSID: ");Serial.println(ssid); TFTscreen.text("Connecting ",28,70);TFTscreen.text(" ... ",28,90);// Connect to network.status = WiFi.begin(ssid, pass); } Serial.println("Connected to wifi"); printWifiStatus(); TFTscreen.fillRect(0,70,128,40,0); // initialize UDP Serial.println("\nStarting connection to server..."); Udp.begin(localPort); // Init Wire and RTC will use I2C Interface Wire1.begin(); getNtpTimeSuccess = 0; // Get NTP time ntpTime(); // if failed ,note user if (!getNtpTimeSuccess) { TFTscreen.stroke(255,0,0); TFTscreen.textSize(1); TFTscreen.text("get NTP Time",28,70); TFTscreen.text("failed",46,80); delay(3000); TFTscreen.stroke(0,0,0); TFTscreen.text("get NTP Time",28,70); TFTscreen.text("failed",46,80); TFTscreen.stroke(255,255,255); TFTscreen.textSize(2); } else RTC.setTime(&time); // display the dial draw_dial();
loop
if(millis() > curr_ms){ curr_ms = millis() + 250;// displaytime(); display_proc();}//20ms 检测一次按键状态if(millis() > curr_ms_key){ curr_ms_key = millis() + 20; key_sacn(); key_proc(); event_proc(); }
示例程序
#include <TFT.h> // Arduino LCD library#include "RTC.h"#include "WiFi.h"#include <WiFiUdp.h>#include "Wire.h" // define for calculate time#define SECONDS_IN_DAY 86400#define START_YEAR 1900#define TIME_ZONE +8 // status of display#define MODE_DISPLAY_TIME 0#define MODE_DISPLAY_CAL 1#define MODE_BROWSE_CAL 2//#define MODE_DGET_NTP_TIME_FAILD 3 // event of key#define EVENT_MODE 1#define EVENT_UP 2#define EVENT_DOWN 3#define EVENT_MODE_CHANG 4#define EVENT_MODE_CLICK 5 // Key flag#define KEY_MODE 0x01#define KEY_UP 0x02#define KEY_DOWN 0x04 #define UP_YEAR 0#define DOWN_YEAR 1#define UP_MON 2#define DOWN_MON 3 // count ms of key pressunsigned int curr_ms;unsigned int curr_ms_key; // current statusunsigned char curr_mode;unsigned char event_key; // counts of key pressunsigned char mode_count;unsigned char up_count;unsigned char down_count; unsigned char mode_count_i;unsigned char up_count_i;unsigned char down_count_i; // flag of keysunsigned char key_trg;unsigned char key_count; unsigned char modif_bit = 0; // for display the monthstatic int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};String mon_list[] = {" ","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; // WIFI informationint status = WL_IDLE_STATUS;char ssid[] = "Fireduino"; // your network SSID (name)char pass[] = "12345678"; // your network password // Get NTP time statusunsigned char getNtpTimeSuccess; unsigned int localPort = 2390; // local port to listen for UDP packets IPAddress timeServer(128, 138, 140, 44); // time-nw.nist.gov NTP server const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets // A UDP instance to let us send and receive packets over UDPWiFiUDP Udp; RTCTime time;RTCTime browseTime;String cal_char[6][7];String browse_cal_char[6][7]; TFT TFTscreen = TFT(); // function for WIFIvoid printWifiStatus(); // function for NTP Timeunsigned long sendNTPpacket(IPAddress& address); RTCTime * timeStamp2time(unsigned int timeStamp ,RTCTime *time); void ntpTime(void); // function for displayunsigned char Lcd_TimeX(unsigned char circle_x,unsigned char Length,unsigned char Angle);unsigned char Lcd_TimeY(unsigned char circle_y,unsigned char Length,unsigned char Angle);void clear_all(void);void clear_dial(void);void clear_time_pointer(void);void clear_time_txt(unsigned char flash_bit);void draw_dial(void);void draw_time_pointer(RTCTime *time);void draw_time_txt(RTCTime *time);void draw_cal(RTCTime *time);void draw_browse_cal(RTCTime *time); // function of key eventvoid key_sacn(void);void key_proc(void);void event_proc(void);void display_proc(void); void setup() { // initialize the serial port Serial.begin(115200); // initialize the TFT Screen delay(1); TFTscreen.begin(); Serial.println("TFTscreen init success"); delay(1); // clear the screen with a pretty color TFTscreen.background(0, 0, 0); TFTscreen.setTextSize(1); TFTscreen.stroke(255,255,255); // attempt to connect to Wifi network: while (status != WL_CONNECTED) { Serial.print("Attempting to connect to SSID: ");Serial.println(ssid); TFTscreen.text("Connecting ",28,70);TFTscreen.text(" ... ",28,90);// Connect to network.status = WiFi.begin(ssid, pass); } Serial.println("Connected to wifi"); printWifiStatus(); TFTscreen.fillRect(0,70,128,40,0); // initialize UDP Serial.println("\nStarting connection to server..."); Udp.begin(localPort); // Init Wire and RTC will use I2C Interface Wire1.begin(); getNtpTimeSuccess = 0; // Get NTP time ntpTime(); // if failed ,note user if (!getNtpTimeSuccess) { TFTscreen.stroke(255,0,0); TFTscreen.textSize(1); TFTscreen.text("get NTP Time",28,70); TFTscreen.text("failed",46,80); delay(3000); TFTscreen.stroke(0,0,0); TFTscreen.text("get NTP Time",