voidループ外の関数はどのように機能しますか?


9

Arduinoのスケッチで、void setup()1回実行するvoid loop()部分とループし続ける部分を使用することに慣れています。メインの外部にvoid関数があるとどうなりますvoid loop()か?これらはすべて並行してループし続けますか、それとも次々に実行されますか?または、特定のvoid関数は、特定の基準が満たされた場合にのみ実行されますか(whileループなど)?

たとえば、以下のコードではvoid receiveData(int byteCount)void sendData()関数と関数はいつ実行されますか?

//I2C_test

//This code demonstrates communication via an I2C bus between a raspberry pi and an arduino.
//When the Raspberry pi (master) sends data to the Arduino (slave), the Arduino uses this
//data to control a motor. After the Arduino has recieved data from the master, it then collects
//data from the external environment via a sensor and sends this data back to the Raspberry pi.

#include <Wire.h>
int number = 0; //Declare variables
int val = 0;

void setup() {
  //Anything between the curly brackets runs once when the arduino is turned on or reset
  pinMode(0, INPUT);
  //Set pin 0 as input and 3 as output
  pinMode(3, OUTPUT);
  Serial.begin(9600);
  //Set the data rate for serial transmission at 9600bps
  Wire.begin(0x04);
  //Initiate the Wire library, join the Arduino as a slave, and specify its 7 bit slave address
  Wire.onReceive(receiveData);
  //Define callbacks for i2c communication
  Wire.onRequest(sendData);
}

void loop() {
  //The code between the curly brackets keeps repeating
  delay(100);
}

void receiveData(int byteCount) {
  while(Wire.available()) {
    number = Wire.read();
    //Set the variable "number" to the data sent by the master
    analogWrite(3, number);
    //Write this number to pin 3 (PWM). This controls the motor speed
  }
  val = analogRead(0);
  //Read the voltage on pin 0 (connected to the sensor). Map input voltages between 0 and 5 volts into integer values between 0 and 1023
}

void sendData() {
  Wire.write(val);
  //Send the data read from the sensor to the master.
}

これは面白いですね。コードのソースへのリンク(およびArduinoとPiの間の接続の詳細)を投稿できますか?
ミリウェイズ2014年

1
@Milliways この*チュートリアルを使用して、arduino unoおよびRaspberry pi(B +モデル)でコードを記述しましたが、いくつかの小さな変更を加えました.2つのボードのSDAピンとSCLピン、およびそれらの場合はグラウンドピンを接続します別の電源に接続されています。次に、電位分割器構成で構成されたセンサーに接続されたピン3を+ 5VピンとGndピンの間に接続しました。ピン0とGndはモータードライブボードに接続されています。
Blue7 2014年

回答:


11

setup()そしてloop()それらはArduinoのコードによって自動的に呼び出されるための機能が珍しいです。他の関数はこのように動作しません。

あなたが明示的に(内から例えばそれを自分で呼び出さない限り一般的に言って、関数が実行されることはありませんsetup()loop()、またはそれを呼び出すためのプログラムの他の部分指示します)。(関数を実行する方法は他にもありますが、これには通常、非常に高度ないじくりが含まれますが、回避するのが最善です。)

たとえば、pinMode()他の関数とまったく同じです。実際にpinMode(3, INPUT)コードに何かを入れたときにのみ実行されます。その時点で、1回実行されて終了し、呼び出し元の関数は中断したところから実行されます(並列に実行されることはありません)。

あなたが投稿したサンプルコードは非常に興味深いものです。これらの行を見てくださいsetup()

Wire.onReceive(receiveData);
Wire.onRequest(sendData);

これらの行は語っているWireコールにオブジェクトをreceiveData()し、sendData()I2Cのイベントに応じて。これは、によって保存および使用される関数ポインタを渡すことによって行われWireます。

これについて詳しく知りたい場合は、C / C ++関数ポインターに関する情報をオンラインで検索することをお勧めします。ArduinoのattachInterrupt()機能を探索することもできます。


ご回答有難うございます。これは今より意味を成し始めています。ただし、receiveData()and sendData()関数が呼び出されない限り実行されない場合、なぜそれらがvoid setup()メインvoid loop()関数ではなく関数内で呼び出されるのですか?確かにこれらの関数は、命令ポインターがvoid setup関数内にある間にi2cイベントが発生するというまれな可能性がない限り、決して呼び出されませんか?これらの関数を関数内から呼び出す方が良いのではないでしょうか?void loopi2cイベントがあるときはいつでも、関数が呼び出されますか?
Blue7 2014年

4
@ Blue7これらの関数はで呼び出されずvoid setup()onReceiveおよびのパラメーターとして渡され、コメントの状態でonRequestコールバックです。非常に短い要約:これは、特定の物事が(発生したとき、これらの関数を呼び出すためにワイヤーライブラリ(からコードを)伝えarduino.cc/en/Reference/WireOnReceivearduino.cc/en/Reference/WireOnRequest ...)
FredP

@FredPああ大丈夫。リンクをありがとう、私が私の電話にいないときにそれらをチェックします。それでも差し支えなければ、私はその間、簡単な質問をします。これらのコールバックは常に準備ができていて、i2cイベントを待っていますか?つまり、命令ポインタがどこにあっても、これらのコールバックはi2cイベントが発生するとすぐに関数を即座に呼び出しますか?
Blue7 2014年

1
@ Blue7おそらくI2Cアクティビティを監視するために割り込みを使用しています。割り込みが実行されると、一時的にメインプログラムから制御を奪います。
Peter Bloomfield

3
@ Blue7コールバックは待機していません(Arduinoはマルチスレッドではありません)。@ PeterRBloomfieldが言うように、Wireライブラリはtwi_init()を呼び出すとI2C割り込みを有効にしますWire.begin。I2Cアクティビティがあると、µCは現在のタスクの実行を停止し(...今は気にしない限り:-)、Wireライブラリのコードに移動し、登録されている(発生していることに応じて適切な)関数を呼び出します。コールバック(receiveDataたとえば)。コールバックは、同じような機能の総称であるreceiveDataか、sendDataそれらが呼び出されていることで、割り込みハンドラワイヤーの内側。
FredP 2014年

2

そのケースではありませんsetup()一度と呼ばれ、loop()繰り返し呼び出されますか?つまり、次のような目に見えない main()ものが存在します。

void main(){
  setup();
  while(True){
    loop();
  }
}

Arduinoを調べているだけで、C / C ++の経験はほとんどありません。私はこのloop()状況に自分で対処しようとしています。


基本的にそうです。呼び出しもありますinit()のために行くのタイマーを取得したがmillisdelayそうはなどinit()、一般的な初期化のためであるsetup()ためであるあなたの初期化、およびloop良く、のためである、ループ。main完全に制御したい場合は、独自に作成できます。
ニックギャモン

素敵な投稿。;最後から2番目以降のBTW は必要ありません}:-)
Greenonline

serial_event()の呼び出しもありますよね?
Divisadero 2017年

2

ディーの返答についてコメントすることはできません。メインループで実行される実際のコードは次のとおりです

    int main(void) {
    init();
    initVariant();

    setup();

    for (;;) {
        loop();
        if (serialEventRun) serialEventRun();
    }   
    return 0;
}

そしてはい、setup()一度loop()呼び出され、繰り返し呼び出されます(いくつかのシリアルのものと共に)。


0

これは通常の機能として機能します。意味をなすように呼び出す必要があります。loop()/ setup()は、Arduinoディレクトリからコンパイルされてリンクされているmain()関数から呼び出されます。receiveData / sendDataは、ルートがloop / setup関数にあるプログラムから呼び出されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.