如何使用 pigpio SetAlertFunc 正确更改变量?
How to change a variable properly with pigpio SetAlertFunc?
我想监控一个连接有按钮的特定 GPIO 引脚,根据按钮被按下的次数,它会打开一些 LED 灯,使它们闪烁或关闭。
#include <stdio.h>
#include <pigpio.h>
#include <stdlib.h>
#include <unistd.h>
#define LED_1 13
#define LED_2 19
#define BUTTON 25
#define ON 1
#define OFF 0
#define DELAY 1
void initalise_pins();
void clear_all();
void start_button();
void turn_on_lights();
void increment_state(int gpio, int level, uint32_t tick);
int current_state = 0; /*Don't have a better way of breaking out of loop during pulse so using global var*/
int main(){
if (gpioInitialise() < 0){
printf("Error initializing pigpio library, exiting");
}
else{
initalise_pins();
clear_all();
start_button();
}
}
int main(){
initalise_pins();
clear_all();
start_button();
}
void initalise_pins(){
gpioSetMode(LED_1, PI_OUTPUT); /*Set LED at pin 13 to output*/
gpioSetMode(LED_2, PI_OUTPUT); /*Set LED at pin 19 to output*/
gpioSetMode(BUTTON, PI_INPUT); /*Set Button at pin 25 to input*/
gpioSetPullUpDown(BUTTON, PI_PUD_DOWN); /*Set Button at pin 25 to pulldown*/
gpioSetAlertFunc(BUTTON, increment_state); /*Function to watch for GPIO state change*/
}
void clear_all(){
gpioWrite(LED_1, OFF); /*Resets LED_1 to off*/
gpioWrite(LED_2, OFF); /*Resets LED_2 to off*/
}
void turn_on_lights(){
gpioWrite(LED_1, ON);
gpioWrite(LED_2, ON);
}
void increment_state(int gpio, int level, uint32_t tick){
if (level == 1){
current_state += 1;
}
}
void start_button(){
for (;;){ /*Loop to keep reading button value*/
if (current_state == 0){ /*Current state off*/
continue;
}
else if (current_state == 1){ /*Current state on*/
turn_on_lights();
}
else if (current_state == 2){ /*Current state blinking*/
clear_all();
sleep(DELAY);
turn_on_lights();
sleep(DELAY);
}
else{ /*Reset state to off*/
clear_all();
current_state = 0;
}
sleep(0.1);
}
}
代码按预期工作,但是否有正确的方法来设置 current_state
的值而不是将其作为全局变量?此解决方案的主要问题是,当我将其编译为要在 Python 中使用的库时,此函数将中断。
据我所知,存在三种存储数据的方法'beyond their scope'。
- 一个全局变量 - 如您所知,该变量在所有调用中共享,甚至可以在编译单元之外引用。
- 一个
static
变量 - 此类型仅限于其定义的范围,无法从外部访问,但再次在所有调用之间共享。
- 传递给您的函数的参数。
根据我对您问题的理解,您不想在调用的所有实例中共享变量的值,这会自动取消 1. 和 2.
因此,您需要将所需信息从外部传递到您的函数中。
虽然您可以将 current_state_id
传递到您的函数集 'as is',但这需要您的图书馆的用户了解一两件关于您的图书馆如何运作的事情。
更好的解决方案是上下文结构,它隐藏了您需要的数据的内部,让您可以灵活地从内部获取 add/remove 数据,而不必担心更改您的 API .
正常的做法是这样的:
struct _PIN_Ctrl; //Forward declaration of the (opaque) structure.
typedef struct _PIN_Ctrl *PIN_Ctrl;
PIN_Ctrl createPINCtrl(void);
//Any number of functions taking PINCtrl as context structure.
freePINCtrl(PIN_Ctrl ctrl);
调用的工作方式类似(现在使用 C99 表示法):
if (PIN_Ctrl ctrl = createPINCtrl())
{
//doStuffWithYourContext
freePINCtrl(ctrl);
}
createPINCtrl
需要 malloc
您的结构并将其成员初始化为定义的状态(即 'currentState' 为 0)。
在内部,您自然会访问结构的成员,最后 'freePINCtrl' 仅执行 free(ctrl)
来清理分配的内存。
我想监控一个连接有按钮的特定 GPIO 引脚,根据按钮被按下的次数,它会打开一些 LED 灯,使它们闪烁或关闭。
#include <stdio.h>
#include <pigpio.h>
#include <stdlib.h>
#include <unistd.h>
#define LED_1 13
#define LED_2 19
#define BUTTON 25
#define ON 1
#define OFF 0
#define DELAY 1
void initalise_pins();
void clear_all();
void start_button();
void turn_on_lights();
void increment_state(int gpio, int level, uint32_t tick);
int current_state = 0; /*Don't have a better way of breaking out of loop during pulse so using global var*/
int main(){
if (gpioInitialise() < 0){
printf("Error initializing pigpio library, exiting");
}
else{
initalise_pins();
clear_all();
start_button();
}
}
int main(){
initalise_pins();
clear_all();
start_button();
}
void initalise_pins(){
gpioSetMode(LED_1, PI_OUTPUT); /*Set LED at pin 13 to output*/
gpioSetMode(LED_2, PI_OUTPUT); /*Set LED at pin 19 to output*/
gpioSetMode(BUTTON, PI_INPUT); /*Set Button at pin 25 to input*/
gpioSetPullUpDown(BUTTON, PI_PUD_DOWN); /*Set Button at pin 25 to pulldown*/
gpioSetAlertFunc(BUTTON, increment_state); /*Function to watch for GPIO state change*/
}
void clear_all(){
gpioWrite(LED_1, OFF); /*Resets LED_1 to off*/
gpioWrite(LED_2, OFF); /*Resets LED_2 to off*/
}
void turn_on_lights(){
gpioWrite(LED_1, ON);
gpioWrite(LED_2, ON);
}
void increment_state(int gpio, int level, uint32_t tick){
if (level == 1){
current_state += 1;
}
}
void start_button(){
for (;;){ /*Loop to keep reading button value*/
if (current_state == 0){ /*Current state off*/
continue;
}
else if (current_state == 1){ /*Current state on*/
turn_on_lights();
}
else if (current_state == 2){ /*Current state blinking*/
clear_all();
sleep(DELAY);
turn_on_lights();
sleep(DELAY);
}
else{ /*Reset state to off*/
clear_all();
current_state = 0;
}
sleep(0.1);
}
}
代码按预期工作,但是否有正确的方法来设置 current_state
的值而不是将其作为全局变量?此解决方案的主要问题是,当我将其编译为要在 Python 中使用的库时,此函数将中断。
据我所知,存在三种存储数据的方法'beyond their scope'。
- 一个全局变量 - 如您所知,该变量在所有调用中共享,甚至可以在编译单元之外引用。
- 一个
static
变量 - 此类型仅限于其定义的范围,无法从外部访问,但再次在所有调用之间共享。 - 传递给您的函数的参数。
根据我对您问题的理解,您不想在调用的所有实例中共享变量的值,这会自动取消 1. 和 2.
因此,您需要将所需信息从外部传递到您的函数中。
虽然您可以将 current_state_id
传递到您的函数集 'as is',但这需要您的图书馆的用户了解一两件关于您的图书馆如何运作的事情。
更好的解决方案是上下文结构,它隐藏了您需要的数据的内部,让您可以灵活地从内部获取 add/remove 数据,而不必担心更改您的 API .
正常的做法是这样的:
struct _PIN_Ctrl; //Forward declaration of the (opaque) structure.
typedef struct _PIN_Ctrl *PIN_Ctrl;
PIN_Ctrl createPINCtrl(void);
//Any number of functions taking PINCtrl as context structure.
freePINCtrl(PIN_Ctrl ctrl);
调用的工作方式类似(现在使用 C99 表示法):
if (PIN_Ctrl ctrl = createPINCtrl())
{
//doStuffWithYourContext
freePINCtrl(ctrl);
}
createPINCtrl
需要 malloc
您的结构并将其成员初始化为定义的状态(即 'currentState' 为 0)。
在内部,您自然会访问结构的成员,最后 'freePINCtrl' 仅执行 free(ctrl)
来清理分配的内存。