답변:
올바르게 이해하면 UART를 통해 2 개의 장치가 연결되어 있습니다. TX, RX 및 GND 회선 만 장치간에 연결되어 있다고 가정합니까? (즉, DTS / CTS / DTR / RTS 제어 라인이 사용되지 않습니다-이것이 일반적입니다).
이 시나리오에서 장치 1의 TX (전송)는 장치 2의 RX (수신)에 연결되며 그 반대도 마찬가지입니다. 그들의 근거는 서로 연결되어 있습니다. 따라서, 각각의 장치는 동시에 송수신 할 수있다 (각각 별도의 유선을 통해 전송하며, 통신은 전이 중이다).
내가이 모든 것을 언급 한 이유는 "스니핑"또는 "듣기"가 확실하기 때문에 대화의 양쪽을 들으려면 실제로 2 개의 UART가 필요하다는 것입니다.
기본적으로 3 개의 장치의 UART GND가 모두 단락되고 배관과 같은 T- 피팅과 같이 "실제로"티 "인 장치 1과 장치 2의 TX 회선을 2 개의 RX 회선에 연결하기 만하면됩니다. 2 개의 UART에. 전송 속도가 모두 동일하게 구성되어 있는지 확인하십시오.
Arduino 보드 / 디자인이 많이 있습니다. 요즘 가장 흔한 Duemilanove는 ATMega328P를 사용하는데 UART는 1 개뿐입니다. 따라서 두 번째 UART IC를 연결하거나 두 번째 수신기의 "비트 뱅킹"을 사용해야합니다.
비동기 UART 통신은 시작 및 중지 비트 (때로는 패리티 비트)와 함께 잘 정의되어 있으므로 프로세서가 충분히 빠르면 장치의 UART TX 회선 중 하나를 입력으로 구성된 GPIO에 연결하고 회선을 폴링 할 수 있습니다. 오버 샘플링으로 시작 및 중지 및 샘플 비트를 감지하기에 충분히 빠릅니다. Jack Ganssle의 "Bit Banging" 기사 는 씹을만한 내용을 많이 제공합니다.
RS232 파형에 대한 적절한 설명은 BeyondLogic 에서 확인할 수 있습니다 .
고려해야 할 전압 레벨 (0 / + 5, -10V / + 10V 등)과 같은 다른 문제가 있습니다 ( "RS232 레벨 컨버터"의 로직 이외의 섹션 참조). 위에서 설명한 "연결 연결"접근 외에 하드웨어 인터페이스에 대해 논의 할 시스템에 대한 정보가 충분하지 않습니다. 전압 레벨이 일치한다고 가정하면 일반적으로 TX 라인을 두 번째 수신기 (스니퍼)에 "티 (tee)"하는 것은 문제가되지 않지만 TX에 충분한 드라이브가없는 경우 버퍼 / 드라이버를 삽입해야합니다. 저하로부터의 신호.
통신이 한 번에 한 방향으로 만 이루어지는 경우 (예 : 반이중 통신) 깔끔한 트릭이 있습니다. 양측이 동시에 서로 대화하는 경우에는 작동하지 않지만 (전이중) 일반적인 "이것" "이것은 반응입니다" "지금은" ""새로운 반응은 여기 있습니다 " 꽤 잘 작동합니다.
UART 링크는 로직 하이 (1) 레벨에서 트랜스미터의 유휴 상태를 사용하므로 2- 입력 AND 게이트를 사용하여 각 측면에서 AND 입력으로 TX를 연결합니다. AND 게이트의 출력은 스니퍼의 UART (RX 핀)에 대한 입력입니다. 이제 장치 B의 TX 라인을 가져와 스니퍼의 I / O 포트로 가져옵니다. 이 핀이 높음에서 낮음으로 갈 때 인터럽트를 생성하도록 스니퍼를 구성합니다.
요약 : 장치 A UART TX-> AND 게이트 입력. 장치 B UART TX-> 기타 AND 게이트 입력 및 스니퍼 GPIO 핀. AND 게이트-> 스니퍼 UART RX 라인의 출력.
UART 통신은 시작 비트, 일부 데이터 비트, 선택적 패리티 비트 및 하나 이상의 정지 비트로 구성됩니다. 유휴 상태는 로직 하이 (1)이므로 모든 바이트의 시작은 로직 로우 (0)가되고 스니퍼의 인터럽트가 발생합니다. 스니퍼가 I / O 인터럽트를 실행하는 동안 UART 하드웨어는 AND 게이트에서 비트를 수집합니다. UART가 정지 비트를 수신 할 때까지 I / O 인터럽트가 오래 걸리고 UART RX 인터럽트가 발생합니다.
IO에서 인터럽트 변경 루틴은 "방향"변수를 설정하여 통신이 "B-> A"방향임을 나타냅니다. 스니퍼의 UART 수신 인터럽트는이 "방향"변수를보고 방금 수신 한 바이트를 적절한 버퍼에 씁니다. 그런 다음 UART RX 인터럽트는 "direction"변수를 기본 "A-> B"상태로 다시 설정합니다.
volatile int direction = 0; /* 0 = A -> B */
void io_interrupt(void)
{
direction = 1; /* switch direction, now B -> A */
}
void uart_interrupt(void)
{
unsigned char b;
b = UART_RX_REG;
if(direction) {
store_byte_to_device_b_sniff_buffer(b);
} else {
store_byte_to_device_a_sniff_buffer(b);
}
direction = 0; /* reset direction to default A -> B */
}
이 코드는 명확성을 위해 작성되었으며 실제 상황에서 작성해야하는 것은 아닙니다. 개인적으로 나는 "방향"을 적절한 FIFO 구조에 대한 포인터로 만들 것입니다. 그러나 그것은 또 다른 연습입니다. :-)
장치 A가 대화 중일 때 I / O 라인이 움직이지 않으며 (장치 B의 UART 송신기가 유휴 상태이므로 논리 '1'로 유지됨) UART RX 인터럽트가 바이트를 수신합니다. 방향이 A-> B인지 확인하십시오. 데이터를 해당 버퍼에 저장하십시오. 장치 B가 대화 중일 때 장치 B가 데이터 이동을 시작하자마자 I / O 라인이 낮아지고 I / O 인터럽트 루틴은 장치 B가 대화 중임을 나타내는 방향을 설정합니다. UART RX 인터럽트는 모든 비트가 수집 된 후에 발생하며 I / O 인터럽트가 방향 레지스터를 적절하게 설정하기 때문에 수신 된 바이트가 올바른 버퍼에 저장됩니다.
Presto : 스니퍼에서 단일 UART 및 I / O 라인으로 캡처 한 두 장치 간의 반이중 통신 (비트 뱅킹 UART 통신 없음).