잘못된 핀 번호를 사용하면 어떻게됩니까?


답변:


9

컴파일러는 오류를 감지하지 않으며 코드가 컴파일되어 실행됩니다. 따라서 어떤 일이 발생하는지 알아 보려면 무대 뒤의 마술을 탐험해야합니다. 요약을 보려면 건너 뛰십시오.


코드의 두 번째 줄은 마술이 일어날 곳과 우리가 집중해야 할 곳입니다.

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_PGMpins_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.


경계 검사가 없다는 것이 흥미 롭습니다. digitalWrite는 어쨌든 너무 느리고 부피가 크므로 컴파일 시간이나 런타임 검사를 수행하는 것이 어색하지 않습니다.
Cybergibbons

모든 arduino 핀이 연속 범위에있는 경우, 포트 == 핀 확인이 아닌 pin> BOARD_MAX_PIN 확인으로 대체 할 수 없었습니다. 여기서 보드 최대 핀은 보드를 감지하는 일부 ifdef를 기반으로 일부 헤더 파일에 정의되어 있습니까?
EternityForest

999를 표현할 수 없으므로 uint8_t코드 호출에 의해 231로 먼저 변환됩니다 pinMode. 최종 결과는 동일합니다 pinModedigitalWrite예기치 않은 동작이있을 것이다 당신이 나쁜 핀 인수를 호출하는 경우 메모리의 임의 부분을 소지품 수 있습니다.
David Grayson

3

표준 라이브러리에는 핀을 포트로 변환하기 위해 설계된 매크로가 있으며 이는 조립에 사용됩니다. 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_PGM20 개의 요소 만 포함 하는 배열 의 985 번째 요소를 가리 키려고합니다 . 이것은 아마도 프로그램에서 임의의 지점을 가리킴으로써 Arduino를 망칠 것입니다.

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