RPi 4 GPIO上升和下降触发上的中断在C语言中不起作用

问题描述

从这里开始学习编码Linux内核模块的代码。

我想用C语言为RPi 4编写一个内核模块。

我想在按下按钮时使用中断来点亮LED。只要按下按钮,LED就会亮起,而当我松开它时,LED应该会熄灭。

我使用了request_irq()函数,以便通过指示“ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING”在按钮的上升沿和下降沿调用处理中断的函数。我以前使用过函数gpio_to_irq(BUTTON_PIN)。

request_irq(button_irq,button_ih,IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,"button_irq",NULL);

当我按下按钮时调用此函数,但在释放按钮时不调用。它的编码如下所示:

static irqreturn_t button_ih(int irq,void *data)
{
    int state;
    
    state = gpio_get_value(BUTTON_PIN);

    printk(KERN_INFO "Actual state of the button : %d",state);
    
    //Debounce condition
    if(jiffies - last_interrupt_time > msecs_to_jiffies(200))
    {
        if(state)
        {
            gpio_set_value(LED_PIN,1);
        }else
        {
            gpio_set_value(LED_PIN,0);
        }
    }
    last_interrupt_time = jiffies;

    return IRQ_HANDLED;
}

我检查按钮的值是1(按下)还是0(释放),并希望相应地打开/关闭LED。

当我尝试使用不同的GPIO时,有时我的按钮的值为1,即使我还没有按下它(通过从init函数打印一条消息),有时它的值为0。所以我不知道我是否在做错事。我不认为GPIO已经被使用,因为我可以使用gpio_request_one()函数来请求它们。

因此,当按钮已经具有值1时,LED会亮起,但在我释放按钮时不会熄灭。

当该值已经为0时,进入中断处理程序功能时按钮值不会变为1(并且LED显然不会点亮)。

能告诉我这是怎么回事吗?

解决方法

形成简单的C程序,而不是内核模块 这个最低限度,以了解我的状况。 main.h

typedef struct s_Data {
    int exitFlag;
    struct {int value; int bcmPin;} In01; //<--- Stock actual GPIO Value
    struct {int value; int bcmPin;} In02;
    ....
    struct {int value; int bcmPin;} Out01;
    struct {int value; int bcmPin;} Out02;
    ....
} t_Data;

#define NO_Click 0
#define SimpleClick 1
#define LongClick 2
#define MultiClick 3

typedef struct s_Button {
    pthread_t button_thread;
    int *exitFlag;
    int * input; //Button
    int * output;
    int old_state;
    int new_state;
    struct timeval t0;
    struct timeval t1;
    struct timeval pressedTime;
    struct timeval releasedTime;
    int clickType;
    //float debounce = 0.020; // ms debounce period to prevent flickering when pressing or releasing the button
    // debounce not necessary while thread have time to take a coffee
    float DCgap;            // max ms between clicks for a double click event
    float holdTime;        // ms hold period: how long to wait for press+hold event
} t_Button;

main.c

#include "main.h"
#include <wiringPi.h>
#include <pthread.h>

// initial state
static t_Data data = {
  .exitFlag = 0,.In01.value = 0,.In01.bcmPin = 4,.In02.value = 0,.In02.bcmPin = 17,.Out01.value = 0,.Out01.bcmPin = 4,.Out02.value = 0,.Out02.bcmPin = 17,}

static _Data data_prev;

static void *inputRead_threadFn(void *p_Data) {
   pinMode(Data.In01.bcmPin,INPUT);
   pullUpDnControl(Data.In01.bcmPin,PUD_UP);
   pinMode(Data.In02.bcmPin,INPUT);
   pullUpDnControl(Data.In02.bcmPin,PUD_UP);

   while (!Data.exitFlag) {
      Data.In01.value = !digitalRead(Data.In01.bcmPin);
      Data.In02.value = !digitalRead(Data.In02.bcmPin);
      if (Data.In01.value != Data_old.In01.value) {
        Data_old.In01.value = Data.In01.value;
      }
      if (Data.In02.value != Data_old.In02.value) {
        Data_old.In02.value = Data.In02.value;
      }
      usleep(50)
   }
}

static void *outputWrite_threadFn(void *p_Data) {
   pinMode(Data.In01.bcmPin,OUTPUT);
   pinMode(Data.In02.bcmPin,OUTPUT);

   while (!Data.exitFlag) {
      digitalWrite(Data.Out01.bcmPin,!Data.Out01.value);
      digitalWrite(Data.Out02.bcmPin,!Data.Out02.value);
   }
   usleep(50)
}

static void *button_threadFn(void *p_Data) {
  t_Button *button = (t_Button *)p_data;

  LOG("Button[%s] thread initialized\r\n",button->name);

  button->old_state = 0;
  button->new_state = 0;
  button->clickType = NO_Click;


  int clickCount = 0;
    
  while(*(button->exitFlag) == 0) {
    
    button->new_state = *(button->input) || *(button->web_input); //*((int *)

    if( button->old_state == 0 && button->new_state == 1 ) {
       //printf("front montant\r\n"); fflush(stdout);
        // *****************************   
        // traitement sur front montant
        // rising edge
        // ***************************** 

        button->old_state = 1;
        
        gettimeofday(&button->pressedTime,0);
        
        //Button pressed
  

    } else if( (button->old_state == 1) && (button->new_state == 0) ) {
        //printf("front descendant\r\n"); fflush(stdout);
        // ***************************** 
        // traitement sur front descendant
        // falling edge
        // ***************************** 
        button->old_state = 0;
        gettimeofday(&button->releasedTime,0);
        
        if (my_timedifference_msec(button->releasedTime,button->pressedTime ) < button->DCgap) {
            clickCount++;
            button->clickType = MultiClick;
        }
        
        
        //Button released
        
        
    } else if( (button->old_state == 0) && (button->new_state == 0) ) {
       // printf("front bas\r\n"); fflush(stdout);
        // ***************************** 
        // pas de changement d'état : front bas
        // no state change : edge down
        // ***************************** 
        gettimeofday(&button->t0,0);
        

        *(button->output) = 0; //<--- here in your case

        //Attendre DC_Gap pour connaitre le nombre de click
        // Wait for DC_Gap to know click count
        if (my_timedifference_msec(button->t0,button->releasedTime) > button->DCgap) {
            if (clickCount == 1) {
                LOG("SimpleClick");
                //Simple Click

            } else if ( clickCount > 1 ) {
                //Multiclicks
            }
            button->clickType = NO_Click;
            clickCount = 0;
        }
        
    } else if( (button->old_state == 1) && (button->new_state == 1) ) {
       // printf("front haut\r\n"); fflush(stdout);
        // ***************************** 
        // pas de changement d'état : front haut
        // no state change : edge up
        // ***************************** 
        gettimeofday(&button->t1,0);
        
        *(button->output) = 1; //<--- here in your case
       
        //long click
        if (my_timedifference_msec(button->t1,button->pressedTime) >= button->holdTime) {
            LOG("LongClick");
            button->clickType = LongClick;

            //do what you want while not released

            usleep(30*1000);
        }
    }
    usleep(100);   
  }
  printf("Light Loop::exiting...\r\n"); fflush(stdout);
}

int main(int argc,char** argv) {
   wiringPiSetup();
   wiringPiSetupGpio();

   data_prev = data;

   //start input thread
   //start output thread

   int DCGap = 250; //ms
   int HoldTime = 600;
   t_Button Buttons[] = {
    { //WC
        .exitFlag = &Data.exitFlag,.DCgap = DCGap,.holdTime = HoldTime,.input = &Data.In01.value,.output = &Data.Out01.value,},{ //chambre
        .exitFlag = &Data.exitFlag,.input = &Data.In02.value,.output= &Data.Out02.value,}
   }
   //start buttons threads
   for (i = 0; i < (sizeof(Buttons) / sizeof(t_Button)) ; i++) {
     ret = pthread_create (&Buttons[i].button_threadFn,NULL,fn_Button,&Buttons[i]); 
     if (ret) {
         fprintf (stderr,"%s",strerror (ret));
     }
   }


   //threads join

   return (EXIT_SUCCESS);
}
,

好的,谢谢所有的评论/答案。

确实是因为我没有正确使用任何上拉或下拉电阻器。

因此,我将电路更改如下: Circuit

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...