为了确保无论是按 Ctrl+C
终止程序,还是程序自动退出时都能关闭所有的灯,你可以使用 signal
处理来捕捉 SIGINT
信号(即 Ctrl+C
),同时结合 atexit
来在正常退出时关闭灯。
以下是修改后的代码,加入了对 SIGINT
信号的处理:
#include <iostream>
#include <fstream>
#include <string>
#include <thread>
#include <chrono>
#include <cstdlib> // for system function
#include <csignal> // for signal handling
// GPIO操作函数
void setGPIO(const std::string& gpio, const std::string& value) {
std::ofstream valueFile("/sys/class/gpio/gpio" + gpio + "/value");
if (valueFile.is_open()) {
valueFile << value;
valueFile.close();
std::cout << "GPIO " << gpio << " set to " << value << std::endl;
} else {
std::cerr << "Unable to set value for GPIO " << gpio << std::endl;
}
}
// 初始化GPIO
void initGPIOs() {
// 先取消导出已导出的 GPIO
system("echo \"290\" | sudo tee /sys/class/gpio/unexport");
system("echo \"289\" | sudo tee /sys/class/gpio/unexport");
system("echo \"291\" | sudo tee /sys/class/gpio/unexport");
system("echo \"288\" | sudo tee /sys/class/gpio/unexport");
// 导出 GPIO 并设置方向
system("echo \"290\" | sudo tee /sys/class/gpio/export && \
echo \"289\" | sudo tee /sys/class/gpio/export && \
echo \"291\" | sudo tee /sys/class/gpio/export && \
echo \"288\" | sudo tee /sys/class/gpio/export && \
echo \"out\" | sudo tee /sys/class/gpio/gpio290/direction && \
echo \"out\" | sudo tee /sys/class/gpio/gpio289/direction && \
echo \"out\" | sudo tee /sys/class/gpio/gpio291/direction && \
echo \"out\" | sudo tee /sys/class/gpio/gpio288/direction");
std::cout << "GPIOs initialized" << std::endl;
}
// 关闭所有灯
void turnOffAllGPIOs() {
setGPIO("290", "0");
setGPIO("289", "0");
setGPIO("291", "0");
setGPIO("288", "0");
std::cout << "All GPIOs turned off" << std::endl;
}
// 信号处理函数,用于捕捉 Ctrl+C (SIGINT)
void signalHandler(int signum) {
std::cout << "Interrupt signal (" << signum << ") received.\n";
turnOffAllGPIOs();
exit(signum);
}
int main() {
// 注册程序退出时的清理函数
atexit(turnOffAllGPIOs);
// 注册信号处理函数来捕捉 SIGINT (Ctrl+C)
signal(SIGINT, signalHandler);
// 初始化GPIO
initGPIOs();
// 定义要操作的GPIO编号
std::string gpio290 = "290";
std::string gpio289 = "289";
std::string gpio291 = "291";
std::string gpio288 = "288";
try {
while (true) {
// 290和289轮流亮三秒
setGPIO(gpio290, "1");
setGPIO(gpio289, "0");
std::this_thread::sleep_for(std::chrono::seconds(3));
setGPIO(gpio290, "0");
setGPIO(gpio289, "1");
std::this_thread::sleep_for(std::chrono::seconds(3));
// 291和288轮流亮三秒
setGPIO(gpio291, "1");
setGPIO(gpio288, "0");
std::this_thread::sleep_for(std::chrono::seconds(3));
setGPIO(gpio291, "0");
setGPIO(gpio288, "1");
std::this_thread::sleep_for(std::chrono::seconds(3));
}
} catch (...) {
std::cerr << "An exception occurred, exiting..." << std::endl;
turnOffAllGPIOs();
throw; // rethrow the exception
}
return 0;
}
代码说明:
-
signalHandler
函数:- 这个函数会捕捉
SIGINT
信号(通常是Ctrl+C
触发),然后调用turnOffAllGPIOs
来关闭所有的 GPIO 灯,最后退出程序。
- 这个函数会捕捉
-
signal(SIGINT, signalHandler)
:- 这一行代码注册了
SIGINT
信号的处理函数。这样当用户按下Ctrl+C
时,程序会调用signalHandler
,确保在退出前关闭灯。
- 这一行代码注册了
-
atexit(turnOffAllGPIOs)
:- 在程序正常退出时,这个函数会自动被调用,以关闭所有灯。
-
正常和异常情况下的退出:
- 无论是通过
Ctrl+C
终止,还是程序由于异常退出,或者正常退出,所有 GPIO 灯都会被关闭。
- 无论是通过
通过这样的处理方式,可以确保在任何情况下,程序都能安全地关闭所有的 GPIO 灯,避免不必要的电力消耗或硬件损坏。