因为每次都要做大量的测试,上传到单片机实在是太费事,所以写了这个模拟项目用来测试
很多方法我没有补充进去,因为太多了,如果有需要请自行补充
stdafx.h
#pragma once#include<iostream>
#include<atlimage.h>
#include<time.h>
#include<string>
#include <ws2tcpip.h>
#include<Windows.h>
FS.h
#pragma once
#include"stdafx.h"
#define HSPI 0
#define OUTPUT 0
#define HIGH 0
#define LOW 0
class SPIClass
{
public:SPIClass(int t) {};void begin(int, int, int, int) {};
};
class serial {
public:serial() {};void begin(int) {};void println(const char *t) {printf("%s\n", t);};
};
void pinMode(int, int);
void digitalWrite(int, int);
SD.h
#pragma once
#include"stdafx.h"
#define CARD_NONE 0
#pragma warning(disable:4996)
#define MN_PATH "D:\\Program Files\\all\\desktop\\SD"
class String :public std::string
{
public:String() : std::string() {}String(const char*t) :std::string(t) {}int indexOf(const char *st){return this->find(st, 0);}String substring(int _off, int ct = -1){if (ct == -1){ct = this->length();}String h= this->substr(_off, ct).c_str();return h;}
};
class File
{
private:FILE* fp;
public:File(const char *path){this->fp = fopen(path, "rb");}explicit operator bool() const { // 防止隐式转换到其他类型return fp!=NULL; /* 根据对象状态返回true/false */;}String readStringUntil(char ends){String t = "";char t1;int lna = 0;while ((lna = fread(&t1, 1, 1, this->fp))>0){t+=t1;if (t1 == ends)break;}return t;}void close(){fclose(this->fp);}void seek(long pos){fseek(this->fp, pos, 0);}int read(void *addr, int size){return fread(addr, size, 1, this->fp);}
};
class sd {
public:sd() {};bool begin(int, SPIClass&t) { return true; }int cardType() { return 1; }File open(const char*path){int len = strlen(path) + 1;char *t = new char[len];memset(t, 0, sizeof(len));strcat(t,path);for (int i = 0; i < len; i++)if (t[i] == '/')t[i] = '\\';std::string p = MN_PATH;p += t;File file(p.c_str());return file;}
};
SPI.h
#pragma once
#include"stdafx.h"
void delay(int min);
long millis();
void loop();
void setup();
void setmillis(long t);
TFT_eSPI.h
#pragma once
#include"stdafx.h"
#pragma warning(disable:4996)
#define TFT_BLUE 0x1F
#define TFT_GREEN 0x3E0
#define TFT_BLACK 0x0000
#define TFT_WHITE 0x7FFF
#define TFT_WIDTH 160
#define TFT_HEIGHT 128
#define TFT_SCA 4LRESULT CALLBACK GLWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
DWORD WINAPI CTF(void*E);
int Get_real_col(uint16_t c1);
class TMp2
{
public:HWND*hwnd;HINSTANCE *hInstance;bool *ok;
};
class TFT_eSPI
{
public:static HINSTANCE hInstance;static HWND hwnd;static bool ok,canrun;static void setH(HINSTANCE hInstance){TFT_eSPI::hInstance = hInstance;}static CImage img;static bool img_ch;static void CT(){if (ok)return;TMp2 *t=new TMp2();t->hwnd = &(TFT_eSPI::hwnd);t->hInstance = &(TFT_eSPI::hInstance);t->ok = &(TFT_eSPI::ok);CreateThread(0, 0, CTF, t, 0, 0);}int col;TFT_eSPI() {}void init(){CT();Sleep(400);while (!ok){Sleep(400);}img.Create(TFT_WIDTH, TFT_HEIGHT, 24);}void setRotation(int) {};void fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color){HDC hdc = GetDC(hwnd);RECT rect;rect.left = x* TFT_SCA;rect.top = y * TFT_SCA;rect.right = x * TFT_SCA +(w * TFT_SCA);rect.bottom = y * TFT_SCA +(h * TFT_SCA);HBRUSH hb = CreateSolidBrush(Get_real_col(color));HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, hb);FillRect(hdc, &rect, hb);SelectObject(hdc, hOldBrush);DeleteObject(hb);ReleaseDC(hwnd, hdc);}void fillCircle(int prevX1, int prevY1, int R, int BG_COLOR){int prevX = prevX1 * TFT_SCA;int prevY = prevY1 * TFT_SCA;HDC hdc = GetDC(hwnd);HPEN hTransparentPen = CreatePen(PS_NULL, 1, RGB(0, 0, 0));HPEN hOldPen = (HPEN)SelectObject(hdc, hTransparentPen);// 设置画笔颜色和样式HBRUSH hb = CreateSolidBrush( Get_real_col(BG_COLOR));HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, hb);// 绘制圆,左上角坐标(100, 100),半径100int r = R *TFT_SCA;Ellipse(hdc, prevX-r, prevY-r, prevX+r, prevY+r);// 恢复原来的画笔并删除新画笔SelectObject(hdc, hOldPen);SelectObject(hdc, hOldBrush);DeleteObject(hTransparentPen);DeleteObject(hb);ReleaseDC(hwnd, hdc);}void fillScreen(uint16_t col){RECT rect;rect.left = 0;rect.top = 0;rect.right = TFT_WIDTH* TFT_SCA;rect.bottom = TFT_HEIGHT* TFT_SCA;HBRUSH hb= CreateSolidBrush(Get_real_col(col));HDC hdc = GetDC(hwnd);FillRect(hdc, &rect, hb);ReleaseDC(hwnd,hdc);DeleteObject(hb);}void setTextColor(uint16_t col){this->col = Get_real_col(col);}void drawString(const char *str, int x, int y, int fontsize=1){RECT rect;rect.left = x* TFT_SCA;rect.top = y* TFT_SCA;rect.right = TFT_WIDTH * TFT_SCA;rect.bottom = TFT_HEIGHT * TFT_SCA;HDC hdc = GetDC(hwnd);SetTextColor(hdc, this->col);LOGFONT lf;memset(&lf, 0, sizeof(LOGFONT));lf.lfHeight = -MulDiv(fontsize* TFT_SCA *5, GetDeviceCaps(hdc, LOGPIXELSY), 72); // 设置字体高度(20磅)lf.lfWeight = FW_NORMAL; // 字体粗细strcpy(lf.lfFaceName, "Arial"); // 字体名称HFONT hFont = CreateFontIndirect(&lf);HFONT hOldFont = (HFONT)SelectObject(hdc, hFont);int nOldMode = SetBkMode(hdc, TRANSPARENT);DrawText(hdc, str, strlen(str), &rect, DT_LEFT); SetBkMode(hdc, nOldMode);SelectObject(hdc, hOldFont);DeleteObject(hFont);ReleaseDC(hwnd, hdc);}void startWrite(){img_ch = true;}int x,y,w,h;void setAddrWindow(int x, int y, int w, int h){this->h = h;this->x = x;this->y = y;this->w = w;}void pushPixels(uint16_t*rowBuffer, int size){unsigned char* rgb1 = (unsigned char*)img.GetBits();int pitch1 = img.GetPitch();int i = this->y;for (int j1 = 0; j1 < size; j1 ++){int j = this->x + j1;uint16_t c = rowBuffer[j1];c = (c << 8) | (c >> 8);c = c >> 1;unsigned char r, g, b;r = (c >> 10&0x1F) * 8;g = (c >> 5 & 0x1F) * 8;b = (c & 0x1F) * 8;*(rgb1 + (j * 3) + (i * pitch1) + 0) = b;*(rgb1 + (j * 3) + (i * pitch1) + 1) = g;*(rgb1 + (j * 3) + (i * pitch1) + 2) = r;}}void endWrite(){HDC hdc = GetDC(TFT_eSPI::hwnd);TFT_eSPI::img.StretchBlt(hdc, 0, 0, TFT_SCA*TFT_WIDTH, TFT_SCA * TFT_HEIGHT);ReleaseDC(hwnd, hdc);}
};
int constrain(int value, int min_value, int max_value);
WiFi.h
#pragma once
#include"stdafx.h"
#pragma comment(lib, "ws2_32.lib")
#define WL_CONNECTED 0
class Tmp
{
public:Tmp(){}const char* toString(){return "192.168.0.123";}
};
class wifi
{
public:static __time64_t _time_net;wifi() {WSADATA wsaData;WSAStartup(MAKEWORD(2, 2), &wsaData);};void begin(const char*, const char*) { Sleep(1000); }int status(){return 0;}Tmp localIP(){Tmp t;return t;}
};
void configTime(long gmtOffset_sec, int daylightOffset_sec, const char* ntpServer);
bool getLocalTime(tm* tm1);
other.cpp
#include "FS.h"
#include "SD.h"
#include "SPI.h"
#include "TFT_eSPI.h"
#include "WiFi.h"
void delay(int min)
{}
long t1 = 0;
void setmillis(long t)
{t1 = t;
}
long millis()
{return t1;
}
void digitalWrite(int, int) {}
void pinMode(int, int)
{}
__time64_t wifi::_time_net = 0;uint64_t tryNtpServer(const char* server) {SOCKET sock = INVALID_SOCKET;char buffer[48] = { 0 };struct addrinfo hints = { 0 }, * res = nullptr;// 解析DNShints.ai_family = AF_INET;hints.ai_socktype = SOCK_DGRAM;if (getaddrinfo(server, "123", &hints, &res) != 0) {std::cerr << "[DNS Error] " << server << std::endl;return 0;}// 遍历所有解析到的IP地址for (auto* ptr = res; ptr != nullptr; ptr = ptr->ai_next) {sock = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);if (sock == INVALID_SOCKET) continue;// 配置套接字选项// setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&NTP_TIMEOUT, sizeof(NTP_TIMEOUT));// 构造NTP请求包memset(buffer, 0, 48);buffer[0] = 0x1B; // NTPv3客户端模式// 发送请求if (sendto(sock, buffer, 48, 0,ptr->ai_addr, (int)ptr->ai_addrlen) <= 0) {closesocket(sock);continue;}// 接收响应int bytes = recv(sock, buffer, 48, 0);if (bytes > 0) {uint32_t seconds = ntohl(*((uint32_t*)(buffer + 40)));freeaddrinfo(res);closesocket(sock);return seconds - 2208988800ULL; // 转换为Unix时间戳}closesocket(sock);}freeaddrinfo(res);return 0;
}
void configTime(long gmtOffset_sec, int daylightOffset_sec, const char* ntpServer)
{wifi::_time_net = tryNtpServer(ntpServer);
}
bool getLocalTime(tm* tm1)
{long long t = (wifi::_time_net +( t1/1000));tm* tm_t =localtime(&t);memcpy(tm1, tm_t, sizeof(tm));return true;
}
HINSTANCE TFT_eSPI::hInstance=NULL;
HWND TFT_eSPI::hwnd=NULL;
bool TFT_eSPI::ok=false;
bool TFT_eSPI::canrun = true;
bool TFT_eSPI::img_ch = false;
CImage TFT_eSPI::img;
LRESULT CALLBACK GLWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{switch (msg){case WM_CLOSE:PostQuitMessage(0);TFT_eSPI::canrun = false;return 0;default:break;}return DefWindowProc(hwnd, msg, wParam, lParam);
}DWORD WINAPI CTF(void*e)
{TMp2*E = (TMp2*)e;WNDCLASSEX wndclass;wndclass.cbClsExtra = 0;wndclass.cbSize = sizeof(WNDCLASSEX);wndclass.cbWndExtra = 0;wndclass.hbrBackground = NULL;wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);wndclass.hIcon = NULL;wndclass.hIconSm = NULL;wndclass.hInstance = *(E->hInstance);wndclass.lpfnWndProc = GLWindowProc;wndclass.lpszClassName = "GLWindow";wndclass.lpszMenuName = NULL;wndclass.style = CS_VREDRAW | CS_HREDRAW;ATOM atom = RegisterClassEx(&wndclass);if (!atom){MessageBox(NULL, "Notice", "Error", MB_OK);return 0;}HWND hwnd = CreateWindowEx(NULL, "GLWindow", "TFT模拟", WS_OVERLAPPEDWINDOW, 0, 0, TFT_WIDTH*TFT_SCA+16, TFT_HEIGHT * TFT_SCA+37, NULL, NULL, *(E->hInstance), NULL);*(E->hwnd) = hwnd;ShowWindow(hwnd, SW_SHOW);UpdateWindow(hwnd);*(E->ok) = true;//程序持续运行MSG msg;while (true){if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)){if (msg.message == WM_QUIT)break;TranslateMessage(&msg);DispatchMessage(&msg);}}return 0;
}
int Get_real_col(uint16_t c)
{unsigned char r, g, b;r = (c >> 10 & 0x1F) * 8;g = (c >> 5 & 0x1F) * 8;b =( c & 0x1F )* 8;//printf("%d %d %d %d\n",c, r,g,b);return RGB(r,g,b);
}
int constrain(int value, int min_value, int max_value) {return min(max(value, min_value), max_value);
}#ifdef _CONSOLE
int main()
#elif
int WINAPI WinMain(HINSTANCE h1, HINSTANCE h2, LPSTR cmd, int show)
#endif
{
#ifdef _CONSOLEHINSTANCE h1 = GetModuleHandle(NULL);
#endifTFT_eSPI::setH(h1);setup();long t = 0;while (1){if (!TFT_eSPI::canrun)break;loop();/*if (TFT_eSPI::img_ch){TFT_eSPI::img_ch = false;}*/Sleep(50);t = t + 50;setmillis(t);}
}
测试用.cpp
#include "SPI.h"
#include "wifi.h"
#include "FS.h"
#include "SD.h"
#include "TFT_eSPI.h"
#ifdef WIN32
serial Serial;
wifi WiFi;
sd SD;
#endifconst char* ntpServer = "time.windows.com";
const long gmtOffset_sec = 8 * 3600; // 东八区(北京时间)
const int daylightOffset_sec = 0;
#define HSPI_CLK 14
#define HSPI_MISO 12
#define HSPI_MOSI 13
#define HSPI_CS 15
#define SD_CS 15
#define TFT_CS 5 // TFT片选引脚
TFT_eSPI tft;
SPIClass spiSD(HSPI); // 创建HSPI对象
void setup() {tft.init();tft.setTextColor(TFT_WHITE);tft.fillScreen(TFT_BLACK);tft.fillRect(60-5, 20, 9, 32, TFT_GREEN);tft.fillRect(100-5, 20, 9, 32, TFT_GREEN);
}
unsigned long lastTime = 0;
int y = 0;
#define AD 8
int ad = AD;
int t11 = 3;
void loop() {if (t11 >= 3|| t11==2){tft.fillRect(60 - 5, 20 + y, 9, AD, TFT_BLACK);}if (t11 >= 3 || t11 == 1){tft.fillRect(100 - 5, 20 + y, 9, AD, TFT_BLACK);}y += ad;if (t11 >= 3 || t11 == 2){tft.fillRect(60 - 5, 20 + y, 9, 32 - y, TFT_GREEN);}if (t11 >= 3 || t11 == 1){tft.fillRect(100 - 5, 20 + y, 9, 32 - y, TFT_GREEN);}if (y <= 0) {ad = AD;Sleep(rand() % 10*500);t11 = rand() % 3 + 1;}else if (y >= 32){ad = -AD;}
}