Jestem przyzwyczajony do szkiców Arduino z void setup()
częścią, która działa raz i void loop()
częścią, która ciągle się zapętla. Co się stanie, gdy będziesz mieć nieważne funkcje poza głównym void loop()
? Czy to wszystko będzie się zapętlać równolegle, czy będą działać jeden po drugim? Czy też niektóre funkcje void działają tylko po spełnieniu określonych kryteriów (np. Pętla while)?
Na przykład w poniższym kodzie, kiedy będzie void receiveData(int byteCount)
i void sendData()
funkcje uruchomić?
//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-uno
i2c
Blue7
źródło
źródło
Odpowiedzi:
Funkcje
setup()
iloop()
są niezwykłe, ponieważ są wywoływane automatycznie przez kod Arduino. Żadne inne funkcje nie zachowują się w ten sposób.Ogólnie rzecz biorąc, funkcja nigdy się nie uruchomi, chyba że użytkownik wywoła ją jawnie (np. Z wewnątrz
setup()
lubloop()
) lub nie poinstruuje innej części programu, aby ją wywołała. (Istnieją inne sposoby wykonywania funkcji, ale zwykle wymaga to bardzo zaawansowanego majsterkowania, którego najlepiej unikać).Na przykład
pinMode()
jest funkcją taką jak każda inna. Działa tylko wtedy, gdy faktycznie umieścisz coś takiego jakpinMode(3, INPUT)
w kodzie. W tym momencie uruchamia się raz, kończy, a następnie funkcja wywoływania jest kontynuowana od miejsca, w którym została przerwana (nigdy nie działają równolegle).Przykładowy kod, który opublikowałeś, jest dość interesujący. Spójrz na te linie w
setup()
:Linie te informują
Wire
obiekt o wywołaniureceiveData()
isendData()
w odpowiedzi na zdarzenia I2C. Robi to poprzez przekazywanie wskaźników funkcji, które są przechowywane i używane przezWire
.Polecam wyszukiwanie informacji o wskaźnikach funkcji C / C ++ online, jeśli chcesz dowiedzieć się więcej na ten temat. Możesz być także zainteresowany poznaniem
attachInterrupt()
funkcji Arduino .źródło
receiveData()
isendData()
nie są uruchamiane, chyba że zostaną wywołane, to dlaczego są wywoływane w ramachvoid setup()
funkcji, a nievoid loop()
funkcji głównej ? Z pewnością te funkcje nigdy nie zostaną wywołane, chyba że istnieje rzadka szansa, że wystąpi zdarzenie i2c, gdy wskaźnik instrukcji nadal znajduje się wvoid setup
funkcji? Czy nie byłoby lepiej wywoływać te funkcje z poziomuvoid loop
funkcji, więc gdy występuje zdarzenie i2c, funkcja jest wywoływana?void setup()
, są one przekazywane jako parametronReceive
aonRequest
, są wywołania zwrotne jak stwierdza komentarz. W bardzo krótkim podsumowaniu: mówi (kod z) biblioteki Wire, aby wywoływała te funkcje, gdy zdarzają się określone rzeczy ( arduino.cc/en/Reference/WireOnReceive , arduino.cc/en/Reference/WireOnRequest ...)twi_init()
podczas rozmowyWire.begin
. Gdy występuje aktywność I2C, µC przestaje wykonywać swoje bieżące zadanie (chyba że ... nie ma na razie znaczenia :-) i przechodzi do kodu biblioteki Wire, który następnie wywołuje funkcję (odpowiednią, w zależności od tego, co się dzieje) zarejestrowaną jako oddzwanianie (receiveData
na przykład). Zwrotna to ogólna nazwa dla funkcji, takich jakreceiveData
lubsendData
, są one nazywane przez obsługi przerwań wewnątrz Wire.Czy to nie przypadek, który
setup()
jest wywoływany raz iloop()
jest wywoływany wielokrotnie? tzn. że jest coś niewidocznego,main()
które może wyglądać tak:Przepraszam, że patrzę tylko na Arduino i prawie nie mam doświadczenia w C / C ++; Sam próbuję poradzić sobie z tą
loop()
sytuacją.źródło
init()
którego dostaje liczniki dzieje namillis
,delay
itd. Takinit()
jest do ogólnego inicjalizacjisetup()
jest dla swojej inicjacji, aloop
to za dobrze, zapętlenie. Możesz napisać własny,main
jeśli chcesz przejąć pełną kontrolę.;
nie jest wymagane po przedostatnim}
:-)Nie mogę skomentować odpowiedzi Dee. Rzeczywisty kod wykonywany w głównej pętli znajduje się tutaj :
I tak,
setup()
zostaje wywołany raz iloop()
jest wywoływany wielokrotnie (wraz z kilkoma seriami).źródło
Działa jak normalna funkcja, należy ją wywołać, aby miała sens. loop () / setup () są wywoływane z funkcji main (), która jest skompilowana z katalogu Arduino i połączona z.
źródło