Jump to content

墨香年少

Administrators
  • Content Count

    309
  • Joined

  • Last visited

  • Days Won

    18

墨香年少 last won the day on March 13

墨香年少 had the most liked content!

Community Reputation

32 童生

1 Follower

About 墨香年少

  • Rank
    入门
  • Birthday 05/22/1985

Recent Profile Visitors

5388 profile views
  1. #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; int main() { // 读取图像 Mat image = imread("your_image_path.jpg"); if (image.empty()) { std::cerr << "Error: Could not read the image file." << std::endl; return -1; } // 将图像转换为HSV颜色空间 Mat hsv_image; cvtColor(image, hsv_image, COLOR_BGR2HSV); // 计算直方图 int hbins = 30, sbins = 32; int histSize[] = {hbins, sbins}; float hranges[] = {0, 180}; // hue的范围 float sranges[] = {0, 256}; // saturation的范围 const float* ranges[] = {hranges, sranges}; MatND hist; int channels[] = {0, 1}; calcHist(&hsv_image, 1, channels, Mat(), hist, 2, histSize, ranges, true, false); // 找到直方图中的最大值 double maxVal = 0; Point maxLoc; minMaxLoc(hist, nullptr, &maxVal, nullptr, &maxLoc); // 最大值对应的色调(hue)和饱和度(saturation) int hmax = maxLoc.x; int smax = maxLoc.y; // 转换回BGR颜色空间 Mat dominant_color_hsv = Mat::zeros(1, 1, CV_8UC3); dominant_color_hsv.at<Vec3b>(0, 0) = Vec3b(hmax, smax, 255); // Value为255 Mat dominant_color_bgr; cvtColor(dominant_color_hsv, dominant_color_bgr, COLOR_HSV2BGR); // 提取主要颜色的BGR值 Vec3b main_color = dominant_color_bgr.at<Vec3b>(0, 0); int b = main_color[0]; int g = main_color[1]; int r = main_color[2]; // 输出主要颜色的BGR值 std::cout << "Main color BGR: (" << b << ", " << g << ", " << r << ")" << std::endl; return 0; }
  2. 效果如下: compress_file.exe decompress_file.exe
  3. 1. 设置开发环境 Windows 环境(Qt) 安装 Qt 和 Qt Creator: 下载并安装 Qt Creator。 确保安装 Qt 的编译工具(如 MinGW 或 MSVC)。 安装 gRPC 和 Protobuf: 使用 vcpkg 或手动安装 gRPC 和 Protobuf。对于 vcpkg,首先安装 vcpkg,然后运行以下命令: vcpkg install grpc protobuf 配置 Qt 项目以使用 vcpkg: 在 CMakeLists.txt 中添加: set(CMAKE_TOOLCHAIN_FILE "C:/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake") Linux 环境(C++) 安装 gRPC 和 Protobuf: 在 Linux 上安装所需库: sudo apt-get update sudo apt-get install -y build-essential autoconf libtool pkg-config git clone --recurse-submodules -b v1.57.0 https://github.com/grpc/grpc cd grpc mkdir -p cmake/build cd cmake/build cmake -DgRPC_INSTALL=ON -DgRPC_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=Release ../.. make -j sudo make install 确保 Protobuf 也安装成功: sudo apt-get install -y protobuf-compiler 2. 定义 Protobuf 文件 创建一个 Protobuf 文件,定义服务和消息。 syntax = "proto3"; package example; service ExampleService { rpc SayHello (HelloRequest) returns (HelloResponse); } message HelloRequest { string name = 1; } message HelloResponse { string message = 1; } 3. 生成 gRPC 代码 在两种环境中,使用 protoc 工具生成 gRPC 和 Protobuf 的 C++ 代码: protoc --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` example.proto protoc --cpp_out=. example.proto 4. 实现 gRPC 服务器(Linux C++) 创建一个 gRPC 服务器应用程序来响应客户端请求。 #include <iostream> #include <memory> #include <string> #include <grpcpp/grpcpp.h> #include "example.grpc.pb.h" using grpc::Server; using grpc::ServerBuilder; using grpc::ServerContext; using grpc::Status; using example::ExampleService; using example::HelloRequest; using example::HelloResponse; class ExampleServiceImpl final : public ExampleService::Service { Status SayHello(ServerContext* context, const HelloRequest* request, HelloResponse* response) override { std::string prefix("Hello "); response->set_message(prefix + request->name()); return Status::OK; } }; void RunServer() { std::string server_address("0.0.0.0:50051"); ExampleServiceImpl service; ServerBuilder builder; builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); builder.RegisterService(&service); std::unique_ptr<Server> server(builder.BuildAndStart()); std::cout << "Server listening on " << server_address << std::endl; server->Wait(); } int main(int argc, char** argv) { RunServer(); return 0; } 5. 实现 gRPC 客户端(Windows Qt) 创建一个 Qt 项目并实现 gRPC 客户端功能。 #include <QCoreApplication> #include <iostream> #include <grpcpp/grpcpp.h> #include "example.grpc.pb.h" using grpc::Channel; using grpc::ClientContext; using grpc::Status; using example::ExampleService; using example::HelloRequest; using example::HelloResponse; class ExampleClient { public: ExampleClient(std::shared_ptr<Channel> channel) : stub_(ExampleService::NewStub(channel)) {} std::string SayHello(const std::string& user) { HelloRequest request; request.set_name(user); HelloResponse response; ClientContext context; Status status = stub_->SayHello(&context, request, &response); if (status.ok()) { return response.message(); } else { std::cout << "RPC failed" << std::endl; return "RPC failed"; } } private: std::unique_ptr<ExampleService::Stub> stub_; }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); ExampleClient client(grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials())); std::string user("world"); std::string reply = client.SayHello(user); std::cout << "Greeter received: " << reply << std::endl; return a.exec(); } 6. 编译和运行 Windows 下 打开 Qt Creator,加载项目并配置为使用 CMake 和 vcpkg。 构建并运行客户端应用程序。 Linux 下 使用 g++ 或 cmake 构建服务器应用程序。 运行服务器,确保它监听在合适的端口。 7. 测试通信 确保服务器在 Linux 上运行,然后在 Windows 上运行客户端,查看消息传递是否成功。调试任何连接问题可能需要查看网络设置和防火墙配置。
  4. 获取13位时间戳 #include <iostream> #include <chrono> #include <string> // 获取当前的时间戳(毫秒级) long long getTimestamp() { auto now = std::chrono::system_clock::now(); auto duration = now.time_since_epoch(); auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(); return milliseconds; } // 获取当前的时间戳(毫秒级)并转换为字符串 std::string getTimestampString() { auto now = std::chrono::system_clock::now(); auto duration = now.time_since_epoch(); auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(); return std::to_string(milliseconds); } int main() { long long timestamp = getTimestamp(); std::string timestampStr = getTimestampString(); std::cout << "Timestamp as long long: " << timestamp << std::endl; std::cout << "Timestamp as string: " << timestampStr << std::endl; return 0; } [root@VM-0-6-centos cpp]# g++ time13.cpp -o time13 -std=c++11 [root@VM-0-6-centos cpp]# ./time13 Timestamp as 13 long long: 1721732176087 Timestamp as 13 string: 1721732176087
  5. #include <iostream> #include <chrono> #include <string> // 获取当前的时间戳(秒级) int getTimestamp() { auto now = std::chrono::system_clock::now(); auto duration = now.time_since_epoch(); auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count(); return static_cast<int>(seconds); } // 获取当前的时间戳(秒级)并转换为字符串 std::string getTimestampString() { auto now = std::chrono::system_clock::now(); auto duration = now.time_since_epoch(); auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count(); return std::to_string(seconds); } int main() { int timestampInt = getTimestamp(); std::string timestampStr = getTimestampString(); std::cout << "Timestamp as int: " << timestampInt << std::endl; std::cout << "Timestamp as string: " << timestampStr << std::endl; return 0; }
  6. #include <iostream> #include <fstream> #include "addressbook.pb.h" // 这是一个序列化函数,用于将AddressBook对象写入文件 void SerializeToFile(const std::string& filename, const tutorial::AddressBook& address_book) { std::ofstream output(filename, std::ios::out | std::ios::binary); if (!address_book.SerializeToOstream(&output)) { std::cerr << "Failed to write address book." << std::endl; } } // 这是一个反序列化函数,用于从文件中读取AddressBook对象 tutorial::AddressBook DeserializeFromFile(const std::string& filename) { tutorial::AddressBook address_book; std::ifstream input(filename, std::ios::in | std::ios::binary); if (!address_book.ParseFromIstream(&input)) { std::cerr << "Failed to read address book." << std::endl; } return address_book; } int main() { // 初始化Protobuf库 GOOGLE_PROTOBUF_VERIFY_VERSION; // 创建一个AddressBook对象 tutorial::AddressBook address_book; // 向AddressBook对象中添加一个Person对象 tutorial::Person* person = address_book.add_people(); person->set_name("John Doe"); person->set_id(1234); person->set_email("johndoe@example.com"); // 序列化到文件 SerializeToFile("addressbook.bin", address_book); // 反序列化从文件 tutorial::AddressBook new_address_book = DeserializeFromFile("addressbook.bin"); // 打印反序列化后的数据 for (const auto& person : new_address_book.people()) { std::cout << "Person ID: " << person.id() << std::endl; std::cout << " Name: " << person.name() << std::endl; std::cout << " E-mail address: " << person.email() << std::endl; } // 清理Protobuf库 google::protobuf::ShutdownProtobufLibrary(); return 0; }
  7. ThreadPool.h: #ifndef THREAD_POOL_H #define THREAD_POOL_H #include <vector> #include <queue> #include <memory> #include <thread> #include <mutex> #include <condition_variable> #include <future> #include <functional> #include <stdexcept> class ThreadPool { public: ThreadPool(size_t); template<class F, class... Args> auto enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type>; ~ThreadPool(); private: // need to keep track of threads so we can join them std::vector< std::thread > workers; // the task queue std::queue< std::function<void()> > tasks; // synchronization std::mutex queue_mutex; std::condition_variable condition; bool stop; }; // the constructor just launches some amount of workers inline ThreadPool::ThreadPool(size_t threads) : stop(false) { for(size_t i = 0;i<threads;++i) workers.emplace_back( [this] { for(;;) { std::function<void()> task; { std::unique_lock<std::mutex> lock(this->queue_mutex); this->condition.wait(lock, [this]{ return this->stop || !this->tasks.empty(); }); if(this->stop && this->tasks.empty()) return; task = std::move(this->tasks.front()); this->tasks.pop(); } task(); } } ); } // add new work item to the pool template<class F, class... Args> auto ThreadPool::enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> { using return_type = typename std::result_of<F(Args...)>::type; auto task = std::make_shared< std::packaged_task<return_type()> >( std::bind(std::forward<F>(f), std::forward<Args>(args)...) ); std::future<return_type> res = task->get_future(); { std::unique_lock<std::mutex> lock(queue_mutex); // don't allow enqueueing after stopping the pool if(stop) throw std::runtime_error("enqueue on stopped ThreadPool"); tasks.emplace([task](){ (*task)(); }); } condition.notify_one(); return res; } // the destructor joins all threads inline ThreadPool::~ThreadPool() { { std::unique_lock<std::mutex> lock(queue_mutex); stop = true; } condition.notify_all(); for(std::thread &worker: workers) worker.join(); } #endif Basic usage: // create thread pool with 4 worker threads ThreadPool pool(4); // enqueue and store future auto result = pool.enqueue([](int answer) { return answer; }, 42); // get result from future std::cout << result.get() << std::endl;
  8. 线程池的头文件 ThreadPool.h #pragma once #include <queue> #include <vector> #include <thread> #include <mutex> #include <condition_variable> #include <functional> class ThreadPool { public: ThreadPool(size_t numThreads); ~ThreadPool(); template<class F, class... Args> void enqueue(F&& f, Args&&... args); private: // Need to keep track of threads so we can join them std::vector<std::thread> workers; // The task queue std::queue<std::function<void()>> tasks; // Synchronization std::mutex queueMutex; std::condition_variable condition; bool stop; }; // Constructor inline ThreadPool::ThreadPool(size_t numThreads) : stop(false) { for (size_t i = 0; i < numThreads; ++i) { workers.emplace_back( [this] { for (;;) { std::function<void()> task; { std::unique_lock<std::mutex> lock(this->queueMutex); this->condition.wait(lock, [this] { return this->stop || !this->tasks.empty(); }); if (this->stop && this->tasks.empty()) return; task = std::move(this->tasks.front()); this->tasks.pop(); } task(); } } ); } } // Destructor inline ThreadPool::~ThreadPool() { { std::unique_lock<std::mutex> lock(queueMutex); stop = true; } condition.notify_all(); for (std::thread& worker : workers) { worker.join(); } } // Add new work item to the pool template<class F, class... Args> void ThreadPool::enqueue(F&& f, Args&&... args) { { std::function<void()> task = std::bind(std::forward<F>(f), std::forward<Args>(args)...); std::unique_lock<std::mutex> lock(queueMutex); tasks.emplace(std::move(task)); } condition.notify_one(); } 假设我们有一个需要使用线程池执行的复杂计算任务,比如计算一个大型矩阵的乘法。以下是一个简单的示例: Example.cpp: #include "ThreadPool.h" #include <iostream> #include <vector> // Function to multiply two matrices void multiplyMatrices(const std::vector<std::vector<int>>& matrix1, const std::vector<std::vector<int>>& matrix2, std::vector<std::vector<int>>& result, size_t startRow, size_t endRow) { size_t n = matrix1.size(); size_t m = matrix2[0].size(); size_t p = matrix2.size(); for (size_t i = startRow; i < endRow; ++i) { for (size_t j = 0; j < m; ++j) { result[i][j] = 0; for (size_t k = 0; k < p; ++k) { result[i][j] += matrix1[i][k] * matrix2[k][j]; } } } } int main() { const size_t numThreads = 4; ThreadPool pool(numThreads); // Example matrices std::vector<std::vector<int>> matrix1 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; std::vector<std::vector<int>> matrix2 = {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}; std::vector<std::vector<int>> result(matrix1.size(), std::vector<int>(matrix2[0].size(), 0)); // Define the number of rows each thread should handle size_t rowsPerThread = matrix1.size() / numThreads; // Enqueue tasks for each thread for (size_t i = 0; i < numThreads; ++i) { size_t startRow = i * rowsPerThread; size_t endRow = (i == numThreads - 1) ? matrix1.size() : startRow + rowsPerThread; pool.enqueue(multiplyMatrices, std::ref(matrix1), std::ref(matrix2), std::ref(result), startRow, endRow); } // Wait for all tasks to complete // (In this example, we're not synchronizing explicitly because ThreadPool's destructor handles it) // Print the result std::cout << "Resultant matrix:\n"; for (const auto& row : result) { for (int num : row) { std::cout << num << " "; } std::cout << "\n"; } return 0; } ThreadPool 类: 线程池类管理一组线程,并提供了任务队列和同步机制来安全地执行任务。 enqueue 方法: 用于将任务添加到队列中,可以接受任意的函数和参数,并在需要时执行。 ComplexTaskExample.cpp: 展示了如何使用线程池来并行计算两个矩阵的乘法。每个线程负责处理矩阵的一部分行,以提高计算效率。
  9. SDL2 - 一个跨平台开发库,旨在提供硬件抽象层。 FLTK - 适用于 UNIX®/Linux® (X11)、Microsoft® Windows® 和 MacOS® X 的跨平台 C++ GUI 工具包。 asio - 用于网络和低级 I/O 编程的跨平台 C++ 库。 g3log - 一个易于使用的异步、“崩溃安全”记录器。 lua - 一种强大、高效、轻量级、可嵌入的脚本语言。 sol2 - 快速、简单的 C++ 和 Lua 绑定。 tinyxml2 - 一个简单、小型、高效的 C++ XML 解析器。 utf8-cpp - 一个简单、可移植且轻量级的 C++ 库,用于 UTF-8 字符串处理。 libpng - 官方 PNG 参考库,修补了 APNG 支持。 ThreadPool - 一个简单的 C++11 线程池实现。 SQLiteCpp - SQLiteC++ (SQLiteCpp) 是一个智能且易于使用的 C++ SQLite3 包装器。
  10. 有很多非中国的程序员在线接单网站,其中一些包括: Upwork: 这是全球最大的自由职业者平台之一,覆盖了各种技能领域,包括软件开发和编程。 Freelancer: 类似于Upwork,Freelancer也是一个全球自由职业者市场,提供软件开发和编程项目。 Toptal: Toptal聚焦于连接顶尖的自由职业者与客户,提供高质量的软件开发和设计服务。 Guru: Guru是一个在线自由职业者市场,提供软件开发、网站开发等服务。 PeoplePerHour: 这是一个英国为基础的在线自由职业者市场,提供软件开发、设计等服务。 Fiverr: Fiverr上有各种技能的自由职业者,包括软件开发、网站设计等,客户可以根据需求选择合适的服务。 这些平台提供了连接客户和自由职业者的渠道,并提供支付、沟通和项目管理工具,以确保项目顺利完成。
  11. 通过/proc文件系统:Linux的/proc文件系统包含了系统运行时的各种信息,包括当前运行的进程信息。你可以遍历/proc目录下的每个子目录(以数字命名的目录,每个目录名对应一个进程ID),并读取其中的status文件来获取进程名称等信息。 使用popen和grep:通过执行ps -A命令并结合grep来搜索特定的进程名。如果命令的输出非空,则表示进程存在。这种方法适用于简单的场景,但可能不是最高效或最可靠的方式。 使用系统调用kill:通过发送信号0(不会结束进程)给指定的进程ID(如果你已知),如果调用成功,则表明进程存在。注意,这需要适当的权限。 检测进程使用的端口 读取/proc/net/tcp和/proc/net/udp文件:这些文件包含了当前系统TCP和UDP端口的使用情况。通过解析这些文件,可以找出特定进程正在监听或使用的端口。 使用lsof命令:lsof是一个列出打开文件的工具,对于网络连接,打开的“文件”是网络套接字。你可以通过popen执行lsof -i命令并解析输出来查找特定进程的端口使用情况。 示例代码 以下是一个使用C语言通过读取/proc文件系统来检测特定进程是否存在的简单示例。注意,这只是一个基本的例子,可能需要根据具体需求进行调整: #include <stdio.h> #include <dirent.h> #include <string.h> int process_exists(const char* process_name) { DIR *dir; struct dirent *ent; char buf[512]; // 打开/proc目录 if ((dir = opendir("/proc")) != NULL) { // 遍历/proc下的所有项 while ((ent = readdir(dir)) != NULL) { long pid; char cmdline[256]; FILE *fp; // 尝试将目录名转换为pid if ((pid = strtol(ent->d_name, NULL, 10)) > 0) { // 构建cmdline文件的路径 snprintf(cmdline, sizeof(cmdline), "/proc/%ld/cmdline", pid); // 尝试打开文件 if ((fp = fopen(cmdline, "r")) != NULL) { // 读取命令行内容 if (fgets(buf, sizeof(buf), fp) != NULL) { // 检查进程名称是否匹配 if (strstr(buf, process_name) != NULL) { fclose(fp); closedir(dir); return 1; // 找到进程 } } fclose(fp); } } } closedir(dir); } return 0; // 未找到进程 } int main() { const char* process_name = "your_process_name_here"; if (process_exists(process_name)) { printf("Process '%s' exists.\n", process_name); } else { printf("Process '%s' does not exist.\n", process_name); } return 0; }
  12. systemctl list-units --type=service --state=running | grep messenger 这条命令的作用是: systemctl list-units --type=service --state=running:列出所有类型为服务且当前状态为运行中的单元。 | grep messenger:通过管道将前一个命令的输出传递给grep命令,grep将过滤出包含“messenger”的行。 如果有任何正在运行的服务的名称中包含“messenger”,这条命令会列出它们。如果没有输出,那么可能没有符合条件的正在运行的服务。 请注意,这个命令区分大小写。如果你想要进行不区分大小写的搜索,可以使用grep的-i选项: systemctl list-units --type=service --state=running | grep -i messenger
  13. // src/Service/PaymentLogService.php namespace App\Service; class PaymentLogService { private $logDirectory; public function __construct(string $logDirectory) { $this->logDirectory = $logDirectory; } public function appendToPaymentLog($pno, $content): void { $filePath = $this->logDirectory . '/' . $pno; // 确保目录存在 if (!file_exists(dirname($filePath))) { mkdir(dirname($filePath), 0777, true); } // 追加内容到文件,如果文件不存在则创建 file_put_contents($filePath, $content, FILE_APPEND); } } # config/services.yaml services: App\Service\PaymentLogService: arguments: $logDirectory: '%kernel.project_dir%/log' // src/Controller/SomeController.php namespace App\Controller; use Symfony\Component\HttpFoundation\Response; use App\Service\PaymentLogService; class SomeController { private $paymentLogService; public function __construct(PaymentLogService $paymentLogService) { $this->paymentLogService = $paymentLogService; } public function appendLogAction($pno): Response { $content = date('Y-m-d H:i:s') . "\n"; $this->paymentLogService->appendToPaymentLog($pno, $content); return new Response('Log updated.'); } }
  14. #include <windows.h> #include <stdio.h> // 打开串口 HANDLE open_serial_port(LPCSTR port_name, DWORD baud_rate) { HANDLE hSerial; DCB dcbSerialParams = {0}; COMMTIMEOUTS timeouts = {0}; // 打开串口 hSerial = CreateFile(port_name, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hSerial == INVALID_HANDLE_VALUE) { fprintf(stderr, "Error opening serial port\n"); return INVALID_HANDLE_VALUE; } // 获取当前串口配置 dcbSerialParams.DCBlength = sizeof(dcbSerialParams); if (!GetCommState(hSerial, &dcbSerialParams)) { fprintf(stderr, "Error getting serial port state\n"); CloseHandle(hSerial); return INVALID_HANDLE_VALUE; } // 配置串口 dcbSerialParams.BaudRate = baud_rate; dcbSerialParams.ByteSize = 8; // 数据位为8位 dcbSerialParams.StopBits = ONESTOPBIT; // 停止位为1 dcbSerialParams.Parity = NOPARITY; // 无奇偶校验位 if (!SetCommState(hSerial, &dcbSerialParams)) { fprintf(stderr, "Error setting serial port state\n"); CloseHandle(hSerial); return INVALID_HANDLE_VALUE; } // 设置超时 timeouts.ReadIntervalTimeout = 50; timeouts.ReadTotalTimeoutConstant = 50; timeouts.ReadTotalTimeoutMultiplier = 10; timeouts.WriteTotalTimeoutConstant = 50; timeouts.WriteTotalTimeoutMultiplier = 10; if (!SetCommTimeouts(hSerial, &timeouts)) { fprintf(stderr, "Error setting timeouts\n"); CloseHandle(hSerial); return INVALID_HANDLE_VALUE; } return hSerial; } // 写数据到串口 BOOL write_serial_port(HANDLE hSerial, LPCVOID data, DWORD size) { DWORD bytes_written; return WriteFile(hSerial, data, size, &bytes_written, NULL); } // 从串口读数据 BOOL read_serial_port(HANDLE hSerial, LPVOID buffer, DWORD size, DWORD *bytes_read) { return ReadFile(hSerial, buffer, size, bytes_read, NULL); } // 关闭串口 void close_serial_port(HANDLE hSerial) { CloseHandle(hSerial); } // 示例使用 int main() { HANDLE hSerial = open_serial_port("COM3", CBR_9600); // 以9600波特率打开COM3 if (hSerial == INVALID_HANDLE_VALUE) return 1; char data_to_send[] = "Hello, serial port!"; if (!write_serial_port(hSerial, data_to_send, sizeof(data_to_send))) { fprintf(stderr, "Error writing to serial port\n"); } char read_buf[128]; DWORD bytes_read; if (read_serial_port(hSerial, read_buf, sizeof(read_buf), &bytes_read)) { printf("Received: %.*s\n", (int)bytes_read, read_buf); } else { fprintf(stderr, "Error reading from serial port\n"); } close_serial_port(hSerial); return 0; } 这段代码中,open_serial_port函数用于打开指定的串口并进行配置,write_serial_port和read_serial_port函数分别用于向串口写数据和从串口读数据,最后通过close_serial_port函数关闭串口。注意,这段代码只是一个基础的示例,实际使用中可能需要根据具体需求进行调整,例如处理错误情况、调整超时设置等。在编译运行这段代码时,需要确保你的开发环境支持Windows API调用,并且链接了kernel32.lib库(如果使用Microsoft Visual C++,通常这是默认配置)。
  15. #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <termios.h> #include <string.h> // 函数声明 int open_serial(const char *device); int setup_serial(int fd, int speed, int parity); int serial_read(int fd, char *buf, int size); int serial_write(int fd, const char *buf, int size); void close_serial(int fd); // 打开串口设备 int open_serial(const char *device) { int fd = open(device, O_RDWR | O_NOCTTY | O_SYNC); if (fd < 0) { perror("open_serial() failed"); return -1; } return fd; } // 配置串口参数 int setup_serial(int fd, int speed, int parity) { struct termios tty; memset(&tty, 0, sizeof tty); if (tcgetattr(fd, &tty) != 0) { perror("setup_serial() failed"); return -1; } cfsetospeed(&tty, speed); cfsetispeed(&tty, speed); tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars tty.c_iflag &= ~IGNBRK; // disable break processing tty.c_lflag = 0; // no signaling chars, no echo, // no canonical processing tty.c_oflag = 0; // no remapping, no delays tty.c_cc[VMIN] = 0; // read doesn't block tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl tty.c_cflag |= (CLOCAL | CREAD); // ignore modem controls, // enable reading tty.c_cflag &= ~(PARENB | PARODD); // shut off parity tty.c_cflag |= parity; tty.c_cflag &= ~CSTOPB; tty.c_cflag &= ~CRTSCTS; if (tcsetattr(fd, TCSANOW, &tty) != 0) { perror("setup_serial() failed"); return -1; } return 0; } // 读取串口数据 int serial_read(int fd, char *buf, int size) { int n = read(fd, buf, size); if (n < 0) { perror("serial_read() failed"); return -1; } return n; } // 向串口写入数据 int serial_write(int fd, const char *buf, int size) { int n = write(fd, buf, size); if (n < 0) { perror("serial_write() failed"); return -1; } return n; } // 关闭串口设备 void close_serial(int fd) { close(fd); } // 主函数示例 int main() { int fd = open_serial("/dev/ttyUSB0"); // 替换为实际的串口设备文件 if (fd < 0) return 1; if (setup_serial(fd, B9600, 0) < 0) { // 设置波特率为 9600 close_serial(fd); return 1; } const char *msg = "Hello, serial port!"; serial_write(fd, msg, strlen(msg)); // 发送数据 char buf[100]; int n = serial_read(fd, buf, sizeof(buf) - 1); // 读取数据 if (n >= 0) { buf[n] = '\0'; printf("Received: %s\n", buf); } close_serial(fd); return 0; }
×
×
  • Create New...

Important Information

注册必须使用2-8个中文汉字作为账号