void 루프 외부의 함수는 어떻게 작동합니까?


9

void setup()한 번 실행되는 void loop()부분과 계속 반복 되는 부분 으로 Arduino 스케치에 익숙합니다 . 메인 외부에서 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 간의 연결 세부 정보)에 대한 링크를 게시 할 수 있는지 궁금합니다.
Milliways

1
@Milliways 나는 튜토리얼을 사용 하여 arduino uno 및 Raspberry pi (B + 모델)에 코드를 작성했지만 몇 가지 작은 변경을했습니다. 두 보드의 SDA 및 SCL 핀뿐만 아니라 접지 핀도 연결하십시오 다른 전원 공급 장치에 연결되어 있습니다. 그런 다음 핀 3을 전위 분배기 구성으로 구성된 센서에 연결하고 + 5V와 Gnd 핀 사이에 연결했습니다. 핀 0 및 Gnd는 모터 드라이브 보드에 연결됩니다.
Blue7

답변:


11

setup()loop()그들이 아두 이노 코드에 의해 자동으로 요구되기 때문에 기능이 비정상적입니다. 다른 기능은 이런 식으로 동작하지 않습니다.

일반적으로 함수를 명시 적으로 호출 setup()하거나 (예 : within 또는 loop()) 프로그램의 다른 부분에 호출하지 않으면 함수가 실행되지 않습니다 . (함수를 실행하는 다른 방법이 있지만 일반적으로 피하는 것이 가장 좋은 고급 땜장이 포함됩니다.)

예를 들어, pinMode()다른 것과 같은 기능입니다. 실제로 pinMode(3, INPUT)코드 와 같은 것을 넣을 때만 실행됩니다 . 이 시점에서 한 번 실행 된 후 종료 된 다음 호출 기능이 중단 된 지점부터 수행됩니다 (병렬로 실행되지 않음).

게시 한 예제 코드는 매우 흥미 롭습니다. 이 라인을 살펴보십시오 setup():

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

이 줄은 Wire개체 에게 I2C 이벤트에 대한 호출 receiveData()sendData()응답을 지시합니다. 에 의해 저장되고 사용되는 함수 포인터를 전달하여이를 수행 Wire합니다.

이에 대해 더 배우려면 온라인으로 C / C ++ 함수 포인터 에 대한 정보를 검색하는 것이 좋습니다 . Arduino의 attachInterrupt()기능 을 살펴볼 수도 있습니다 .


답변 주셔서 감사합니다. 이제 더 이해하기 시작했습니다. 그러나 receiveData()sendData()함수가 호출되지 않는 한 실행되지 않으면 왜 void setup()void loop()함수가 아닌 함수 내에서 호출 됩니까? 명령어 포인터가 여전히 void setup함수 내에있는 동안 i2c 이벤트가 발생하는 경우가 아니면 이러한 함수는 호출되지 않습니다 . void loopi2c 이벤트가있을 때마다 함수가 호출되므로 함수 내에서 이러한 함수를 호출하는 것이 더 좋지 않습니까?
Blue7

4
Blue7 @되지 않는 이러한 기능 이라고 의는 void setup(), 그들의 매개 변수로 전달 onReceive하고 onRequest그들이있는 거 콜백을 주석 상태로. 간단히 요약하면 : 특정 상황이 발생할 때 ( arduino.cc/en/Reference/WireOnReceive , arduino.cc/en/Reference/WireOnRequest ...) Wire 라이브러리의 코드에서 이러한 함수를 호출하도록 지시합니다 .
FredP

@FredP 아 알았어. 링크 주셔서 감사합니다, 내가 전화하지 않을 때 그들을 확인합니다. 그래도 걱정하지 않는다면 빠른 질문이 있습니다. 이 콜백은 항상 준비되어 i2c 이벤트를 기다리고 있습니까? 즉, 명령어 포인터의 위치에 관계없이 이러한 콜백은 i2c 이벤트가 발생하자마자 즉시 함수를 호출합니까?
Blue7

1
@ Blue7 아마도 인터럽트를 사용하여 I2C 활동을 모니터링 할 것입니다. 인터럽트가 실행되면 주 프로그램에서 일시적으로 제어를 중단합니다.
Peter Bloomfield

3
@ Blue7 @PeterRBloomfield가 말한 것처럼 Wire 라이브러리는 twi_init()전화를 걸 때 I2C 인터럽트를 활성화 합니다 Wire.begin. I2C 활동이있을 때 µC는 현재 작업 수행을 중단하고 (순간은 신경 쓰지 않는 한 :-) 와이어 라이브러리의 코드를 입력 한 다음 등록한 (적절한 상황에 따라) 함수를 호출합니다. 콜백 ( receiveData예 :) 콜백 과 같은 기능에 대한 일반 이름 receiveData또는 sendData그들이는 호출하고, 인터럽트 핸들러 와이어 내부.
FredP

2

그것은 그 경우가 아니라 setup()한 번 호출되고 loop()반복적으로 호출됩니다? 즉, 다음과 같은 보이지 않는 main() 것이 있습니다.

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

Arduino를 살펴보고 C / C ++ 경험이 거의없는 사과. 이 loop()상황을 직접 처리하려고합니다 .


기본적으로 그렇습니다. 이 호출은 또한에 init()있는가는 타이머를 얻을 millis, delay그래서 등 init(), 일반 초기화를위한 setup()위한 당신의 초기화 및 loop반복, 음,입니다. main모든 권한을 원한다면 직접 작성할 수 있습니다 .
Nick Gammon

좋은 포스트. BTW ;는 두 번째 이후에 필요하지 않습니다 }:-)
Greenonline

serial_event ()의 호출이 있습니까?
Divisadero

2

디의 답변에 대해서는 언급 할 수 없습니다. 메인 루프에서 실행되는 실제 코드는 다음과 같습니다.

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

    setup();

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

그리고 네, setup()한 번 호출 loop()되고 반복적으로 호출됩니다 (일련의 내용과 함께).


0

정상적인 기능으로 작동하므로 이해하기 위해 호출해야합니다. loop () / setup ()은 Arduino 디렉토리에서 컴파일되어 링크 된 main () 함수에서 호출됩니다. receiveData / sendData는 루트에서 루프 / 설정 함수에있는 프로그램에서 호출됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.