外贸网站空间哪个好,罗湖网站建设的公司哪家好,免费网站注册永久,网站优化效果忘记过去#xff0c;超越自己 ❤️ 博客主页 单片机菜鸟哥#xff0c;一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建时间 2024-03-02❤️❤️ 本篇更新时间 2024-03-02❤️#x1f389; 欢迎关注 #x1f50e;点赞 #x1f44d;收藏 ⭐️留言#x1f4dd;#x1f64f;… 忘记过去超越自己 ❤️ 博客主页 单片机菜鸟哥一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建时间 2024-03-02❤️❤️ 本篇更新时间 2024-03-02❤️ 欢迎关注 点赞 收藏 ⭐️留言 此博客均由博主单独编写不存在任何商业团队运营如发现错误请留言轰炸哦及时修正感谢支持 快速导读 1. 前言1.1 模块步骤1.2 代码结构 2. 详细介绍2.1 主工程 —— CLOCK2.2 模块化细节2.2.1 m_wifi —— 管理联网过程2.2.2 m_ntp —— ntp网络时间同步2.2.3 m_display —— 显示联网过程2.2.4 m_display_default —— 时间刷新显示 3.成果3.1 串口调试3.2 实物效果 合宙ESP32C3 Arduino开发付费专栏群 689271933不喜勿加凭借付费专栏订单号加入 1. 前言
在前篇中我们学习了 TFT_eSPI 驱动 合宙Air101 ST7735 LCD这一节我们来学习一下基于它基础上做一个简单时钟并且开始接触模块化编程思想。 【合宙ESP32C3 Arduino开发】第三篇TFT_eSPI 驱动 合宙Air101 ST7735 LCD 1.1 模块步骤 第一步联网显示联网过程 第二步通过ntp同步最新网络时间 第三步时间同步到单片机中每隔秒级进行刷新。 1.2 代码结构
为了区分模块化博主拆开了主工程和功能模块。
2. 详细介绍
2.1 主工程 —— CLOCK
#include Arduino.h
#include ArduinoJson.h
#include TimeLib.h
#include WiFi.h
#include WiFiUdp.h
#include HTTPClient.h
#include TFT_eSPI.h
#include SPI.h
#include TJpg_Decoder.h// 当前版本
#define Version CL V1.0/* ****************************************************************** 字库、图片库* *****************************************************************/
#include number.h
#include font/ZdyLwFont_20.h
#include font/fangzheng/fangzheng20.h
#include font/hanyi/hanyi20.h
#define TEXT_FONT ZdyLwFont_20// 设备启动打印信息
const char projectInfo[] PROGMEM Rrawliteral(
/* ****************************************************************** 基于ESP32C3 160x80 TFT屏 时钟* 当前固件版本V1.3* 创 建 日 期2024.02.27* 最后更改日期2024.02.27** *****************************************************************/
)rawliteral;/* ****************************************************************** 字库、图片库* *****************************************************************/
// 屏幕区域
#define TFT_WIDTH 80
#define TFT_HEIGHT 160TFT_eSPI tft TFT_eSPI(); // 引脚请自行配置tft_eSpi库中的 User_Setup.h文件
TFT_eSprite clk TFT_eSprite(tft);
time_t time_old 0; //上次时间刷新时间
time_t time_now 0; //当前秒Number dig;uint16_t bgColor TFT_BLACK; // 黑色背景色
uint16_t txtColor TFT_WHITE; // 字体颜色
uint32_t targetTime 0;void setup() {Serial.begin(115200);Serial.println(projectInfo);tft_init(); //屏幕初始化// 连接wifiwhile(!wifi_connect());ntp_init(); //ntp服务初始化tft_display_layout(); // 绘制屏幕布局
}void loop(){time_now now();//刷新时间信息每秒刷新if (time_now ! time_old){time_old time_now;tft_display_time();}
}
主工程就管理整个代码运行过程。 初始化tft屏幕并且进行网络连接这里会展示联网界面ntp服务初始化然后持续绘制显示时间 2.2 模块化细节
2.2.1 m_wifi —— 管理联网过程
String WifiSSID xxxxx; // 填写自己的wifi账号只支持2.4G
String WifiPassword xxxx; // 填写自己的wifi密码只支持2.4G
int animate_refresh_Time 0;
int animate_key -1; //初始化图标显示帧数// 连接wifi
extern bool wifi_connect(void){bool conn_result false;if (WifiSSID.length() 0){return conn_result;}WiFi.mode(WIFI_STA);WiFi.disconnect();WiFi.setTxPower(WIFI_POWER_5dBm);WiFi.begin(WifiSSID.c_str(), WifiPassword.c_str());const uint8_t *animate_value; // 指向关键帧的指针uint32_t animate_size; // 指向关键帧大小的指针uint32_t index 0;while (true){if (millis() - animate_refresh_Time 30){index;Serial.print(.);animate_refresh_Time millis();tft_display_loading(50); //每50毫秒检测一次刷新一次进度条// 查询连接结果int status WiFi.status();if (status WL_CONNECT_FAILED ||status WL_NO_SSID_AVAIL ||status WL_CONNECTION_LOST){conn_result false;Serial.println(【m_wifi】连接失败);break;} else if (status WL_CONNECTED){conn_result true;Serial.print(【m_wifi】wifi连接成功当前IP地址:);Serial.println(WiFi.localIP());tft_display_loading_complete(); // 将进度条刷到100%Serial.println(【m_wifi】结束loading);break;}// 超过当做连接失败if (index 300){// 连接超时WiFi.disconnect();break;}}}if (WiFi.status() ! WL_CONNECTED){return false;}return true;
}
在wifi_connect中进行begin网络连接后开始间隔一段时间进行刷新联网进度 tft_display_loading。 当网络连接成功后还需要把进度涨到100% tft_display_loading_complete。当然总不能一直在联网会有一个错误时间这里超过300次就表示连接失败。
2.2.2 m_ntp —— ntp网络时间同步
//NTP服务器
WiFiUDP Udp;
const char ntpServerName[] ntp6.aliyun.com;
const int timeZone 8; //东八区
unsigned int localPort 8000;
const int NTP_PACKET_SIZE 48; // NTP时间在消息的前48字节中
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming outgoing packetsstatic time_t getNtpTime()
{IPAddress ntpServerIP; // NTP servers ip addresswhile (Udp.parsePacket() 0) ; // discard any previously received packets//Serial.println(Transmit NTP Request);// get a random server from the poolWiFi.hostByName(ntpServerName, ntpServerIP);//Serial.print(ntpServerName);//Serial.print(: );//Serial.println(ntpServerIP);sendNTPpacket(ntpServerIP);uint32_t beginWait millis();while (millis() - beginWait 1500) {int size Udp.parsePacket();if (size NTP_PACKET_SIZE) {Serial.println(Receive NTP Response);Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the bufferunsigned long secsSince1900;// convert four bytes starting at location 40 to a long integersecsSince1900 (unsigned long)packetBuffer[40] 24;secsSince1900 | (unsigned long)packetBuffer[41] 16;secsSince1900 | (unsigned long)packetBuffer[42] 8;secsSince1900 | (unsigned long)packetBuffer[43];//Serial.println(secsSince1900 - 2208988800UL timeZone * SECS_PER_HOUR);return secsSince1900 - 2208988800UL timeZone * SECS_PER_HOUR;}}Serial.println(【m_ntp】ntp服务器无响应);return 0; // 无法获取时间时返回0
}// 向NTP服务器发送请求
static void sendNTPpacket(IPAddress address)
{// set all bytes in the buffer to 0memset(packetBuffer, 0, NTP_PACKET_SIZE);// Initialize values needed to form NTP request// (see URL above for details on the packets)packetBuffer[0] 0b11100011; // LI, Version, ModepacketBuffer[1] 0; // Stratum, or type of clockpacketBuffer[2] 6; // Polling IntervalpacketBuffer[3] 0xEC; // Peer Clock Precision// 8 bytes of zero for Root Delay Root DispersionpacketBuffer[12] 49;packetBuffer[13] 0x4E;packetBuffer[14] 49;packetBuffer[15] 52;// all NTP fields have been given values, now// you can send a packet requesting a timestamp:Udp.beginPacket(address, 123); //NTP requests are to port 123Udp.write(packetBuffer, NTP_PACKET_SIZE);Udp.endPacket();
}extern void ntp_init(void)
{Udp.begin(localPort);setSyncProvider(getNtpTime);setSyncInterval(60 * 60); // 1小时同步一次
}这里我们设置了1小时同步一次时间。
关于ntp深入学习可以参考 ESP8266开发之旅 网络篇⑰ NTP——时间服务 2.2.3 m_display —— 显示联网过程
//初始化屏幕
extern void tft_init(void){tft.begin(); // TFT初始化tft.setRotation(3); // 旋转角度0-3tft.setTextColor(TFT_BLACK, TFT_WHITE); //设置字体颜色tft.fillScreen(TFT_BLACK); // 清屏TJpgDec.setJpgScale(1); // 设置放大倍数TJpgDec.setSwapBytes(true); // 它的作用是设置TFT液晶屏的像素字节序。在某些情况下像素字节序可能需要被交换以确保图像正确显示。这段代码中的true表示需要交换字节序而false则表示不需要交换字节序。TJpgDec.setCallback(tft_output); // 回调函数
}extern bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *bitmap) {if (y tft.height())return 0;// 这句代码是将一个位图(bitmap)显示在TFT屏幕上其中x和y是位图左上角的坐标w和h是位图的宽度和高度。具体来说它将位图的像素数据推送到TFT屏幕上从而在指定的位置显示出来。tft.pushImage(x, y, w, h, bitmap);return 1;
}// 进度条
byte loadNum 6;
extern void tft_display_loading(byte delayTime){clk.setColorDepth(8); // 设置TFT屏幕的颜色深度为8位。TFT屏幕的颜色深度指的是每个像素点可以显示的颜色数量8位颜色深度可以显示256种颜色。clk.createSprite(160, 50); // 创建Spriteclk.fillSprite(TFT_BLACK); // 填充颜色黑色clk.drawRoundRect(0, 0, 160, 16, 8, TFT_WHITE); // 画一个圆角矩形框白色clk.fillRoundRect(3, 3, loadNum, 10, 5, TFT_WHITE); // 画一个填充的圆角矩形白色clk.setTextDatum(CC_DATUM); // 设置文本显示基准为居中对齐clk.setTextColor(TFT_WHITE, TFT_BLACK); // 设置文本的前景色和背景色clk.drawString(Connecting to WiFi, 80, 40, 2); // 显示“Connecting to WiFi”这个字符串位置为(80,40)字体大小为2。clk.pushSprite(0, 10); // Sprite中内容一次推向屏幕clk.deleteSprite(); // 删除SpriteloadNum 1;if (loadNum 154){loadNum 154;}delay(delayTime);
}// 将进度条刷到100%
extern void tft_display_loading_complete(void){while (loadNum 154) { //让动画走完tft_display_loading(1);}
} // 绘制屏幕布局
extern void tft_display_layout(void){tft.setRotation(3);tft.fillScreen(bgColor); //清屏
}
2.2.4 m_display_default —— 时间刷新显示
// 刷新时间显示
extern void tft_display_time(void){int timeY 20;// 记录上一次时间static String hourMinute_old ;static String second_old ;static unsigned char Hour_old 60;static unsigned char Minute_old 60;static unsigned char Second_old 60;String hourMinute_now hourMinute();//--------------------中间时间区显示开始--------------------// 时分if(hourMinute_now ! hourMinute_old){hourMinute_old hourMinute_now;// 小时刷新if(hour()! Hour_old){dig.printfW1830(10, timeY, hour()/10);dig.printfW1830(30, timeY, hour()%10);Hour_old hour();}// 分钟刷新if(minute()! Minute_old ){dig.printfW1830(60, timeY, minute()/10);dig.printfW1830(80, timeY, minute()%10);Minute_old minute();}}// 秒if(second()! Second_old){dig.printfW1830(120, timeY, second()/10);dig.printfW1830(140, timeY, second()%10);Second_old second();}//--------------------中间时间区显示结束--------------------
}为了做到性能优化做了新旧数据对比只有数据变化了才会去刷新。
3.成果
3.1 串口调试 3.2 实物效果
wifi联网过程 时钟显示效果