라즈베리파이 Python 프로그래밍 17: UART 프로토콜을 사용한 직렬 통신
이전 포스팅에서 라즈베리파이)를 사용할 때 소프트웨어 PWM의 형태로 아날로그 출력을 생성하는 방법을 배웠습니다. 또한 소프트웨어 PWM을 사용하여 LED를 페이드 하는 방법도 알아보았죠.
PWM 출력은 DC 모터의 속도 제어 또는 서보 모터 제어와 같은 다른 애플리케이션에도 사용할 수 있습니다. 임베디드 컴퓨터로서 라즈베리파이는 디지털 입력, 디지털 출력, PWM 및 다양한 직렬 통신 프로토콜(UART/USART, I2C 및 SPI 등)의 구현이 가능합니다.
범용 비동기식 수신기/송신기 또는 UART는 임베디드 장치에서 사용하는 가장 일반적인 직렬 통신 프로토콜입니다. 이번 포스팅에서 직렬 통신의 기본 사항을 다루고 RPi를 사용한 여러 직렬 통신 옵션을 검토합니다.
직렬 통신이란 무엇입니까 ?
직렬 통신은 유선을 통해 데이터를 순차적으로 전송하는 것을 말합니다. 니블 nibble 또는 바이트 Byte는 정보의 가장 작은 단위입니다. 바이트는 8비트로 구성되고 니블은 4비트로 구성됩니다. 더 큰 단위에는 킬로바이트, 메가바이트, 기가바이트 등이 포함됩니다.
두 장치 간의 데이터 통신은 유선 또는 무선일 수 있습니다. 유선 통신에서 데이터(정보)는 유선을 통해 두 장치 간에 통신됩니다. 이러한 와이어를 데이터 버스라고 합니다. 데이터를 통신하는 장치(또는 장치의 구성요소)의 채널(핀)을 통틀어 통신 포트라고 합니다.
유선 통신 포트에는 두 가지 유형이 있습니다.
1. 병렬 포트 Parrallel Port: 데이터가 병렬 데이터 라인으로 통신합니다.
2. 직렬 포트 Serial Port: 데이터가 bit-stream으로 통신합니다.
병렬 포트는 고정 크기 데이터의 빠른 데이터 통신에 유용합니다. 예를 들어, 데이터는 8, 16, 32 또는 64비트 등의 고정 크기 단위로 구성될 수 있습니다. 또한 병렬 데이터 버스와 병렬 포트 각 와이어에서 1비트 데이터 단위로 높은 전송 속도를 제공할 수 있습니다.
반면에 직렬 포트는 고정 단위의 데이터를 전송하고 가변 크기의 데이터를 통신할 수 있습니다. 병렬 포트가 데이터 통신에 복잡한 회로를 사용하는 경우 직렬 포트는 데이터 전송에 필요한 채널 수를 줄여 데이터 통신을 단순화합니다.
범용 컴퓨터는 전송률이 높기 때문에 데이터 통신에 병렬 포트를 사용하는 경우가 많지만 임베디드 컨트롤러와 컴퓨터는 일반적으로 직렬 포트에 의존합니다. 여기에는 여러 가지 이유가 있습니다.
첫째, 직렬 포트는 덜 복잡한 회로를 포함하고 마이크로컨트롤러 또는 SoC(시스템 온 칩)에 쉽게 통합될 수 있습니다. 또한 임베디드 컨트롤러/컴퓨터는 여러 장치와 인터페이스 하여 단일 사용자 프로그램에서 통신할 수 있습니다. 여러 개의 GPIO(디지털 입/출력) 핀이 필요하기 때문에 병렬 포트가 있는 여러 외부 주변 장치 및 장치를 인터페이스 하는 것은 거의 불가능합니다.
그러나 직렬 포트의 2개, 3개 또는 4개 채널만 사용하여 수백 개의 주변 장치/장치와 인터페이스하고 통신할 수 있습니다. 고정 및 가변 데이터 패킷 크기의 데이터 전송을 지원하는 직렬 통신 프로토콜이 있습니다.
범용 컴퓨팅에서 병렬 포트는 일반적으로 외부 주변 장치와의 인터페이스를 위한 USB(범용 직렬 버스)로 대체되었습니다. 내부 인터페이스를 위한 병렬 인터페이스(예: 저장 장치와의 인터페이스를 위한 ATA)도 직렬 표준으로 대체되었습니다. 여기에는 SATA(Serial ATA), SAS(Serial Attached SCSI) 및 PCIe 물리적 인터페이스가 포함됩니다.
데이터 통신 표준
통신 포트는 인터페이스 된 주변기기/장치와 데이터 통신을 담당하는 컨트롤러/프로세서의 채널(핀) 또는 채널 그룹(핀)을 나타냅니다. 데이터 버스는 두 장치 간에 또는 컨트롤러/프로세서와 주변 장치/장치 간에 데이터가 통신되는 와이어 또는 와이어 그룹입니다.
"인터페이스"라는 용어는 일반적으로 데이터 통신에 사용되는 전자 신호 및 버스 시스템을 나타냅니다. RS-232, RS-422, RS-485, I2C, SPI, Microwire, CAN, 1-wire 및 USB는 직렬 인터페이스의 예입니다(즉, 이러한 표준은 직렬 데이터 통신을 위한 전자 신호 체계 및 버스 시스템을 나타냄).
"프로토콜"이라는 용어는 버스를 통해 두 장치 간 또는 컨트롤러/프로세서와 장치/주변 장치 간에 데이터가 통신, 인코딩 및 디코딩되는 방식을 나타냅니다. UART, USART, I2C, SPI, CAN BUS 프로토콜, Microwire, 1-wire 및 USB는 직렬 통신 프로토콜의 예입니다(즉, 이러한 표준은 직렬 데이터 통신의 데이터 인코딩 및 디코딩을 나타냄).
표준은 인터페이스, 프로토콜 또는 둘 다일 수 있습니다. 예를 들어 RS-232, RS-422 및 RS-485는 UART 직렬 통신 프로토콜을 사용하는 직렬 인터페이스입니다. UART 및 USART는 UART/USART 칩 또는 내장 UART/USART를 통합하여 구현할 수 있는 직렬 통신 프로토콜입니다. I2C, SPI, CAN, Microwire, 1-Wire 및 USB와 같은 표준은 인터페이스이자 프로토콜입니다.
사양
직렬 통신 프로토콜/인터페이스가 작동하는 방식을 이해하려면 먼저 직렬 통신 표준의 많은 사양에 대해 배우는 것이 중요합니다. 일반적으로 다음 사양은 모든 직렬 통신 표준에 적용됩니다.
비동기 및 동기 신호
- 비동기 신호: 데이터 버스에 있는 경우 데이터가 타이밍 신호 없이 전송됩니다.
- 동기 신호: 데이터 버스에서 데이터가 타이밍 클록과 함께 전송되는 경우(클록 신호가 전용 채널을 통해 전달됨을 의미)
전송 모드
전송 모드는 단방향, 반이중 또는 전이중일 수 있습니다.
- 단방향: 데이터가 장치 간에만 단지 수신하거나 또는 전송할 수 있는 경우
- 반이중: 장치 간에 데이터를 주고받을 수 있지만 동시에는 불가능한 경우
- 전이중: 장치 간에 데이터를 동시에 송수신할 수 있는 경우
통신 유형
직렬 통신은 점대점, 다중점, 다중 드롭, 마스터/슬레이브 또는 다중 마스터가 될 수 있습니다.
- 점대점 또는 피어 직렬 통신: 두 장치가 점대점 통신을 할 때. 즉, 한 채널은 다른 장치에서 데이터를 수신하는 데 사용하고 다른 채널은 다른 장치에 데이터를 전송하는 데 사용됩니다. 지점 간 직렬 통신에서는 버스 전체에 피어 트랜시버가 2개뿐입니다(와이어 그룹 및 이 경우에는 2개 와이어만).
- 다중 지점 직렬 통신: 2개 이상의 피어 트랜시버가 공통 버스를 통해 양방향 통신을 할 때. 이러한 형태의 직렬 통신에는 다른 트랜시버 장치가 직렬 데이터를 전송하거나 수신해야 하는 트랜시버 장치를 식별하기 위한 메커니즘이 포함되어야 합니다.
- 다중 드롭 직렬 통신: 공통 버스를 공유하는 직렬 데이터의 단 하나의 송신기와 다중 수신기가 있습니다. 이러한 형태의 직렬 통신에는 공통 버스 시스템에서 수신기를 식별하는 메커니즘이 있어야 합니다.
- 마스터/슬레이브 직렬 통신: 한 장치는 마스터로 구성되고 다른 장치는 슬레이브로 구성됩니다. 마스터는 슬레이브를 제어하고 타이밍 신호(동기 신호)를 사용하여 단일 채널 또는 두 채널을 통해 슬레이브에 데이터를 수신하거나 전송할 수 있습니다.
- 다중 마스터 직렬 통신: 버스의 마스터가 둘 이상 있을 수 있습니다. 이 통신 프로토콜에는 공통 직렬 버스를 사용하기 위해 마스터 간의 충돌을 방지하는 메커니즘이 있어야 합니다.
일반적인 직렬 통신 표준(인터페이스/프로토콜)의 사양은 다음과 같이 요약됩니다.
라즈베리파이의 직렬 통신
디지털 입력 및 출력에 대한 이전 자습서에서는 데이터를 병렬로 전송했습니다. RPi의 GPIO 핀은 3.3V TTL 로직 레벨에서 디지털 데이터 통신이 가능한 병렬 데이터 핀으로 간주될 수 있습니다. 그러나 이러한 GPIO 핀은 마이크로 컨트롤러와 같이 포트(8, 16 또는 32비트 포트)로 배열되지 않습니다.
Raspberry Pi는 UART, I2C, SPI 및 USB와 같은 일반적인 직렬 통신 프로토콜 중 일부를 사용하여 다른 장치와 직렬 데이터를 통신할 수 있습니다. RPi 3B/4B에는 2개의 UART 포트/인터페이스, 2개의 I2C 포트(하나는 HATS용, 다른 하나는 외부 장치용), 2개의 SPI 포트 및 4개의 USB 포트가 있습니다.
라즈베리파이의 UART(universal asynchronous receiver/transmitter)
Universal Asynchronous Receiver/Transmitter 또는 UART는 일반적으로 컴퓨터 용어로 "직렬 포트"라고 합니다. 라즈베리파이도 예외는 아닙니다. RPi의 경우 직렬 포트 용어는 독점적으로 UART를 나타냅니다.
라즈베리파이 모델의 Broadcom SoC에는 두 가지 유형의 내장 UART가 있습니다.
1. PL011 UART
2. Mini UART
PL011은 16550 호환 UART인 반면 mini-UART는 기능 집합이 축소되었습니다. RPi Zero, 1, 2 및 3에는 2개의 UART 포트가 있습니다. 하나는 PL011(UART0)이고 다른 하나는 mini-UART 유형(UART1)입니다.
RPi 4에는 6개의 UART 포트가 있으며 그중 5개는 PL011 유형(UART0, UART2 ~ UART5)이고 하나는 미니 UART 유형(UART1)입니다. 5개의 PL011 유형 중 4개(UART2 ~ UART5)는 기본적으로 비활성화되어 있습니다.
GPIO 14(보드 핀 8)의 두 UART 중 하나는 송신기이고 다른 하나인 GPIO15(보드 핀 10)는 수신기입니다. 이것은 RPi의 기본 UART입니다.
일반적으로 이 기본 UART는 기본적으로 Linux 콘솔에서 사용됩니다. 즉, RPi의 GPIO 헤더에 있는 직렬 TTL 포트(GPIO14 및 GPIO15)를 UART 프로토콜을 사용하는 장치와의 직렬 통신에 사용해야 하는 경우 raspi-config(라즈베리파이 구성 옵션)를 사용하여 구성해야 합니다.
GPIO14 및 GPIO15를 라즈베리파이의 직렬 하드웨어 포트 또는 직렬 TTL 포트라고 합니다.
보조 UART는 GPIO 헤더에 없습니다. 오히려 기본적으로 결합된 WLAN/Bluetooth 컨트롤러의 Bluetooth 측에 연결됩니다.
다양한 RPi 모델의 기본 및 보조 UART 유형은 다음과 같이 요약됩니다.
참고: Mini-UART는 기본 UART인지 보조 UART인지에 관계없이 기본적으로 비활성화되어 있습니다. RPi의 운영 체제(Raspbian, Ubuntu 또는 RPi에서 실행되는 모든 Debian 기반 Linux 배포판 포함)에서 UART는 다음과 같이 Linux 장치로 식별됩니다.
/dev/serial0 및 /dev/serial1은 /dev/ttyS0 또는 /dev/ttyAMA0을 가리키는 심볼릭 링크입니다. 예를 들어, Raspberry Pi 3/4에서 /dev/serial0은 /dev/ttyS0을 가리키고 /dev/serial1은 /dev/ttyAMA0을 가리킵니다. 그러나 Raspberry Pi Zero에서 /dev/serial0은 /dev/ttyAMA0을 가리키고 /dev/serial1은 /dev/ttyS0을 가리킵니다. /boot/config.txt 파일을 검사하여 어떤 UART 유형이 기본 UART인지 알 수 있습니다.
/boot/config.txt 파일에서 enable_uart 플래그가 기본적으로 0으로 설정되어 있으면 mini-UART가 해당 RPi 모델의 기본 UART이고 enable_uart 플래그가 기본적으로 1로 설정되어 있으면 PL011이 해당 RPi 모델의 기본 UART입니다..
mini-UART는 VPU의 코어 주파수에 연결되어 보드 속도(UART 프로토콜을 통한 데이터 전송 속도)가 코어 클럭 주파수에 따라 변경됩니다. 이것은 mini-UART를 불안정하게 만듭니다. 또한 데이터 손실 또는 손상으로 이어질 수 있는 패리티 검사가 없습니다. 따라서 mini-UART를 사용해야 하는 경우 코어 클럭 주파수를 고정해야 합니다.
mini-UART가 기본 UART로 설정된 경우(/boot/config.txt에서 enable_uart = 0이 기본값임) mini-UART는 GPIO 헤더의 직렬 TTL 포트에서 활성화될 수 있으며 코어 클럭 주파수는 250 MHz로 설정할 수 있습니다. /boot/config.txt에서 enable_uart = 1로 설정합니다. VPU 터보 주파수를 mini-UART의 고정 주파수로 사용해야 하는 경우(경우에 따라 Primary UART) force_turbo 플래그를 /boot/config.txt 파일에서 1(force_turbo = 1)로 설정해야 합니다. mini-UART가 보조 UART로 설정된 경우(/boot/config.txt에서 enable_uart = 1이 기본값임) mini-UART의 코어 클록 주파수는 core_freq 플래그를 250(core_freq = 250)으로 설정하여 250MHz로 설정할 수 있습니다. /boot/config.txt 파일에 있습니다.
이 이미지는 RPi의 GPIO 헤더에 있는 직렬 TTL 포트(기본 UART의 Tx 및 Rx 핀과 RPi의 하드웨어 직렬 포트)의 위치를 보여줍니다.
이 직렬 TTL 포트를 사용하려면 기본적으로 사용되는 RPi OS의 직렬 Linux 콘솔을 먼저 비활성화해야 합니다. 두 UART 유형 모두 3.3V와 호환되므로 서로 다른 인터페이스(예: RS-232 또는 USB)를 통한 적절한 직렬 통신을 위해 적절한 직렬 어댑터를 사용하는 것이 중요합니다.
예를 들어 USB 직렬 보드는 다른 장치의 USB 인터페이스와 직렬 통신을 위해 사용해야 합니다. 또는 RS-232-to-TTL-serial-port-converter를 사용하여 다른 장치의 RS-232 인터페이스와 인터페이스 하십시오.
직렬 어댑터에는 3.3/5V 레벨 시프터가 있어야 RPi 직렬 TTL 포트의 3.3V TTL 논리 신호를 5V TTL 논리 신호(USB) 또는 기타 TTL 전압 레벨(RS-232)로 변환할 수 있습니다. 어댑터가 사용하도록 설계된 인터페이스(USB 또는 RS-232)에 연결합니다. 사용자 프로그램(예: Python 스크립트)에서 하드웨어 직렬 포트는 해당 Linux 장치를 참조하여 액세스 할 수 있습니다. /dev/serial0은 항상 기본 UART를 가리킵니다.
직렬 하드웨어 포트의 기본 UART는 UART 유형을 지정하여 액세스할 수도 있습니다. 예를 들어, RPi ¾에서 mini-UART는 기본 UART이므로 /dev/ttyS0은 직렬 TTL 포트의 기본 UART를 가리킵니다.
Raspberry Pi Zero에서 PL011은 기본 UART이므로 /dev/ttyAMA0은 직렬 TTL 포트의 기본 UART를 가리킵니다.
RPI의 USB 포트를 이용한 시리얼 UART 통신
RPi의 USB 포트에 연결된 기기들과 UART 프로토콜을 이용한 시리얼 통신도 가능합니다. RPI의 USB 포트에 연결된 장치가 CDC(통신 장치 클래스)로 식별되면 Linux 장치에 /dev/ttyAMC*로 표시됩니다(여기서 *는 장치 번호).
예를 들어 Arduino는 USB-to-USB 케이블을 통해 RPi에 연결된 경우 CDC 장치로 식별합니다. 다른 USB CDC 장치가 이미 RPi에 연결된 경우 이는 /dev/ttyAMC0 또는 /dev/ttyAMC1로 표시됩니다. UART 프로토콜을 사용하는 직렬 통신은 해당 Linux 장치(예: Arduino의 경우 /dev/ttyAMC0)를 사용하여 장치를 가리키면 장치와 함께 시작할 수 있습니다.
일부 장치에는 하드웨어 USB 인터페이스가 없고 대신 소프트웨어 전용 USB 스택이 있을 수 있습니다. 이러한 장치가 RPI의 USB 포트에 연결되면 Linux 장치에 /dev/ttyUSB*로 표시됩니다(여기서 *는 장치 번호).
RPi에서 사용 가능한 직렬 포트는 셸에서 ls /dev/ 명령을 실행하여 나열할 수 있습니다. 나열된 장치에 /dev/ttyAMC0, /dev/ttyAMC1 등과 같은 Linux 장치가 포함되어 있으면 CDC 클래스 USB 장치입니다. 목록에 /dev/ttyUSB0, /dev/ttyUSB1 등과 같은 Linux 장치가 포함되어 있으면 소프트웨어 전용 USB 스택을 통해 연결된 USB 장치입니다.
RPI의 Bluetooth 및 WLAN 포트를 사용한 직렬 UART 통신
기본적으로 보조 UART는 Raspberry Pi의 WLAN/Bluetooth 결합 커넥터에 연결됩니다. UART 프로토콜을 사용하여 Bluetooth 또는 WLAN을 통해 직렬 통신을 하려면 Linux 장치 /dev/serial1을 가리킬 수 있습니다. 또는 /dev/ttyS0 또는 /dev/ttyAMA0 또는 보조 UART가 사용자 프로그램에서 지정될 수 있습니다(Python 스크립트에서와 같이).
RPi의 이더넷 포트를 사용한 직렬 UART 통신 이더넷 포트를
통해 연결된 UART 프로토콜을 사용하는 직렬 통신에 보조 UART를 사용할 수 있습니다. 보조 UART는 기본적으로 Bluetooth/WLAN 커넥터에 연결되어 있으므로 /boot/config.txt 파일에 다음 플래그를 추가하여 Bluetooth 연결을 비활성화해야 합니다.
dtoverlay=pi3-disable-bt
다음으로 이 플래그를 제거하여 /boot/cmdline.txt 파일에서 직렬 포트의 커널 사용을 비활성화해야 합니다.
console=serial0,115200
이제 보조 UART는 pppd(Point-to-Point Protocol Daemon)와 같은 도구를 사용하여 RPI의 이더넷 포트를 통한 직렬 UART 통신에 사용할 수 있습니다.
하드웨어 직렬 포트와 USB
대부분의 임베디드 전자 모듈 및 센서는 마이크로컨트롤러 및 임베디드 컴퓨터와의 인터페이스를 위해 TTL UART 포트를 사용합니다. 따라서 하드웨어 직렬 포트(GPIO 헤더를 통한 직렬)는 임베디드 센서 및 모듈을 RPi와 인터페이스 하는 데 유용합니다.
범용 컴퓨팅 장치는 RPi의 USB 포트를 사용하여 USB-USB 케이블을 통해 Raspberry Pi에 직접 연결할 수 있습니다. 이러한 장치에는 다음이 포함됩니다.
- 노트북, PC 또는 워크스테이션
- USB-CDC 장치
- USB-HID 장치
- 소프트웨어 전용 USB 스택 장치
컴퓨팅 장치는 적절한 USB 직렬 어댑터 또는 USB 직렬 브리지 보드를 사용하여 RPi의 하드웨어 직렬 포트(GPIO 헤더에 있음)와 인터페이스 할 수도 있습니다.
따라서 직렬 하드웨어 포트는 임베디드 애플리케이션에서 가장 유용하며 USB 또는 RS-232 인터페이스 장치와의 인터페이스에도 사용할 수 있습니다.
다음 포스팅에서 시리얼 UART 통신을 위한 라즈베리파이의 시리얼 하드웨어 포트를 사용에 대해 논의할 것입니다. 라즈베리파이의 직렬 TTL 포트와 직렬 USB 어댑터를 사용하여 노트북/PC와 직렬 읽기/쓰기 통신을 설정하는 방법을 알아봅니다.
고생하셨습니다. ^^
'개발자 > 라즈베리파이4' 카테고리의 다른 글
라즈베리파이 4 IoT(사물인터넷) 4강 개발환경 2 (0) | 2021.11.30 |
---|---|
RPi Python 프로그래밍 19: RPi의 TTL 포트에서 직렬 UART 통신 (0) | 2021.11.30 |
라즈베리파이 4 IoT(사물인터넷) 3강 개발 환경 1 (0) | 2021.11.26 |
라즈베리파이 파이선 프로그래밍 18 – Raspberry Pi의 TTL 포트에서 직렬 UART 통신 (0) | 2021.11.26 |
라즈베리파이 4 IoT(사물인터넷) 2강 IoT 기반기술 (0) | 2021.11.23 |
라즈베리파이 Python 프로그래밍 16: 아날로그 출력 및 소프트웨어 PWM (0) | 2021.11.22 |
라즈베리파이 4 IoT(사물인터넷) 1강 IoT와 웨어러블 디바이스 (0) | 2021.11.20 |
라즈베리파이 Python 프로그래밍 15: 푸시 버튼 및 디지털 입력 인터페이스 (0) | 2021.11.19 |
더욱 좋은 정보를 제공하겠습니다.~ ^^