【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百三十八:ESP32开发板WiFi蓝牙2.8寸240*320智能液晶显示屏带触摸屏TFT模块
项目实验之二十四:带 LVGL 的 ESP32 CYD:显示时间和日期的数字时钟
实验开源代码
/*
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百三十八:ESP32开发板WiFi蓝牙2.8寸240*320智能液晶显示屏带触摸屏TFT模块
项目实验之二十四:带 LVGL 的 ESP32 CYD:显示时间和日期的数字时钟
*/
#include <lvgl.h> // 引入LVGL图形库
#include <TFT_eSPI.h> // 引入TFT_eSPI库,用于驱动TFT显示屏
#include <WiFi.h> // 引入WiFi库,用于WiFi连接
#include <HTTPClient.h> // 引入HTTPClient库,用于发起HTTP请求
#include <ArduinoJson.h> // 引入ArduinoJson库,用于处理JSON数据
// 替换为您的网络凭据
const char* ssid = "zhz3";// WiFi名称
const char* password = "z156721";// WiFi密码
// 指定您想要获取时间的时区:https://worldtimeapi.org/api/timezone
// 葡萄牙时区示例:"Europe/Lisbon"
const char* timezone = "Europe/Lisbon"; // 设置时区
// 存储日期和时间
String current_date; // 当前日期
String current_time; // 当前时间
// 存储小时、分钟、秒
static int32_t hour; // 小时
static int32_t minute; // 分钟
static int32_t second; // 秒
bool sync_time_date = false; // 是否同步日期和时间
#define SCREEN_WIDTH 240 // 屏幕宽度
#define SCREEN_HEIGHT 320 // 屏幕高度
#define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 10 * (LV_COLOR_DEPTH / 8)) // 绘图缓冲区大小
uint32_t draw_buf[DRAW_BUF_SIZE / 4]; // 绘图缓冲区
// 如果启用了日志记录,它将告知用户库中发生了什么
void log_print(lv_log_level_t level, const char * buf) {
LV_UNUSED(level); // 未使用的参数
Serial.println(buf); // 打印日志
Serial.flush(); // 清空串口缓冲区
}
String format_time(int time) { // 格式化时间为两位数
return (time < 10) ? "0" + String(time) : String(time);
}
static lv_obj_t * text_label_time; // 时间标签
static lv_obj_t * text_label_date; // 日期标签
static void timer_cb(lv_timer_t * timer){ // 定时器回调函数
LV_UNUSED(timer);
second++;
if(second > 59) { // 秒数超过59则进位
second = 0;
minute++;
if(minute > 59) { // 分钟超过59则进位
minute = 0;
hour++;
sync_time_date = true; // 设置同步日期和时间标志
Serial.println(sync_time_date);
Serial.println("\n\n\n\n\n\n\n\n");
if(hour > 23) { // 小时超过23则归零
hour = 0;
}
}
}
String hour_time_f = format_time(hour); // 格式化小时
String minute_time_f = format_time(minute); // 格式化分钟
String second_time_f = format_time(second); // 格式化秒
String final_time_str = String(hour_time_f) + ":" + String(minute_time_f) + ":" + String(second_time_f); // 组合成最终时间字符串
//Serial.println(final_time_str);
lv_label_set_text(text_label_time, final_time_str.c_str()); // 设置时间标签文本
lv_label_set_text(text_label_date, current_date.c_str()); // 设置日期标签文本
}
void lv_create_main_gui(void) { // 创建主GUI界面
// 从WorldTimeAPI获取时间和日期
while(hour==0 && minute==0 && second==0) {
get_date_and_time();
}
Serial.println("Current Time: " + current_time); // 打印当前时间
Serial.println("Current Date: " + current_date); // 打印当前日期
lv_timer_t * timer = lv_timer_create(timer_cb, 1000, NULL); // 创建定时器
lv_timer_ready(timer); // 定时器立即执行
// 创建居中对齐的时间文本标签
text_label_time = lv_label_create(lv_screen_active()); // 创建标签
lv_label_set_text(text_label_time, ""); // 设置标签文本为空
lv_obj_align(text_label_time, LV_ALIGN_CENTER, 0, -30); // 设置标签位置
// 设置字体类型和大小
static lv_style_t style_text_label;
lv_style_init(&style_text_label); // 初始化样式
lv_style_set_text_font(&style_text_label, &lv_font_montserrat_48); // 设置字体为48号
lv_obj_add_style(text_label_time, &style_text_label, 0); // 应用样式
// 创建居中对齐的日期文本标签
text_label_date = lv_label_create(lv_screen_active()); // 创建标签
lv_label_set_text(text_label_date, current_date.c_str()); // 设置标签文本
lv_obj_align(text_label_date, LV_ALIGN_CENTER, 0, 40); // 设置标签位置
// 设置字体类型和大小
static lv_style_t style_text_label2;
lv_style_init(&style_text_label2); // 初始化样式
lv_style_set_text_font(&style_text_label2, &lv_font_montserrat_30); // 设置字体为30号
lv_obj_add_style(text_label_date, &style_text_label2, 0); // 应用样式
lv_obj_set_style_text_color((lv_obj_t*) text_label_date, lv_palette_main(LV_PALETTE_GREY), 0); // 设置文本颜色为灰色
}
void get_date_and_time() { // 获取日期和时间
if (WiFi.status() == WL_CONNECTED) { // 如果WiFi已连接
HTTPClient http; // 创建HTTPClient对象
// 构造API端点
String url = String("http://worldtimeapi.org/api/timezone/") + timezone;
http.begin(url); // 初始化HTTP请求
int httpCode = http.GET(); // 发起GET请求
if (httpCode > 0) { // 如果请求成功
// 检查响应
if (httpCode == HTTP_CODE_OK) { // 如果响应码为OK
String payload = http.getString(); // 获取响应内容
//Serial.println("Time information:");
//Serial.println(payload);
// 解析JSON以提取时间
JsonDocument doc; // 创建JSON文档
DeserializationError error = deserializeJson(doc, payload); // 反序列化JSON
if (!error) { // 如果没有错误
const char* datetime = doc["datetime"]; // 获取datetime字段
// 将datetime分割为日期和时间
String datetime_str = String(datetime);
int splitIndex = datetime_str.indexOf('T');
current_date = datetime_str.substring(0, splitIndex); // 提取日期部分
current_time = datetime_str.substring(splitIndex + 1, splitIndex + 9); // 提取时间部分
hour = current_time.substring(0, 2).toInt(); // 提取小时
minute = current_time.substring(3, 5).toInt(); // 提取分钟
second = current_time.substring(6, 8).toInt(); // 提取秒
} else { // 如果反序列化失败
Serial.print("deserializeJson() failed: ");
Serial.println(error.c_str()); // 打印错误信息
}
}
} else { // 如果请求失败
Serial.printf("GET request failed, error: %s\n", http.errorToString(httpCode).c_str()); // 打印错误信息
sync_time_date = true; // 设置同步日期和时间标志
}
http.end(); // 关闭连接
} else { // 如果WiFi未连接
Serial.println("Not connected to Wi-Fi"); // 打印未连接信息
}
}
void setup() {
String LVGL_Arduino = String("LVGL Library Version: ") + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch(); // LVGL库版本
Serial.begin(115200); // 初始化串口通信
Serial.println(LVGL_Arduino); // 打印LVGL库版本
// 连接到WiFi
WiFi.begin(ssid, password); // 初始化WiFi连接
Serial.print("Connecting"); // 打印连接信息
while (WiFi.status() != WL_CONNECTED) { // 等待WiFi连接
delay(500); // 延时
Serial.print("."); // 打印点以显示进度
}
Serial.print("\nConnected to Wi-Fi network with IP Address: "); // 打印连接成功的信息
Serial.println(WiFi.localIP()); // 打印IP地址
// 开始LVGL图形库的初始化
lv_init();
// 注册打印函数,用于调试
lv_log_register_print_cb(log_print);
// 创建一个显示对象
lv_display_t * disp;
// 使用TFT_eSPI库初始化TFT显示屏
disp = lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT, draw_buf, sizeof(draw_buf)); // 创建显示对象,设置屏幕宽高和绘图缓冲区
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_270); // 设置屏幕旋转方向为270度
// 函数用于绘制GUI
lv_create_main_gui();
}
void loop() {
// 从WorldTimeAPI获取日期和时间
if(sync_time_date) { // 如果需要同步日期和时间
sync_time_date = false; // 重置同步标志
get_date_and_time(); // 获取日期和时间
while(hour==0 && minute==0 && second==0) { // 如果获取的时间无效(即小时、分钟、秒都为0)
get_date_and_time(); // 再次尝试获取日期和时间
}
}
lv_task_handler(); // 让LVGL执行GUI任务
lv_tick_inc(5); // 告诉LVGL已经过去了5毫秒
delay(5); // 等待5毫秒
} 复制代码