Void loop dışındaki fonksiyonlar nasıl çalışır?


9

Ben bir void setup()kez çalışan bir void loop()parçası ve döngü devam bir parçası ile Arduino skeçler alışkınım . Ana ünite dışında geçersiz işlevleriniz olduğunda ne olur void loop()? Bunların hepsi paralel olarak dönecek mi yoksa birbiri ardına koşuyorlar mı? Veya belirli geçersiz işlevler yalnızca belirli ölçütler karşılandıktan sonra mı çalışır (bir while döngüsü gibi)?

Örneğin aşağıdaki kodda, void receiveData(int byteCount)ve void sendData()işlevleri ne zaman çalışır?

//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.
}

Bu ilginç görünüyor. Kodun kaynağına (ve Arduino ile Pi arasındaki bağlantıların ayrıntılarına) bağlantılar gönderebilir misiniz acaba?
Milliways

1
@Milliways Arduino uno ve Raspberry pi (B + model) üzerine kod yazmak için bu * öğreticiyi kullandım , ancak birkaç küçük değişiklik yaptım.İki kartın SDA ve SCL pinlerini ve ayrıca zemin pimlerini bağlayın farklı güç kaynaklarına bağlıdır. Daha sonra, + 5V ve Gnd pinleri arasında bağlı, potansiyel bölücü konfigürasyonunda yapılandırılmış bir sensöre pin 3 bağladım. Pim 0 ve Gnd bir motor sürücü kartına bağlıdır.
Blue7

Yanıtlar:


11

setup()Ve loop()onlar Arduino kodu ile sizin için otomatik olarak adlandırılır, çünkü fonksiyonları sıradışı. Başka hiçbir işlev bu şekilde davranmaz.

Genel olarak, bir işlev, açıkça kendiniz (örn. İçinden setup()veya içinden loop()) çağrılmadıkça veya programın başka bir bölümünü çağırmasını istemediğiniz sürece hiçbir zaman çalışmaz . (İşlevleri yürütmenin başka yolları da vardır, ancak bu genellikle en iyi kaçınılması gereken çok gelişmiş müdahaleleri içerir.)

Örneğin, pinMode()tıpkı diğerleri gibi bir işlevdir. Yalnızca pinMode(3, INPUT)kodunuza benzer bir şey koyduğunuzda çalışır . Bu noktada, bir kez çalışır, biter ve daha sonra çağrı işlevi kaldığı yerden devam eder (asla paralel çalışmazlar).

Gönderdiğiniz örnek kod oldukça ilginç. Şu satırlara bakın setup():

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

Bu satırlar, Wirenesneye çağrı yapmasını receiveData()ve sendData()I2C olaylarına yanıt olarak söyler . Bunu, tarafından depolanan ve kullanılan fonksiyon işaretleyicilerini geçirerek yapar Wire.

Bu konuda daha fazla bilgi edinmek isterseniz çevrimiçi olarak C / C ++ işlev işaretçileri hakkında bilgi aramanızı öneririm . Ayrıca, Arduino'nun attachInterrupt()işlevini keşfetmek de ilginizi çekebilir .


Cevabınız için teşekkürler. Bu şimdi daha anlamlı olmaya başlıyor. Ancak, receiveData()ve sendData()işlevleri çağrılmadıkça çalıştırılmazsa, neden void setup()ana void loop()işlev yerine işlev içinde çağrılır ? Şüphesiz bu işlevler, yönerge işaretçisi hala void setupişlev içindeyken bir i2c olayı olması nadiren olmadıkça asla çağrılmayacak mı? Bu işlevleri işlev içinden çağırmak daha iyi olmaz, bu void loopnedenle her i2c olayı olduğunda işlev çağrılır mı?
Blue7

4
Blue7 @ değildir Bu fonksiyonlar denir içinde void setup(), onlar parametre olarak geçirilir onReceiveve onRequestonlar, konum geri aramalar açıklama devletler olarak. Çok kısa bir özetle: Bu, Tel kütüphanesinden (kod) belirli şeyler olduğunda bu işlevleri çağırmasını söyler ( arduino.cc/en/Reference/WireOnReceive , arduino.cc/en/Reference/WireOnRequest ...)
FredP

@FredP Ah tamam. Bağlantılar için teşekkürler, telefonumda olmadığımda onları kontrol edeceğim. Bu arada hızlı bir sorum var, eğer sakıncası yoksa. Bu geri aramalar her zaman hazır ve i2c etkinliği bekliyor mu? yani, yönerge işaretçisi nerede olursa olsun, i2c olayı meydana gelir gelmez bu geri çağrılar anında işlevi çağırır?
Blue7

1
@ Blue7 Muhtemelen I2C aktivitesini izlemek için kesmeler kullanacaktır. Bir kesinti yürütüldüğünde, kontrolü geçici olarak ana programdan uzaklaştırır.
Peter Bloomfield

3
@ Blue7 @PeterRBloomfield'ın dediği gibi, geri aramalar beklemiyor (Arduino çok iş parçacıklı değil), Tel kütüphanesi twi_init()aradığınızda I2C kesilmesini etkinleştiriyor Wire.begin. I2C aktivitesi olduğunda µC mevcut görevini yapmayı durdurur (... an için nevermind :-) ve Wire kütüphanesinin koduna girmez, daha sonra kaydettiğiniz (uygun olana bağlı olarak) işlevi çağırır geri arama ( receiveDataörneğin). Geri arama , receiveDataveya gibi işlevler için genel addır ve sendDatabunlar Wire içindeki bir kesme işleyicisi tarafından çağrılır .
FredP

2

Bir setup()kez çağrılan ve loop()tekrar tekrar çağrılan bu durum değil mi? yani şöyle görünebilecek bir görünmeyen main() var:

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

Ben sadece Arduino bakarak ve neredeyse hiçbir C / C ++ deneyimim özür dilerim; Bu loop()durumu kendim halletmeye çalışıyorum .


Temel olarak, evet. Orada bir çağrı da hiç init()hangi gidiş zamanlayıcılar alır millis, delayYani vb init()genel başlatma içindir setup()içindir senin başlatma ve loopdöngü, iyi, içindir. mainTam kontrole sahip olmak istiyorsanız kendiniz yazabilirsiniz .
Nick Gammon

Güzel mesaj. BTW ;sondan bir önceki }:-) gerekli değildir
Greenonline

Ayrıca serial_event () çağrısı var değil mi?
Divisadero

2

Dee'nin yanıtı hakkında yorum yapamam. Ana döngüde yürütülen gerçek kod burada :

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

    setup();

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

Ve evet, bir setup()kez çağrılır ve loop()tekrar tekrar çağrılır (bazı seri şeylerle birlikte).


0

Normal işlev olarak çalışır, mantıklı olması için çağrılmalıdır. loop () / setup (), Arduino dizininden derlenen ve bağlanan bir main () işlevinden çağrılır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.