관련 : 런타임 오류가 발생하면 어떻게됩니까?
이 질문은 위의 질문과 유사하지만 대체 상황입니다.
int pin = 999;
pinMode(pin, OUTPUT);
digitalWrite(pin, HIGH);
이 경우 어떻게됩니까? 컴파일러가 그것을 잡을 수도 있지만 난수를 사용하면 IDE가 잡을까요?
관련 : 런타임 오류가 발생하면 어떻게됩니까?
이 질문은 위의 질문과 유사하지만 대체 상황입니다.
int pin = 999;
pinMode(pin, OUTPUT);
digitalWrite(pin, HIGH);
이 경우 어떻게됩니까? 컴파일러가 그것을 잡을 수도 있지만 난수를 사용하면 IDE가 잡을까요?
답변:
컴파일러는 오류를 감지하지 않으며 코드가 컴파일되어 실행됩니다. 따라서 어떤 일이 발생하는지 알아 보려면 무대 뒤의 마술을 탐험해야합니다. 요약을 보려면 건너 뛰십시오.
코드의 두 번째 줄은 마술이 일어날 곳과 우리가 집중해야 할 곳입니다.
pinMode(pin, OUTPUT);
pinMode
이 논의 와 관련된 부분 은 다음과 같습니다.
void pinMode(uint8_t pin, uint8_t mode)
{
uint8_t bit = digitalPinToBitMask(pin); //The first instance where pin is used
uint8_t port = digitalPinToPort(pin);
if (port == NOT_A_PIN) return;
//Do something
}
(완전한 구현은 배선 _ 디지털 .c 에서 찾을 수 있습니다 )
따라서 여기에서는 중간 비트를 계산하는 데 사용하는 digitalPinToBitMask
것 같습니다 pin
. 더 자세히 살펴보면,이 one-liner라는 정의에 정의 digitalPinToBitMask
된 매크로입니다 Arduino.h
.
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
이 이상하게 보이는 하나의 라이너는 매우 간단한 작업을 수행합니다. 배열에서 P 번째 요소를 인덱싱 digital_pin_to_bit_mask_PGM
하고 반환합니다. 이 어레이 digital_pin_to_bit_mask_PGM
는 pins_arduino.h
사용중인 특정 보드의 핀 맵 또는 핀 맵에 정의되어 있습니다.
const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
_BV(0), /* 0, port D */
_BV(1),
_BV(2),
_BV(3),
_BV(4),
_BV(5),
_BV(6),
_BV(7),
...
};
이 배열에는 총 20 개의 요소가 있으므로 운이 좋지 않습니다. 999는이 어레이 외부의 플래시 메모리에서 메모리 위치를 인덱싱하여 예기치 않은 동작을 초래합니다. 아니면?
우리는 여전히 런타임 무정부 상태에 대한 또 다른 방어선을 가지고 있습니다. 함수의 다음 줄 pinMode
:
uint8_t port = digitalPinToPort(pin);
digitalPinToPort
우리를 비슷한 길로 안내합니다. 와 함께 매크로로 정의됩니다 digitalPinToBitMask
. 정의는 다음과 같습니다.
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
이제 핀 맵에 정의 된 배열 인 P 번째 요소를 색인화합니다 digital_pin_to_port_PGM
.
const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
PD, /* 0 */
PD,
....
PC,
PC,
};
이 배열은 20 개의 요소를 포함하므로 999가 다시 범위를 벗어납니다. 다시이 명령은 값을 읽을 수없는 플래시 메모리에서 값을 읽고 반환합니다. 이것은 다시 여기에서 예측할 수없는 행동으로 이어질 것입니다.
여전히 최후의 방어선이 하나 있습니다. 그것이 반환 값의 if
체크인 pinMode
입니다 digitalPinToPort
:
if (port == NOT_A_PIN) return;
NOT_A_PIN
에서 0으로 정의됩니다 Arduino.h
. 따라서 반환 된 바이트 digitalPinToPort
가 0 pinMode
이되면 자동으로 실패하고 반환됩니다.
어쨌든 pinMode
무질서에서 우리를 구할 수는 없습니다. 999는 운명을 초래할 운명입니다.
TL; DR, 코드가 실행되며 그 결과를 예측할 수 없습니다. 대부분의 경우에는 핀으로 설정되지 않습니다 OUTPUT
, 그리고 digitalWrite
실패합니다. 당신이 매우 나쁜 운이 일어날 경우, 임의의 핀으로 설정을받을 수 있습니다 OUTPUT
, 그리고 digitalWrite
그것을 설정할 수 있습니다 HIGH
.
uint8_t
코드 호출에 의해 231로 먼저 변환됩니다 pinMode
. 최종 결과는 동일합니다 pinMode
및 digitalWrite
예기치 않은 동작이있을 것이다 당신이 나쁜 핀 인수를 호출하는 경우 메모리의 임의 부분을 소지품 수 있습니다.
표준 라이브러리에는 핀을 포트로 변환하기 위해 설계된 매크로가 있으며 이는 조립에 사용됩니다. Arduino 1.0.5의 Uno를위한 것입니다 :
#define digitalPinToPCICR(p) (((p) >= 0 && (p) <= 21) ? (&PCICR) : ((uint8_t *)0))
#define digitalPinToPCICRbit(p) (((p) <= 7) ? 2 : (((p) <= 13) ? 0 : 1))
#define digitalPinToPCMSK(p) (((p) <= 7) ? (&PCMSK2) : (((p) <= 13) ? (&PCMSK0) : (((p) <= 21) ? (&PCMSK1) : ((uint8_t *)0))))
#define digitalPinToPCMSKbit(p) (((p) <= 7) ? (p) : (((p) <= 13) ? ((p) - 8) : ((p) - 14)))
더 있지만 여기에 표시하지 않습니다.
귀하의 프로그램이 999에서 14를 뺀 것으로 여전히 브로 그램에 비해 너무 큽니다. 그런 다음 digital_pn_to_bit_mask_PGM
20 개의 요소 만 포함 하는 배열 의 985 번째 요소를 가리 키려고합니다 . 이것은 아마도 프로그램에서 임의의 지점을 가리킴으로써 Arduino를 망칠 것입니다.