2017-02-21 38 views
0

Я только что начал свой первый проект на языке C на малине pi 3, и я хочу создать свое первое графическое приложение для сенсорной панели. Моя цель - запустить цикл while (1), который контролирует ввод-вывод малины и функцию gtk_main, чтобы открыть простое окно.gtk_main() рядом с (1) Raspberry Pi 3

После вызова gtk_main() остальная часть кода не работает. Я знаю, что это вызвано тем, что gtk_main создает собственный цикл. Есть ли способ запустить эти две петли одновременно?

#include <stdio.h> // Used for printf() statements 
#include <wiringPi.h> // Include WiringPi library! 
#include <gtk/gtk.h> 

// Pin number declarations. We're using the Broadcom chip pin numbers. 
const int pwmPin = 18; // PWM LED - Broadcom pin 18, P1 pin 12 
const int ledPin = 23; // Regular LED - Broadcom pin 23, P1 pin 16 
const int butPin = 21; // Active-low button - Broadcom pin 17, P1 pin 11  

const int pwmValue = 0; // Use this to set an LED brightness 

int main(int argc, char *argv[]){ 

    int add = 0; 
    int sign = 1; 
    // Setup stuff: 
    wiringPiSetupGpio(); // Initialize wiringPi -- using Broadcom pin numbers 

    pinMode(pwmPin, PWM_OUTPUT); // Set PWM LED as PWM output 
    pinMode(ledPin, OUTPUT);  // Set regular LED as output 
    pinMode(butPin, INPUT);  // Set button as INPUT 
    pullUpDnControl(butPin, PUD_UP); // Enable pull-up resistor on button 

    GtkWidget *window; 

    gtk_init (&argc, &argv); 

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 
    gtk_widget_show (window); 

    gtk_main(); 

    // Loop (while(1)): 
    while(1) 
    { 
     if (digitalRead(butPin)) // Button is released if this returns 1 
     { 
      pwmWrite(pwmPin, pwmValue+add); // PWM LED at bright setting 
      digitalWrite(ledPin, LOW);  // Regular LED off 
      add=add+(sign*50); 
      if (add==1000) sign=-1; 
      if (add==0) sign=1; 
      delay(50); 
     } 
     else // If digitalRead returns 0, button is pressed 
     { 
      pwmWrite(pwmPin, 1024 - pwmValue); // PWM LED at dim setting 
      // Do some blinking on the ledPin: 
      digitalWrite(ledPin, HIGH); // Turn LED ON 
      delay(75); // Wait 75ms 
      digitalWrite(ledPin, LOW); // Turn LED OFF 
      delay(75); // Wait 75ms again 
     } 
    }  

} 
+0

Не эксперт GTK, но вы должны рассмотреть возможность использования многозадачности для этого. – LPs

ответ

0

У меня есть два решения в виде, чтобы решить вашу проблему:

  • Вы можете create a timer, который будет вызывать функцию, чтобы иметь дело с butPin значения каждого 100ms,
  • Вы можете использовать темы:

    void *start_gtk_thread(void *arg) 
    { 
        gtk_main(); 
        return NULL; 
    } 
    void *start_pin_thread(void *arg) 
    { 
        while(1) 
        { 
         if (digitalRead(butPin)) // Button is released if this returns 1 
         { 
          .... 
         } 
         return NULL; 
        } 
    } 
    

    И в вашей основной функции

    gtk_widget_show (window); 
    
    /* threads id*/ 
    pthread_t tid[2]; 
    
    /* create threads */   
    pthread_create(&tid[0], NULL, start_gtk_thread, NULL); 
    pthread_create(&tid[1], NULL, start_pin_thread, NULL); 
    
    /* wait for threads (warning, they should never terminate) */ 
    pthread_join(id[0], NULL); 
    pthread_join(id[1], NULL); 
    
+2

Я не рекомендую использовать потоки в приложении Gtk, закодированном новичком; использование потоков с GTK - довольно продвинутая тема, особенно потому, что большинство функций GTK можно вызывать только из * основного * потока. –

0

gtk_main является documented как:

Запускает основной цикл до тех пор, пока gtk_main_quit() называется.

Вы можете вложить звонки на номер gtk_main(). В этом случае gtk_main_quit() сделает самый внутренний вызов возврата основного цикла.

Таким образом, вы должны иметь некоторые callbackявно вызова gtk_main_quit (и я думаю, вы не).

Таким образом, поведение ожидается. Вы можете обращаться с "delete-event" GTK signal на свой window (имея ваш обработчик сигналов GTK для этого события, вызывающего явноgtk_main_quit). Вам нужно прочитать гораздо больше, особенно о GTK event loop и GObject's signals.

Если вы хотите poll(2) и read(2) некоторые устройства, вы будете лучше делать внутри цикла событий GTK (например, с помощью вызова g_source_add_unix_fd или g_io_channel_unix_new, и т.д. и т.д. ...).

Вы должны провести несколько дней, чтобы узнать больше о Gtk, в частности о его главе Getting Started.

0

Удалите цикл while и используйте g_idle_add и/или g_timeout, чтобы вызвать ваши обратные вызовы. Это определяет , когда вы вызываете код. Затем, в своем обратном вызове, делайте свой элемент управления ввода-вывода. Просто помните, что использование delay или любая функция блокировки, аналогичная sleep, заморозит ваш пользовательский интерфейс за такое же количество времени. Вы можете избежать этого, используя g_idle_add или g_timeout, чтобы активировать изменение состояния.

 Смежные вопросы

  • Нет связанных вопросов^_^