代码
第一步设置驱动库TFT_eSPI的默认配置文件
1,设置适配的屏幕 #define ST7789_DRIVER
2,设置屏幕大小 #define TFT_WIDTH 170
#define TFT_HEIGHT 320
3,设置屏幕驱动板端口和ESP8266对应的端口
// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation
#define TFT_MISO PIN_D6 // Automatically assigned with ESP8266 if not defined
#define TFT_MOSI PIN_D7 // Automatically assigned with ESP8266 if not defined
#define TFT_SCLK PIN_D5 // Automatically assigned with ESP8266 if not defined
#define TFT_CS PIN_D0 // Chip select control pin D8
#define TFT_DC PIN_D3 // Data Command control pin
#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line)
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V
#define TFT_BL PIN_D1 // LED back-light (only for ST7789 with backlight control pin)
主代码
#include "ArduinoJson.h"
#include <TimeLib.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WebServer.h>
#include <WiFiUdp.h>
#include <TFT_eSPI.h>
#include <SPI.h>
#include <TJpg_Decoder.h>
#include <EEPROM.h>
#include <Servo.h>
#include "loadingimg.h"
/*** Component objects ***/
LOADING_IMG loadingimgclass;
#include <WiFiManager.h>
//WiFiManager 参数
WiFiManager wm; // global wm instance
/* *******字库、图片库******************************/
#include "font/ZdyLwFont_20.h"
int AnimLoad = 0; //开机图标显示指针记录
int AprevTimeLoad = 0; //更新时间记录
/* ************** 参数设置*********/
struct config_type
{
char stassid[32];//定义配网得到的WIFI名长度(最大32字节)
char stapsw[64];//定义配网得到的WIFI密码长度(最大64字节)
};
//---------------修改此处""内的信息--------------------
//如开启WEB配网则可不用设置这里的参数,前一个为wifi ssid,后一个为密码
config_type wificonf = {{""}, {""}};
//LCD屏幕相关设置
TFT_eSPI tft = TFT_eSPI(170,320); // 引脚请自行配置tft_espi库中的 User_Setup.h文件
TFT_eSprite clk = TFT_eSprite(&tft);
Servo servo;
#define PWM_DJ D8 //舵机控制
#define TOUCH_PIN D2 //触摸按钮
#define LCD_BL_PIN 5 //LCD背光引脚
uint16_t bgColor = 0x0000;
//其余状态标志位
int LCD_Rotation = 1; //LCD屏幕方向
int LCD_BL_PWM = 70;//屏幕亮度0-100,默认10
uint8_t Wifi_en = 1; //wifi状态标志位 1:打开 0:关闭
unsigned long weaterTime = 0; //天气更新时间记录
//EEPROM参数存储地址位
int BL_addr = 1;//被写入数据的EEPROM地址编号 1亮度
int wifi_addr = 30; //被写入数据的EEPROM地址编号 20wifi-ssid-psw
//NTP服务器参数
static const char ntpServerName[] = "ntp6.aliyun.com";
const int timeZone = 8; //东八区
//wifi连接UDP设置参数
WiFiUDP Udp;
WiFiClient wificlient;
unsigned int localPort = 8000;
//函数声明
time_t getNtpTime();
void sendNTPpacket(IPAddress &address);
void LCD_reflash(int en);
void savewificonfig();
void readwificonfig();
void deletewificonfig();
/* ******函数******************************/
//wifi ssid,psw保存到eeprom
void savewificonfig()
{
//开始写入
uint8_t *p = (uint8_t*)(&wificonf);
for (int i = 0; i < sizeof(wificonf); i++)
{
EEPROM.write(i + wifi_addr, *(p + i)); //在闪存内模拟写入
}
delay(10);
EEPROM.commit();//执行写入ROM
delay(10);
}
//删除原有eeprom中的信息
void deletewificonfig()
{
config_type deletewifi = {{""}, {""}};
uint8_t *p = (uint8_t*)(&deletewifi);
for (int i = 0; i < sizeof(deletewifi); i++)
{
EEPROM.write(i + wifi_addr, *(p + i)); //在闪存内模拟写入
}
delay(10);
EEPROM.commit();//执行写入ROM
delay(10);
}
//从eeprom读取WiFi信息ssid,psw
void readwificonfig()
{
uint8_t *p = (uint8_t*)(&wificonf);
for (int i = 0; i < sizeof(wificonf); i++)
{
*(p + i) = EEPROM.read(i + wifi_addr);
}
}
//TFT屏幕输出函数
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
{
if ( y >= tft.height() ) return 0;
tft.pushImage(x, y, w, h, bitmap);
// Return 1 to decode next block
return 1;
}
//1、开机动画 屏幕加载动画替换进度条
byte loadNum = 6; //原始默认为6
void loading(byte delayTime)//绘制进度条
{
if (millis() - AprevTimeLoad > 1) //x ms切换一次 // int AprevTimeLoad = 0; 更新时间记录
{
AnimLoad++; //int AnimLoad = 0; 开机图标显示指针记录
AprevTimeLoad = millis();
}
if (AnimLoad == 36){
AnimLoad = 0;
}
//调用函数显示图片,全局,TFT,
loadingimgclass.printfloading(60,5,AnimLoad);
clk.setColorDepth(8);
clk.createSprite(200,60);//创建窗口
clk.fillSprite(0x0000); //填充率
clk.setTextDatum(CC_DATUM); //设置文本数据
clk.setTextColor(TFT_ORANGE, 0x0000);
clk.drawString("Hello inventor!", 100, 10, 2);//Connecting to WiFi......
clk.setTextColor(TFT_WHITE, 0x0000);
clk.drawString("cat cat cat!", 100, 50, 2);//Connecting to WiFi......
clk.pushSprite(60, 100); //窗口位置 130高度以下
clk.deleteSprite();
loadNum += 1;
delay(delayTime);
}
//WEB配网LCD显示函数
void Web_win()
{
clk.setColorDepth(8);
clk.createSprite(200,60);//创建窗口
clk.fillSprite(0x0000); //填充率
clk.setTextDatum(CC_DATUM); //设置文本数据
clk.setTextColor(TFT_GREEN, 0x0000);
clk.drawString("WiFi Connect Fail!", 100, 10, 2);//Connecting to WiFi......
clk.setTextColor(TFT_YELLOW, 0x0000);
clk.drawString("SSID:AutoConnectAP", 100, 50, 2);//Connecting to WiFi......
clk.pushSprite(60, 100); //窗口位置 130高度以下
clk.deleteSprite();
}
//WEB配网函数
void Webconfig()
{
WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP
delay(3000);
wm.resetSettings(); // wipe settings
int customFieldLength = 40;
WiFiManagerParameter custom_bl("LCDBL", "LCD BackLight(1-100)", "8", 3);
WiFiManagerParameter p_lineBreak_notext("<p></p>");
wm.addParameter(&p_lineBreak_notext);
wm.addParameter(&custom_bl);
wm.setSaveParamsCallback(saveParamCallback);
std::vector<const char *> menu = {"wifi", "restart"};
wm.setMenu(menu);
// set dark theme
wm.setClass("invert");
wm.setMinimumSignalQuality(20); // set min RSSI (percentage) to show in scans, null = 8%
bool res;
// res = wm.autoConnect(); // auto generated AP name from chipid
res = wm.autoConnect("AutoConnectAP"); // anonymous ap
// res = wm.autoConnect("AutoConnectAP","password"); // password protected ap
while (!res);
}
String getParam(String name) {
//read parameter from server, for customhmtl input
String value;
if (wm.server->hasArg(name)) {
value = wm.server->arg(name);
}
return value;
}
void saveParamCallback() {
LCD_BL_PWM = getParam("LCDBL").toInt();
tft.fillScreen(0x0000);//清理屏幕
Web_win();
loadNum--;
loading(1);
if (EEPROM.read(BL_addr) != LCD_BL_PWM)
{
EEPROM.write(BL_addr, LCD_BL_PWM);
EEPROM.commit();
delay(5);
}
//屏幕亮度
Serial.println("亮度调整为:");
analogWrite(LCD_BL_PIN, 1023 - (LCD_BL_PWM * 10));
Serial.println(LCD_BL_PWM);
}
void draweye(){
int isTouch = digitalRead(TOUCH_PIN);
if (isTouch == HIGH) { //接收到触摸信号
clk.setColorDepth(8);
clk.createSprite(200,60);//创建窗口
clk.fillSprite(0x0000); //填充率
clk.fillRoundRect(1, 25, 30, 5, 8,TFT_WHITE);
clk.fillRoundRect(169, 25, 30, 5, 8,TFT_WHITE);
clk.pushSprite(60, 50); //窗口位置 130高度以下
clk.deleteSprite();
servo.write(90);
delay(100);
} else {
clk.setColorDepth(8);
clk.createSprite(200,60);//创建窗口
clk.fillSprite(0x0000); //填充率
clk.fillRoundRect(1, 1, 30, 60, 8,TFT_WHITE);
clk.fillRoundRect(169, 1, 30, 60, 8,TFT_WHITE);
clk.pushSprite(60, 50); //窗口位置 130高度以下
clk.deleteSprite();
servo.write(100);
delay(100);
}
}
void setup()
{
Serial.begin(115200);
EEPROM.begin(1024);
Serial.println("正在连接WIFI ");
// WiFi.forceSleepWake();
// wm.resetSettings(); //在初始化中使wifi重置,需重新配置WiFi
//从eeprom读取背光亮度设置
if (EEPROM.read(BL_addr) > 0 && EEPROM.read(BL_addr) < 100)
LCD_BL_PWM = EEPROM.read(BL_addr);
pinMode(LCD_BL_PIN, OUTPUT);
analogWrite(LCD_BL_PIN, 1023 - (LCD_BL_PWM * 10));
pinMode(TOUCH_PIN,INPUT);
servo.attach(D8);
tft.begin(); /* TFT init */
tft.invertDisplay(1);//反转所有显示颜色:1反转,0正常
tft.setRotation(LCD_Rotation);
tft.fillScreen(0x0000);
tft.setTextColor(TFT_BLACK, bgColor);
readwificonfig();//读取存储的wifi信息
Serial.print("正在连接WIFI ");
Serial.println(wificonf.stassid);
WiFi.begin(wificonf.stassid, wificonf.stapsw);
TJpgDec.setJpgScale(1);
TJpgDec.setSwapBytes(true);
TJpgDec.setCallback(tft_output);
while (WiFi.status() != WL_CONNECTED)
{
loading(30);
if (loadNum >= 194)
{
Web_win();//显示配网
Webconfig();
break;
}
}
delay(10);
while (loadNum < 194) //让动画走完
{
loading(1);
}
if (WiFi.status() == WL_CONNECTED)
{
strcpy(wificonf.stassid, WiFi.SSID().c_str()); //名称复制
strcpy(wificonf.stapsw, WiFi.psk().c_str()); //密码复制
savewificonfig(); //保存wifi密码
readwificonfig();
}
Udp.begin(localPort);
setSyncProvider(getNtpTime);
setSyncInterval(300);
TJpgDec.setJpgScale(1);
TJpgDec.setSwapBytes(true);
TJpgDec.setCallback(tft_output);
tft.fillScreen(TFT_BLACK);//清屏
WiFi.forceSleepBegin(); //wifi off
Serial.println("WIFI休眠......");
Wifi_en = 0;
draweye();
}
void loop()
{
//LCD_reflash(0);
draweye();
}
//屏幕滚动
int currentIndex = 0;
int lastIndex = 0;
void LCD_reflash(int en)
{
//两秒钟更新一次
if (second() % 2 == 0 && lastIndex != second()) {
lastIndex = second(); //设置一样
scrollBanner();
}
if (millis() - weaterTime > 60000 ) { //10分钟更新一次
if (Wifi_en == 0)
{
WiFi.forceSleepWake();//wifi on
Serial.println("WIFI恢复......");
Wifi_en = 1;
}
if (WiFi.status() == WL_CONNECTED)
{
Serial.println("WIFI已连接");
weaterTime = millis();
while (!getNtpTime());
WiFi.forceSleepBegin(); // Wifi Off
Serial.println("WIFI休眠......");
Wifi_en = 0;
}
}
}
TFT_eSprite clkb = TFT_eSprite(&tft);
String scrollText[7];
void scrollBanner() {
scrollText[0] = "实时天气000 ";
scrollText[1] = "空气质量 1";
scrollText[2] = "风向 2";
scrollText[3] = "今日as3" ;
scrollText[4] = "最低温度4";
scrollText[5] = "最高温度5";
if (scrollText[currentIndex]){
clkb.setColorDepth(8);
/***绘制相关文字***/
clkb.loadFont(ZdyLwFont_20);
clkb.createSprite(160, 20);
clkb.fillSprite(bgColor);
clkb.setTextWrap(false);
clkb.setTextDatum(CC_DATUM);
clkb.setTextColor(TFT_SILVER, bgColor);
clkb.drawString(scrollText[currentIndex], 74, 16,2);
clkb.pushSprite(100, 5);
clkb.deleteSprite();
clkb.unloadFont();
if (currentIndex >= 5)
currentIndex = 0; //回第一个
else
currentIndex += 1; //准备切换到下一个
}
}
/*-------- NTP code ----------*/
const int NTP_PACKET_SIZE = 48; // NTP时间在消息的前48字节中
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets
//获取时间
time_t getNtpTime()
{
IPAddress ntpServerIP; // NTP server's ip address
while (Udp.parsePacket() > 0) ; // discard any previously received packets
WiFi.hostByName(ntpServerName, 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 buffer
unsigned long secsSince1900;
// convert four bytes starting at location 40 to a long integer
secsSince1900 = (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;
}
}
return 0; // 无法获取时间时返回0
}
// 向NTP服务器发送请求
void sendNTPpacket(IPAddress &address)
{
// set all bytes in the buffer to 0
memset(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, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[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 123
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}
loadingimg.cpp
#include "loadingimg.h"
#include <TJpg_Decoder.h>
//显示白色36*60大小数字
void LOADING_IMG::printfloading(int x,int y,int numn)
{
switch (numn)
{
case 0:
TJpgDec.drawJpg(x, y, ii0, sizeof(ii0));
break;
case 1:
TJpgDec.drawJpg(x, y, ii1, sizeof(ii1));
break;
case 2:
TJpgDec.drawJpg(x, y, ii2, sizeof(ii2));
break;
case 3:
TJpgDec.drawJpg(x, y, ii3, sizeof(ii3));
break;
case 4:
TJpgDec.drawJpg(x, y, ii4, sizeof(ii4));
break;
case 5:
TJpgDec.drawJpg(x, y, ii5, sizeof(ii5));
break;
case 6:
TJpgDec.drawJpg(x, y, ii6, sizeof(ii6));
break;
case 7:
TJpgDec.drawJpg(x, y, ii7, sizeof(ii7));
break;
case 8:
TJpgDec.drawJpg(x, y, ii8, sizeof(ii8));
break;
case 9:
TJpgDec.drawJpg(x, y, ii9, sizeof(ii9));
break;
case 10:
TJpgDec.drawJpg(x, y, ii10, sizeof(ii10));
break;
case 11:
TJpgDec.drawJpg(x, y, ii11, sizeof(ii11));
break;
case 12:
TJpgDec.drawJpg(x, y, ii12, sizeof(ii12));
break;
case 13:
TJpgDec.drawJpg(x, y, ii13, sizeof(ii13));
break;
case 14:
TJpgDec.drawJpg(x, y, ii14, sizeof(ii14));
break;
case 15:
TJpgDec.drawJpg(x, y, ii15, sizeof(ii15));
break;
case 16:
TJpgDec.drawJpg(x, y, ii16, sizeof(ii16));
break;
case 17:
TJpgDec.drawJpg(x, y, ii17, sizeof(ii17));
break;
case 18:
TJpgDec.drawJpg(x, y, ii18, sizeof(ii18));
break;
case 19:
TJpgDec.drawJpg(x, y, ii19, sizeof(ii19));
break;
case 20:
TJpgDec.drawJpg(x, y, ii20, sizeof(ii20));
break;
case 21:
TJpgDec.drawJpg(x, y, ii21, sizeof(ii21));
break;
case 22:
TJpgDec.drawJpg(x, y, ii22, sizeof(ii22));
break;
case 23:
TJpgDec.drawJpg(x, y, ii23, sizeof(ii23));
break;
case 24:
TJpgDec.drawJpg(x, y, ii24, sizeof(ii24));
break;
case 25:
TJpgDec.drawJpg(x, y, ii25, sizeof(ii25));
break;
case 26:
TJpgDec.drawJpg(x, y, ii26, sizeof(ii26));
break;
case 27:
TJpgDec.drawJpg(x, y, ii27, sizeof(ii27));
break;
case 28:
TJpgDec.drawJpg(x, y, ii28, sizeof(ii28));
break;
case 29:
TJpgDec.drawJpg(x, y, ii29, sizeof(ii29));
break;
case 30:
TJpgDec.drawJpg(x, y, ii30, sizeof(ii30));
break;
case 31:
TJpgDec.drawJpg(x, y, ii31, sizeof(ii31));
break;
case 32:
TJpgDec.drawJpg(x, y, ii32, sizeof(ii32));
break;
case 33:
TJpgDec.drawJpg(x, y, ii33, sizeof(ii33));
break;
case 34:
TJpgDec.drawJpg(x, y, ii34, sizeof(ii34));
break;
case 35:
TJpgDec.drawJpg(x, y, ii35, sizeof(ii35));
break;
default:
Serial.println("显示AnimLoad错误");
break;
}
}
loadingimg.h
#define LOADING_IMG_H
#include <TFT_eSPI.h>
//将图片转换过的。h文件
#include "img/picture/donghua/ii0.h"
#include "img/picture/donghua/ii1.h"
#include "img/picture/donghua/ii2.h"
#include "img/picture/donghua/ii3.h"
#include "img/picture/donghua/ii4.h"
#include "img/picture/donghua/ii5.h"
#include "img/picture/donghua/ii6.h"
#include "img/picture/donghua/ii7.h"
#include "img/picture/donghua/ii8.h"
#include "img/picture/donghua/ii9.h"
#include "img/picture/donghua/ii10.h"
#include "img/picture/donghua/ii11.h"
#include "img/picture/donghua/ii12.h"
#include "img/picture/donghua/ii13.h"
#include "img/picture/donghua/ii14.h"
#include "img/picture/donghua/ii15.h"
#include "img/picture/donghua/ii16.h"
#include "img/picture/donghua/ii17.h"
#include "img/picture/donghua/ii18.h"
#include "img/picture/donghua/ii19.h"
#include "img/picture/donghua/ii20.h"
#include "img/picture/donghua/ii21.h"
#include "img/picture/donghua/ii22.h"
#include "img/picture/donghua/ii23.h"
#include "img/picture/donghua/ii24.h"
#include "img/picture/donghua/ii25.h"
#include "img/picture/donghua/ii26.h"
#include "img/picture/donghua/ii27.h"
#include "img/picture/donghua/ii28.h"
#include "img/picture/donghua/ii29.h"
#include "img/picture/donghua/ii30.h"
#include "img/picture/donghua/ii31.h"
#include "img/picture/donghua/ii32.h"
#include "img/picture/donghua/ii33.h"
#include "img/picture/donghua/ii34.h"
#include "img/picture/donghua/ii35.h"
class LOADING_IMG
{
private:
public:
void printfloading(int numx,int numy,int numn);
};