• 首页

  • 动态

  • 随笔

  • 学习

  • 留言板

  • 文章归档

  • 友情链接

  • 关于页面
S w e e t 的 笔 记
S w e e t 的 笔 记

SuSweet

这个人有点懒,他是个学生,他只会摸鱼,并且从来不写个性签名。

04月
22
默认分类
电控
学习感悟

指针式CPU与内存占用表DIY

发表于 2022-04-22 • 字数统计 9732 • 被 1,909 人看爆

这个项目是受到B站一个视频启发而做的。Up主他其实是有开源了整套方案的,但是作为一个整天摸鱼的大学生,这种东西肯定还是自己重新实现一遍有意思啦。
参考视频地址:https://www.bilibili.com/video/BV1jL4y1x7gx?share_source=copy_web

既然决定要自己动手做,第一步那得首先确定要用什么硬件。我本身最熟悉的单片机应该是STM32的,使用STM32配合STM32CubeMX程序实现起来也简单。原先我的计划是,pc端的上位机直接通过串口将数据发送到单片机显示。但是现在芯片的价格实在太高了,以前几块钱就能买到的最小系统板都涨了不少,那我也没必要为了那么简单的功能使用显然会资源过剩的单片机了。

最终我选用了esp8266作为控制芯片。当然,既然都选了esp8266了,那数据交换只用串口不用网络就说不过去了。起码也得使用http get或者post。有可能的话最好还要使用mqtt进行通信。

简单测试一下
目前项目PC端代码可以在我的Gitee上找到。

获取内存占用代码:

/*内存使用率*/
//windows 内存 使用率  
DWORD getWin_MemUsage(void)
{
	MEMORYSTATUSEX ms;
	ms.dwLength = sizeof(ms);
	GlobalMemoryStatusEx(&ms);
	//cout << left << setw(17) << "内存占用率:" << setw(3) << ms.dwMemoryLoad << "%" << endl;
	return ms.dwMemoryLoad;
}

获取CPU占用率代码:

FILETIME preidleTime;
FILETIME prekernelTime;
FILETIME preuserTime;

FILETIME idleTime;
FILETIME kernelTime;
FILETIME userTime;

int get_CPU_usage_init(void)
{
    res = GetSystemTimes(&idleTime, &kernelTime, &userTime);

    preidleTime = idleTime;
    prekernelTime = kernelTime;
    preuserTime = userTime;

    return 0;
}
int get_CPU_usage(void)
{
    res = GetSystemTimes(&idleTime, &kernelTime, &userTime);

    __int64 idle = CompareFileTime(preidleTime, idleTime);
    __int64 kernel = CompareFileTime(prekernelTime, kernelTime);
    __int64 user = CompareFileTime(preuserTime, userTime);
    int cpu = (kernel + user - idle) * 100 / (kernel + user);
    //cout << kernel << "     " << user << "     " << idle << endl;
    preidleTime = idleTime;
    prekernelTime = kernelTime;
    preuserTime = userTime;

    return cpu;
}

上位机与单片机通信可选http get或者是mqtt进行。目前已实现通过get来获取。这部分代码参考了网上的资料。但是网上找到的资料有些在我的环境下get失败。另外还有无响应时卡住、长时间运行卡住等小问题。所以进行了一点点的修改优化。
通信代码:

#define IPSTR "192.168.1.112" //服务器IP地址;
#define PORT 80 //服务器端口;
#define BUFSIZE 1024

class httpClient {
	std::string host;
	std::string path;
	std::string post_content;
public:
	std::string httpSend(std::string httpHeader);
	std::string httpGet(std::string host, std::string path);
	std::string httpPost(std::string host, std::string path, std::string post_content);
};
std::string httpClient::httpSend(std::string httpHeader) {
	//POST请求方式
	std::string ret = ""; // 返回Http Response
	// 开始进行socket初始化
	WSADATA wData;
	::WSAStartup(MAKEWORD(2, 2), &wData);
	SOCKET clientSocket = socket(AF_INET, 1, 0);
	struct sockaddr_in ServerAddr = { 0 };
	ServerAddr.sin_addr.s_addr = inet_addr(IPSTR);
	ServerAddr.sin_port = htons(PORT);
	ServerAddr.sin_family = AF_INET;
	int errNo = connect(clientSocket, (sockaddr*)&ServerAddr, sizeof(ServerAddr));
	if (errNo == 0) {
		errNo = send(clientSocket, httpHeader.c_str(), httpHeader.length(), 0);//发送头文件 
		if (errNo > 0) {
			std::cout << "发送成功" << std::endl;
		}
		else {
			std::cout << "errNo:" << errNo << std::endl;
			// socket环境清理
			::WSACleanup();
			return ret;
		}
		// 接收
		char bufRecv[3069] = { 0 };
		errNo = recv(clientSocket, bufRecv, 3069, 0);
		if (errNo > 0) {
			ret = bufRecv;// 如果接收成功,则返回接收的数据内容
			char* p;
			char* delims = { "\n" };
			p = strtok(bufRecv, "\n");
			int i = 0;
			while (p != NULL) {
				if (i == 13) {
					ret = p;
				}
				i++;
				p = strtok(NULL, delims);
			}
			// socket环境清理
			::WSACleanup();
			return ret;
		}
		else {
			std::cout << "errNo:" << errNo << std::endl;
			// socket环境清理
			::WSACleanup();
			return ret;
		}
	}
	else {
		errNo = WSAGetLastError();
		std::cout << "errNo:" << errNo << std::endl;
		// socket环境清理
		::WSACleanup();
		return ret;
	}

}
/** Get 请求 */
std::string httpClient::httpGet(std::string host, std::string path) {
	std::string httpHeader;
	httpHeader =
		"GET " + path + " HTTP/1.1\r\n"
		"Host: " + host + "\r\n"
		"User-Agent: IE or Chrome\r\n"
		"Accept-Type: */*\r\n"
		"Connection: Close\r\n\r\n";
	return httpSend(httpHeader);
}
/** Post 请求 */
std::string httpClient::httpPost(std::string host, std::string path, std::string post_content) {
	std::string httpHeader;
	char lenChar[16]; //这个长度根据需要吧
	sprintf(lenChar, "%d", (int)post_content.length());
	std::string len(lenChar);
	httpHeader =
		"POST " + path + " HTTP/1.1\r\n"
		"Accept-Encoding: gzip, deflate"
		"Host: " + host + "\r\n"
		"Connection: keep-alive\r\n"
		"Content-Type: application/x-www-form-urlencoded\r\n"
		"Content-Length: " + len + "\r\n\r\n"
		+ post_content;
	return httpSend(httpHeader);
}

esp8266是在arduino的平台上开发的,参考代码:

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include "Ticker.h"
#ifndef STASSID
#define STASSID "wifi_ssid"
#define STAPSK  "wifi_密码"
#endif

const char* ssid     = STASSID;
const char* password = STAPSK;

int cpu_usage = 0;
int mem_usage = 0;
int cpu_usage_display = 0;
int mem_usage_display = 0;
Ticker displayTicker; //建立一个需要定时调度的对象
ESP8266WebServer server(80);

const int led = LED_BUILTIN;

const String postForms = "<html>\
  <head>\
    <title>ESP8266 Web Server POST handling</title>\
    <style>\
      body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }\
    </style>\
  </head>\
  <body>\
    <h1>POST plain text to /postplain/</h1><br>\
    <form method=\"post\" enctype=\"text/plain\" action=\"/postplain/\">\
      <input type=\"text\" name=\'{\"hello\": \"world\", \"trash\": \"\' value=\'\"}\'><br>\
      <input type=\"submit\" value=\"Submit\">\
    </form>\
    <h1>POST form data to /postform/</h1><br>\
    <form method=\"post\" enctype=\"application/x-www-form-urlencoded\" action=\"/postform/\">\
      <input type=\"text\" name=\"hello\" value=\"world\"><br>\
      <input type=\"text\" name=\"sweet\" value=\"summer\"><br>\
      <input type=\"text\" name=\"cpu_usage\" value=\"50\"><br>\
      <input type=\"text\" name=\"mem_usage\" value=\"60\"><br>\
      <input type=\"submit\" value=\"Submit\">\
    </form>\
    <h1>update device data</h1><br>\
    <form method=\"post\" enctype=\"application/x-www-form-urlencoded\" action=\"/device/\">\
      <input type=\"text\" name=\"cpu_usage\" value=\"50\"><br>\
      <input type=\"text\" name=\"mem_usage\" value=\"60\"><br>\
      <input type=\"submit\" value=\"Submit\">\
    </form>\
  </body>\
</html>";

void tickerHandle() //到时间时需要执行的任务
{
  if((cpu_usage*10+cpu_usage_display*9)/10 == cpu_usage_display && cpu_usage_display > (cpu_usage*10))
  {
    cpu_usage_display--;
  }
  else if((cpu_usage*10+cpu_usage_display*9)/10 == cpu_usage_display && cpu_usage_display < (cpu_usage*10))
  {
    cpu_usage_display++;
  }
  else
  {
    cpu_usage_display = (cpu_usage*10+cpu_usage_display*9)/10;
  }
  analogWrite(15, cpu_usage_display*105/100);  // D8
}

void handleRoot() {
  digitalWrite(led, 1);
  server.send(200, "text/html", postForms);
  digitalWrite(led, 0);
}

void handlePlain() {
  if (server.method() != HTTP_POST) {
    digitalWrite(led, 1);
    server.send(405, "text/plain", "Method Not Allowed");
    digitalWrite(led, 0);
  } else {
    digitalWrite(led, 1);
    server.send(200, "text/plain", "POST body was:\n" + server.arg("plain"));
    digitalWrite(led, 0);
  }
}

void handleForm() {
  if (server.method() != HTTP_POST) {
    digitalWrite(led, 1);
    server.send(405, "text/plain", "Method Not Allowed");
    digitalWrite(led, 0);
  } else {
    digitalWrite(led, 1);
    String message = "POST form was:\n";
    for (uint8_t i = 0; i < server.args(); i++) {
      message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
    }
    server.send(200, "text/plain", message);
    digitalWrite(led, 0);
  }
}

void handleDevice() {
  if (server.method() != HTTP_POST) {
    digitalWrite(led, 1);
    server.send(405, "text/plain", "Method Not Allowed");
    digitalWrite(led, 0);
  } else {
    digitalWrite(led, 1);
    String message = "POST form was:\n";
    for (uint8_t i = 0; i < server.args(); i++) {
      message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
      if(server.argName(i) == "cpu_usage")
      {
        cpu_usage = server.arg(i).toInt();
        Serial.print("cpu usage:");
        Serial.println(cpu_usage);
      }
      else if(server.argName(i) == "mem_usage")
      {
        mem_usage = server.arg(i).toInt();
        Serial.print("mem usage:");
        Serial.println(mem_usage);
      }
    }
    server.send(200, "text/plain", message);
    Serial.println("=====================================================");
    digitalWrite(led, 0);
  }
}

void handleNotFound() {
  digitalWrite(led, 1);
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
  digitalWrite(led, 0);
}

void setup(void) {
  pinMode(led, OUTPUT);
  digitalWrite(led, 0);
  analogWriteFreq(1000);
  analogWriteRange(1100);
  pinMode(15, OUTPUT);
  analogWrite(15, 0);  // D8
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  if (MDNS.begin("sweet")) {
    Serial.println("MDNS responder started");
  }

  server.on("/", handleRoot);

  server.on("/postplain/", handlePlain);

  server.on("/postform/", handleForm);

  server.on("/device/",handleDevice);

  server.onNotFound(handleNotFound);

  server.begin();
  Serial.println("HTTP server started");

  displayTicker.attach(0.1,tickerHandle);
}

void loop(void) {
  server.handleClient();
  MDNS.update();
}

目前测试正常。

待续。。。

分享到:
使用MATLAB的simulink进行无刷电机仿真
网站备案准备资料(随手记)
  • 文章目录
  • 站点概览
SuSweet

可爱的 SuSweet

你能抓到我么?

QQ Email RSS
看爆 Top5
  • 代码里中文注释变成锟斤拷啦 6,878次看爆
  • Code Composer Studio (CCS)报错program will not fit into available memory (280049C)(#10099-D) 4,396次看爆
  • 解决python中cv2无法自动补全的方法 4,240次看爆
  • CCS中IQmath库报错(_IQ24div(long, long)没有定义) 3,913次看爆
  • 使用GM6020电机参数的Simulink电机控制仿真记录 3,867次看爆

很高兴在这里遇到您!如果您遇到什么问题,或者想留下您的链接,欢迎->网站问题反馈

当然,您也可以通过电子邮件联系我。

Copyright © 2026 SuSweet 粤ICP备2022045669号

由 Halo 强力驱动 · Theme by Sagiri · 站点地图