Как создать прерывание или фоновую задачу в C - PullRequest
0 голосов
/ 20 февраля 2020

Я пытаюсь выяснить, как сделать фоновый процесс в C, я ничего не нашел в Интернете. Я думаю, что причина, по которой я не нашел много, состоит в том, что я, возможно, не задаю правильный вопрос.

Я работаю над школьным проектом с использованием сборки ARM и C с Raspberry Pi с использованием операционной системы Raspbian и компилятор G CC.

Для своего проекта я решил сделать простую систему сигнализации. Идея проста, у меня есть 3 ИК-датчика, которые обнаруживают движение и запускают зуммер при обнаружении движения.

Вместо использования аппаратного обеспечения для клавиатуры, я выбрал GUI, где вы можете поставить / снять систему с охраны, а также сменить пароль и включить / выключить определенные датчики. Например, если вы хотите отключить датчики движения 1 и 2, на GUI будут кнопки для этого.

Проблема, с которой я столкнулся, заключается в том, что используемая библиотека GUI , (GTK3 и Glade) управляется событиями, поэтому если кнопка не нажата, она ничего не сделает. Это было бы хорошо, если бы я хотел включить зуммер только при обнаружении движения, потому что я мог бы сделать свой собственный l oop, чтобы следить за движением, но я действительно хочу повторно воспроизвести какой-то тип паттерна (пример: 3 коротких звука) непрерывно, пока не будет снята сигнализация). В то же время я все еще хочу иметь доступ к кнопкам GUI, чтобы можно было отключить будильник. Это заставляет меня думать, что мне нужно прерывание или фоновый процесс.

Я уверен, что есть много способов решить эту проблему, но я действительно хотел создать своего рода фоновую подпрограмму, которая могла бы выполняться параллельно основной Задача, когда пользователь вооружает систему. Я спросил своего профессора о том, как многопоточность в ARM, но он сказал, что мы не расскажем об этом в классе. Я читал, что стандартная библиотека C не поддерживает многопоточность, но я уверен, что есть способ сделать это. Если бы кто-то мог просто указать мне правильное направление, я был бы благодарен.

Вот код GUI, который я написал, наряду с другим модулем, который я закончил, чтобы получить рабочий прототип, прежде чем я начну подключать датчики , Ничто из этого не содержит ассемблерного кода, потому что я еще не дошел до этого, я хотел, чтобы он работал на более высоком уровне, а затем разбивал некоторые детали до сборки. Если вам нужны все файлы, я с удовольствием предоставлю их, но я думаю, что этого будет достаточно, чтобы вы все поняли, что я пытаюсь сделать.

Код GUI:

/*****************************************************
 * Title:       User Interface
 * Author:      
 * Date:        2/15/20
 * Class:       CISP 2410
 *
 * Description:
 *  ! This header file contains all of the function
 *  ! Declarations and definitions for the GUI
 *  ! Everything involving the GUI will be in
 *    --> this header
 *
 *****************************************************/



#include <gtk/gtk.h>        // For gtk stuff
#include <stdlib.h>         // Standard Library
#include "GUI_Ctrl.h"       // Prototypes
#include "Alarm.h"          // Alarm Functions



/* Private Functions */

static void UpdateLcdDisplay(char keyPadValue);
static void ClearLcdDisplay(void);
static void UpdateDisplay(void);
/***********************************/



// Global Variables
GtkWidget *g_Lbl_Lcd;
GtkWidget *g_Lbl_SysStat;
GtkWidget *g_Lbl_LogStat;


char inputBuffer[6] = {0x0};
int charCounter = 0;
const int INPUT_LIMIT = 6;




/*****************************************************
 * ! Initializes all of the GUI elements
 * ! Adds CSS attributes to GUI elements
 * ! Also handles the formatting of text 
 *****************************************************/
void GUI_INIT(int argc, char* argv[])
{
    GtkBuilder  *builder; 
    GtkWidget   *window;
    GtkWidget *g_Lbl_Lbl1;
    GtkWidget *g_Lbl_Lbl2;

    // Get pointer to css file
    GtkCssProvider *cssProvider = gtk_css_provider_new ();
    gtk_css_provider_load_from_path(cssProvider,"UI/style.css",NULL);

    gtk_init(&argc, &argv);

    // get pointer to xml dat file
    builder = gtk_builder_new_from_file("UI/HelloWorld.glade");

    // Get pointer to main window
    window = GTK_WIDGET(gtk_builder_get_object(builder, "window_main"));
    gtk_builder_connect_signals(builder, NULL);

    // Get pointer to labels
    g_Lbl_Lcd = GTK_WIDGET(gtk_builder_get_object(builder, "Lbl_Lcd"));
    g_Lbl_SysStat = GTK_WIDGET(gtk_builder_get_object(builder, "Lbl_SysStat"));
    g_Lbl_LogStat = GTK_WIDGET(gtk_builder_get_object(builder, "Lbl_LogStat"));
    g_Lbl_Lbl1 = GTK_WIDGET(gtk_builder_get_object(builder, "Lbl1"));
    g_Lbl_Lbl2 = GTK_WIDGET(gtk_builder_get_object(builder, "Lbl2"));

    // Align Text Right
    gtk_label_set_xalign (GTK_LABEL(g_Lbl_Lcd), 1);
    // Align Text Left
    gtk_label_set_xalign (GTK_LABEL(g_Lbl_SysStat), 0);
    gtk_label_set_xalign (GTK_LABEL(g_Lbl_LogStat), 0);
    gtk_label_set_xalign (GTK_LABEL(g_Lbl_Lbl1), 0);
    gtk_label_set_xalign (GTK_LABEL(g_Lbl_Lbl2), 0);

    // Add CSS
    gtk_style_context_add_provider_for_screen(gdk_screen_get_default(), GTK_STYLE_PROVIDER(cssProvider), GTK_STYLE_PROVIDER_PRIORITY_USER);


    // Finish setup and start GUI
    g_object_unref(builder);
    gtk_widget_show(window);    
    UpdateDisplay();           
    gtk_main();
    return;
}



// called when window is closed
void on_window_main_destroy()
{
    gtk_main_quit();
}


/*------------------END SECTION------------------*/




static void UpdateDisplay(void)
{
    ClearLcdDisplay();
    gtk_label_set_text(GTK_LABEL(g_Lbl_SysStat), GetSysStat());
    gtk_label_set_text(GTK_LABEL(g_Lbl_LogStat), GetLogStat());
    return;
}

static void UpdateLcdDisplay(char keyPadValue)
{
    if (charCounter >= INPUT_LIMIT)
        ClearLcdDisplay();
    else
    {
        inputBuffer[charCounter] = keyPadValue;
        charCounter++;
    }
    gtk_label_set_text(GTK_LABEL(g_Lbl_Lcd), inputBuffer);
    return;
}

static void ClearLcdDisplay(void)
{
    memset(inputBuffer, 0, 6);
    charCounter = 0;
    gtk_label_set_text(GTK_LABEL(g_Lbl_Lcd), inputBuffer);
    return;
}




/*------------------ EVENT HANDLERS ------------------*/

void on_btn0_clicked(void)      {UpdateLcdDisplay('0');}
void on_btn1_clicked(void)      {UpdateLcdDisplay('1');}
void on_btn2_clicked(void)      {UpdateLcdDisplay('2');}
void on_btn3_clicked(void)      {UpdateLcdDisplay('3');}
void on_btn4_clicked(void)      {UpdateLcdDisplay('4');}
void on_btn5_clicked(void)      {UpdateLcdDisplay('5');}
void on_btn6_clicked(void)      {UpdateLcdDisplay('6');}
void on_btn7_clicked(void)      {UpdateLcdDisplay('7');}
void on_btn8_clicked(void)      {UpdateLcdDisplay('8');}
void on_btn9_clicked(void)      {UpdateLcdDisplay('9');}
void on_btnClear_clicked(void)  {ClearLcdDisplay();}
void on_btnEnter_clicked(void)   {UpdateDisplay();}

void on_btnLogin_clicked(void)
{
    LoginLogout(inputBuffer);
    UpdateDisplay(); 
    return;
}

void on_btnArm_clicked(void)
{
    ArmDisarm();
    UpdateDisplay(); 
    return;
}

Вот код для будильника. Обратите внимание, это всего лишь прототип, я буду использовать библиотеку wiringPi, как только разберусь с этим прерыванием.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Alarm.h"


// Private Function Prototypes
static int PasswordIsCorrect(char* pswAttempt);

// Global Variables
static int armed = 0;
static int loggedIn = 0;





static int PasswordIsCorrect(char* pswAttempt)
{
    const char PASSWORD[] = "123";

    if (!strcmp(pswAttempt, PASSWORD))
        return 1;
    else
        return 0;
}



/*
 * Returns a string,
 * Used to update label
 */
char* GetSysStat(void)
{
    if(armed)
        return "Armed";
    else
        return "Disarmed";
}


/*
 * Returns a string,
 * Used to update label
 */
char* GetLogStat(void)
{
    if(loggedIn)
        return "Logged In";
    else
        return "Logged Out";
}



void ArmDisarm(void)
{
    if (loggedIn && armed)
        armed = 0;
    else if(loggedIn && !armed)
        armed = 1;
    return;
}



void LoginLogout(char* pswAttempt)
{
    if(PasswordIsCorrect(pswAttempt))
        loggedIn = 1;
    else
        loggedIn = 0;
    return;
}

Спасибо всем за потраченное время!

...