본문 바로가기

IT Tech/Computing

Serial 통신, UART, I2C, SPI 개요(펌)

Serial Communication 개요.
한번에 한 바이트 또는 그 이상의 데이터를 한꺼번에 주고 받는 병렬 통신과 달리 직렬 통신은 데이터를 한 비트씩 순차적으로 주고 받는 통신 방법이다병렬 통신과 비교할 때 직렬 통신은 상대적으로 속도는 느리지만 통신에 필요한 선의 수가 적어서 구조가 단순하다는 장점을 가지고 있다두세 가닥의 선만으로 양방향 통신이 가능하므로 직렬 통신을 사용하는 IC는 병렬 통신을 사용하는 IC에 비해 핀의 수가 적다이런 이유로 DAC, ADC, EEPROM 등의 매우 다양한 종류의 장치들이 직렬 통신을 사용하여 마이크로프로세서와 데이터를 주고 받는다또한 대부분의 마이크로컨트롤러는 두 가지 이상의 직렬 통신 인터페이스를 가지고 있다.
 
직렬 통신은 데이터를 한 비트씩 순차적으로 보내기 때문에 어느 시점부터 어느 시점 까지가 한 비트인지 수신자가 정확하게 알아낼 방법이 필요하다아래 그림을 보자.
 



 
신호의 상태를 어떤 시점에서 검사하느냐에 따라 동일한 신호가 여러 다른 값으로 해석될 수 있다송신 측에서 보낸 데이터를 수신한 쪽에서도 같은 값으로 인식하려면 송신자가 데이터를 보낼 때 사용한 시간 정보를 수신자도 알아야 한다송신자와 수신자는 서로 동기를 맞추어야 한다수신자가 송신자와 상호 동기를 맞추기 위한 한가지 방법은 동기를 위한 Clock 신호를 추가로 사용하는 것이다이런 용도의 Clock 신호 사용 여부에 따라서 직렬 통신을 크게 동기 (synchronous) 통신과 비동기 (asynchronous) 통신으로 구분할 수 있다.
 
동기 (Synchronous) 통신과 비동기 (Asynchronous) 통신
동기 통신은 데이터 전송을 위한 선 외에 송신자와 수신자의 동기를 위한 별도의 Clock 신호를 사용하는 통신 방법이다동기 통신에서 송신자와 수신자는 서로 공유하는 Clock 신호에 맞추어 데이터를 주고 받는다만일 송신자가 Clock 신호의 하강 Edge (falling edge)마다 한 비트씩의 데이터를 내보낸다면하강 Edge에서 다음 하강 Edge까지가 한 비트에 해당하므로 수신자는 데이터가 변하지 않고 안정된 값을 유지하는 구간예를 들어 상승 Edge에서 값을 읽어가면 된다.
 


 
동기를 위한 Clock 신호에 맞추어 서로 데이터를 교환하기 때문에 통신에 참여하고 있는 양측은 정확한 통신 속도에 대해 미리 약속할 필요가 없다. Clock 신호가 데이터 전송 시점을 알려주기 때문이다하지만 Clock 신호의 어떤 시점을 기준으로 송신자가 데이터를 보내는지즉 수신자는 Clock 신호의 어떤 Edge에서 데이터를 읽어야 하는지에 대해서는 상호간의 약속이 필요하다또한 정확한 통신 속도에 대해서는 미리 약속할 필요 없지만 최고 속도에 대한 제한은 있다너무 빠른 속도로 데이터를 보내면 수신자가 이를 제대로 수신할 수 없기 때문이다나중에 설명할 SPI I2C 프로토콜은 임베디드 시스템에서 가장 많이 사용되고 있는 동기 통신 규격이다.
 
반면에 비동기 통신은 동기를 맞추기 위한 별도의 Clock 신호 없이 데이터를 주고 받는 방법이다. Clock 신호가 없기 때문에 송신자는 한 바이트의 데이터를 전송하기 직전에 통신의 시작을 알리는 시작 비트 (start bit)를 먼저 보내 데이터의 전송이 시작된다는 것을 수신자에게 알린다시작 비트를 보낸 다음부터 데이터를 한 비트씩 보내고 마지막에는 통신의 끝을 알리는 정지 비트 (stop bit)를 보내 통신이 끝났음을 알린다시작 비트는 논리 0’이며 정지 비트는 논리 1’이다.
 
 

 
정지 비트가 논리 1’이므로 데이터 전송이 없는 상태에서 통신 선로는 논리 1’을 유지하고 있다그러므로 통신 선로의 상태가 논리 1’을 유지하고 있다가 논리 0’으로 바뀌면 수신자는 이것으로부터 새로운 데이터의 전송이 시작됨을 인식한다.
 
이와 같이 데이터를 전송할 때마다 시작과 끝을 알리는 시작 비트와 정지 비트를 추가로 보내기 때문에 동기용 Clock 없이도 데이터의 송수신이 가능하다하지만 이 경우에는 서로 정확한 통신 속도를 약속하고 있어야 한다통신의 시작을 뜻하는 시작 비트를 받으면 수신자는 이 때부터 미리 약속한 통신 속도에 맞추어 데이터를 한 비트씩 읽어 들이기 때문이다직렬 통신에서의 통신 속도는 보통 bps (bits per second)라는 단위로 표현하는데 이 단위는 초당 전송되는 비트 수를 나타낸다 bps의 속도로 통신할 것인가가 정해지면 한 비트의 시간 폭이 결정된다통신 속도를 알고 있어야만 시작 비트를 받은 수신자가 그 이후 데이터를 한 비트씩 읽어 들이는 속도를 결정할 수 있다. PC의 직렬 포트에 사용되는 RS-232 표준은 비동기 통신 프로토콜의 대표적인 예다.
 
동기 통신과 비동기 통신은 각각 장단점을 가지고 있다동기 통신과 달리 비동기 통신은 Clock 신호를 사용하지 않기 때문에 통신에 필요한 선의 수가 더 적다송신용 선과 수신용 선 두 가닥이 있으면 두 주체가 동시에 데이터를 주고 받는 양방향 통신즉 전이중 (full duplex) 통신이 가능하다반면에 통신 속도 측면에서는 동기 통신이 더 유리하다동기 통신에서는 동기를 위한 별도의 Clock 신호가 있으므로 데이터 길이의 제한 없이 한 바이트 이상의 데이터를 끊김 없이 연속해서 보낼 수 있다하지만 비동기 통신에서는 시작 비트와 정지 비트가 추가로 필요하므로 데이터만 연속해서 보낼 수 없다한 바이트의 데이터를 전송하기 위해서는 시작 비트와 정지 비트를 포함해서 적어도 10 비트를 전송해야 하므로 상대적으로 효율이 떨어진다.
 
이런 점 이외에도 동기 통신과 비동기 통신에는 또 다른 큰 차이가 있다비동기 통신을 사용할 때에는 통신에 참여하는 두 주체가 서로 대등한 관계에서 일대일 통신을 한다이런 구조에서는 양쪽 모두 원하는 때에 언제든지 데이터를 보낼 수 있다반면에 동기 통신에서는 두 주체 사이에 주종 관계가 있어 한쪽이 통신의 주도권을 가지는 Master, 다른 쪽은 Slave로 동작한다. Master가 통신에 필요한 Clock을 출력하며 SlaveMaster가 출력하는 Clock 신호에만 반응할 수 있다따라서 데이터의 전송 방향에 상관없이 항상 Master가 통신을 주도한다마이크로프로세서와 여러 주변 장치 (peripheral) 사이의 통신에는 이러한 Master-Slave 기반의 동기 통신이 많이 사용되는데 이 때 당연히 프로세서는 Master주변 장치는 Slave로 동작하게 된다
 
직렬 통신은 프로토콜이 다양하기 때문에 대부분의 마이크로컨트롤러는 두 가지 이상의 직렬 통신 인터페이스를 지원한다그 중에서도 UART, I2C, SPI는 가장 자주 사용되는 대표적인 예라고 할 수 있다.

 
UART의 개요
UART Universal Asynchronous Receiver/Transmitter의 머리글자로서 비동기 통신을 위한 전용 하드웨어를 뜻한다. UART가 없다면 비동기 통신 프로토콜을 프로그램으로 직접 구현해야 한다데이터를 송신하려면 프로세서가 타이머를 사용하여 미리 정한 직렬 통신 속도에 맞추어 병렬 데이터를 한 비트씩 출력 핀으로 내보내야 한다물론 시작 비트와 정지 비트도 함께 출력해야 한다수신의 경우는 조금 더 어렵다수신 핀의 상황을 계속 검사하거나 또는 인터럽트를 사용하여 시작 비트가 수신되는지 여부를 확인해야 한다그리고 일단 시작 비트의 수신이 확인되면 그때부터 정해진 통신 속도에 맞추어 한 비트씩 값을 읽어 저장해야 한다이런 작업은 어렵지는 않지만 매우 번거롭기도 하고 마이크로프로세서가 다른 일을 할 수 있는 시간을 뺏는 결과를 가져온다.
 
UART는 비동기 통신에 필요한 이런 직렬-병렬 데이터 변환 작업을 자동으로 해주는 하드웨어 장치이다그렇기 때문에 비동기 통신을 해야 한다면 UART가 꼭 필요하다고 할 수 있다. PC에는 16550이라는 이름의 UART IC가 사용되는데 이처럼 UART가 독립된 제품으로 판매되기도 하지만 거의 대부분의 마이크로컨트롤러는 내부에 하나 이상의 UART를 가지고 있다만일 마이크로컨트롤러가 가지고 있는 UART의 수보다 더 많은 비동기 통신 채널이 필요하다면 외부에 UART IC를 추가로 연결해서 사용하면 된다.
 
UART에는 적어도 네 개 정도의 레지스터가 포함되어 있으며 각 레지스터의 주소는 UART의 기본 주소 (base address)에 옵셋 (offset) 값을 더한 값으로 정의된다. CPU UART 레지스터에 값을 쓰거나 레지스터 값을 읽는 방법으로 간단하게 비동기 통신을 진행할 수 있다다음은UART의 동작에 반드시 필요한 레지스터들이다마이크로컨트롤러에 따라 이 레지스터들의 이름은 조금씩 다를 수도 있다.
 
 TxD (송신 데이터레지스터
UART로 송신할 데이터를 쓰기 위한 레지스터이다. CPU가 이 레지스터에 값을 기록하면 미리 정해둔 직렬 통신 속도 및 다른 여러 설정에 맞추어 그 값이 한 비트씩 직렬로 출력된다. TxD 레지스터에 어떤 값을 기록하면 이 시점부터 마지막 비트가 출력될 때까지 시간이 걸리므로 이전에 기록한 값의 송신이 완료되기 전에 TxD 레지스터에 새로운 값을 기록하면 안 된다이전 데이터의 송신이 완료되었는지 여부는 상태 레지스터를 읽어 확인할 수 있다.
 
 RxD (수신레지스터
수신용 핀으로 한 비트씩 입력되어 수신 완료된 데이터가 저장되는 레지스터이다상태 레지스터를 읽어서 새로운 데이터가 수신되었다는 것을 확인하면 CPU는 이 레지스터의 값을 읽으면 된다이 레지스터에 저장된 값은 다음 데이터가 수신되는 동안은 그대로 유지되지만 다음 데이터의 수신이 완료되는 순간 새로운 값으로 갱신된다따라서 데이터 손실을 막기 위해서는 다음 데이터의 수신이 완료되기 전까지는 CPU가 이 레지스터의 값을 읽어 저장해야 한다.
 
 제어 (control) 레지스터
UART의 동작에 필요한 여러 설정을 하기 위한 레지스터이다정지 비트의 길이패리티 (parity) 비트의 사용 유무통신에 사용할 패킷의 길이 등을 설정한다. UART를 동작시키기 전에 반드시 제어 레지스터를 적절하게 설정해야 한다.
 
 상태 (status) 레지스터
UART의 상태를 나타내는 레지스터이다상태 레지스터의 각 비트는 특정한 의미를 가지고 있다예를 들면수신 완료 (receive complete) 비트가 1이면 새로운 데이터가 수신되어 RxD 레지스터에 저장되어 있음을 뜻하며송신 완료 (transmit complete) 비트가 1이면 TxD에 저장한 값의 출력이 완료되었음을 뜻한다이 외에도 TxD 레지스터가 비어 있는지 여부를 알려주는 비트를 가지고 있기도 하다상태 레지스터의 각 비트는 인터럽트와 연결되어 있어서 인터럽트가 활성화되어 있다면 어떤 비트가 1로 설정되는 순간 해당 인터럽트 핸들러(interrupt handler)가 자동으로 호출된다.
 
 baud rate 설정 레지스터
직렬 통신의 속도인 보 (baud) 값을 설정하기 위한 레지스터이다여기에 설정한 통신 속도에 따라 직렬-병렬 변환 속도가 결정된다. baud 값은 통신에서의 변조율 (modulation rate)을 나타내는 단위이므로 baud rate는 초당 전송되는 비트의 수를 뜻하는 bps와는 의미가 다르다그러나 한 심볼 (symbol)이 한 비트에 해당할 때 baud 값과 bps 값은 같기 때문에 유선 통신에서는 흔히 bps와 구분 없이 사용되고 있다.
 
직렬 통신의 비트율 즉, baud rate가 정해지면 한 비트의 시간 폭이 결정된다예를 들어 통신 속도를 38,400 baud로 한다면 한 비트의 시간 폭은 1/38,400 초가 된다시작 비트와 정지 비트가 각 1 비트씩이라면 한 바이트의 데이터를 송신하는데 1/3,840 초가 걸린다사용자가 지정한 baud rate에 맞추어 UART가 직렬-병렬 데이터 변환을 하려면 타이머 (카운터)가 반드시 필요하다. baud rate에 비례하는 주파수를 가진 신호가 있어야 하기 때문이다. 8051 계열 마이크로컨트롤러에서는 내부 타이머 중 하나가 이 용도로 지정되어 있어 직렬 통신을 사용할 때 그 타이머는 다른 용도로 사용할 수 없다. AVR 마이크로컨트롤러의 경우에는 사용자가 프로그래밍 가능한 타이머 이외에 UART용의 전용 카운터가 따로 있다.
 
UART의 타이밍
구현 방법에 따라 조금씩 다르지만 많은 경우 UART는 사용자가 지정한 통신 비트율보다 16 배 높은 주파수의 내부 신호를 사용한다이 내부 신호는 일반적으로 CPU를 위한 오실레이터 입력을 카운터로 분주해서 만든다.
 
이 내부 신호의 주파수는 사용자가 설정한 통신 비트율보다 16 배 높기 때문에 데이터 한 비트의 시간 폭은 내부 신호의 16 Clock Cycle(cycle)과 같다데이터를 전송할 때에는 먼저 시작 비트를 출력하고 이 때부터 내부 신호 16 Clock Cycle마다 한 비트씩을 출력하면 된다. UART의 송신부만 생각한다면 통신 비트율의 16배나 되는 높은 주파수가 필요할 것 같지는 않다이렇게 높은 주파수의 신호가 필요한 것은 수신부 때문이다.
 



 
UART의 수신부는 수신 신호의 상태가 논리 1’에서 논리 0’으로 변하는 하강 Edge, 즉 시작 비트를 기다린다하강 Edge를 검출하면 UART는 이 때부터 카운터를 사용하여 내부 신호의 펄스 수를 세기 시작한다신호의 각 비트가 변하는 순간은 전압이 불안정하므로 UART는 가능하면 각 데이터 비트의 한 가운데에서 입력의 논리 값을 읽는 것이 안정적이다시작 비트가 검출된 시점부터 내부 신호의 8 Clock Cycle 지점이 시작 비트의 한 가운데에 해당하고 이 시점부터 매 16 Clock Cycle 시점이 각 데이터 비트의 한 가운데가 된다.
 
우선 시작 비트가 검출된 순간 이후 8 Clock Cycle 지점에서 시작 비트의 상태를 다시 검사한다만일 이 값이 논리 0’이 아니라면 UART는 이것이 글리치 (glitch) 의한 가짜 시작 비트 (spurious start bit)라고 판단하고 이를 무시한 다음 다시 시작 비트를 기다린다정상적인 시작 비트라고 판단되면 UART는 매 데이터 비트의 한 가운데 지점에서 신호의 상태를 세 번 검사한다즉 내부 신호의 7, 8, 9 번째 Cycle 시점에서 각 비트의 상태를 3번 읽어서 두 번 이상 검출된 논리 값을 그 비트의 값으로 판단한다물론 시작 비트의 상태 역시 내부 신호의 7, 8, 9 번째 Cycle 시점에서 세 차례 검사할 수도 있다이렇게 함으로써 UART는 잡음에 의한 영향을 줄여 통신 선로에서 발생할 수 있는 오류의 확률을 낮춘다.
 
UART의 동작에 필요한 내부 신호는 보통 CPU용 외부 오실레이터 입력을 분주해서 만드는데 송신부와 수신부가 사용하는 오실레이터 주파수가 다른 경우에는 UART의 송신 타이밍과 수신 타이밍이 정확하게 일치하지 않는다비동기 통신에서는 매 데이터마다 시작 비트를 가지고 있어서 시작 비트부터 매번 동기를 새로 맞추기 때문에 송신 비트율과 수신 비트율의 차이가 있다 하더라도 허용 가능한 범위를 초과하지 않으면 통신 오류가 발생하지 않는다그러면 허용 가능 주파수 차이의 한계에 대해 생각해보자.
 
앞에서 설명했듯이 UART의 수신부는 각 데이터 비트의 한 가운데에서 신호의 논리 값을 읽는 것이 바람직하다그런데 송신 비트율이 수신 비트율에 비해 높다면 수신부는 각 데이터 비트의 한 가운데 이후에 그 값을 읽게 된다반대로 송신부 비트율이 더 낮은 경우에 수신부는 각 비트의 한 가운데보다 이전에 값을 읽게 된다이 오차는 시작 비트부터 계속 누적되므로 이 정지 비트에서 가장 큰 타이밍 오차가 발생한다그렇기 때문에 정지 비트를 검출하는데 오류를 일으키지 않는 범위의 송·수신 주파수 차이는 비동기 통신에 문제를 야기하지 않는다.
 
정지 비트의 한 가운데는 정지 비트의 시작부터 8 Clock Cycle 시점인데 정지 비트의 상태를 검사하는 시점이 8 Clock Cycle에서 ±3 Clock Cycle 이내라면 현실적으로 타이밍 차이로 인한 오차가 생길 가능성은 거의 없다고 판단할 수 있다송신부와 수신부가 완전히 같은 주파수로 동작한다면 수신부의 내부 신호의 8 번째 Clock Cycle 시점이 각 비트의 한 가운데가 된다시작 비트에서부터 내부 신호의 펄스 수를 세면정지 비트의 한 가운데는
(16 Clock Cycle / 비트) x (1 시작 비트 + 8 데이터 비트 + ½ 정지 비트) = 152 Clock Cycle
이 된다. 따라서 152 Clock  ±3 Clock 이내의 오차까지 허용 가능하므로 이를 백분율로 따지면 ±3/152 ±2 %에 해당한다.
 
결과적으로 비동기 통신에 있어 송·수신 비트율의 차이가 ±2 % 이내라면 이로 인한 문제는 거의 발생하지 않는다이 값은 8 비트 단위의 데이터 전송을 가정하고 계산한 값이며 전송 단위가 9 비트 이상이라면 허용 가능한 오차의 한계는 더 감소한다또한 송·수신 통신 비트율 차이를 계산하면서 단순히 양쪽에서 사용된 오실레이터의 명목상 주파수만을 고려해서는 안 된다오실레이터는 그 자체로 어느 정도의 주파수 오차를 가지고 있으며 동작 온도에 따라서도 조금씩 출력 주파수가 변하기 때문이다.
 
비동기 통신에서 사용되는 비트율의 대표적인 예로 37400 bps, 57600 bps, 115200 bps 등을 들 수 있다마이크로컨트롤러에 7.3728 MHz22.1184 MHz와 같은 특이한 주파수의 오실레이터를 연결하는 경우를 종종 볼 수 있는데 그 이유는 37400 bps, 57600 bps, 115200 bps 등의 비트율을 얻기 위해서는 이러한 비트율의 정수배 주파수가 필요하기 때문이다특히 8051 계열 프로세서가 이런 주파수의 오실레이터를 자주 사용하는데 그것은 8051에서는 (통신 비트율 x 16)의 정수배 주파수가 필요하기 때문이다.
 
RS-232 표준
RS-232 표준은 비동기 직렬 통신 프로토콜의 가장 대표적인 예이다지금까지의 비동기 통신에 관한 설명은 RS-232 표준의 일부이다요즘은USB 인터페이스가 많이 사용되고 있어서 PC에 직렬 포트가 아예 없는 경우도 많지만 아직도 RS-232 표준은 여전히 많이 사용되고 있다임베디드 소프트웨어 개발 과정에서 PC와 임베디드 시스템을 RS-232 인터페이스로 연결하고 UART를 간단한 디버거로 활용하는 경우는 매우 흔하다.
 
RS-232 표준은 비동기 직렬 통신에 필요한 전기적인 신호 특성 (전압타이밍 등)과 기계적 특성 (커넥터 모양핀 배치등 모든 사양을 규정하고 있는 미국 Electronic Industries Association (EIA)라는 단체가 정한 표준이다. PC의 뒤쪽에 나와 있는 직렬 포트용 DB-9 커넥터의 모양과 핀 배치도 이 표준을 따른다송신 신호 (TxD)와 수신 신호 (RxD) 이외에도 다른 용도의 여러 신호들이 이 표준에 정의되어 있다그러나 데이터 흐름 제어 (flow control)나 반송파 검출 (carrier detection) 등의 다른 기능은 사용하지 않고 순수하게 통신만 하겠다면 TxD RxD 두 신호로 충분하다.
 
UART가 있으면 비동기 통신이 가능하지만 UART의 송수신 핀을 PC의 직렬 포트에 바로 연결할 수는 없다. RS-232 표준에서 규정하고 있는 전압 레벨은 TTL 호환 (TTL compatible)이 아니기 때문이다. RS-232 표준은 논리 1’에 해당하는 전압의 범위를 -3 V ~ -15 V로 논리 0’에 해당하는 전압의 범위를 +3 V ~ +15 V로 규정한다이런 전압은 일반 디지털 회로에서 사용되는 범위를 벗어나기 때문에 RS-232 표준을 따르기 위해서는 0 V ~ 3 V (또는 3.3 V 또는 5 V) 범위의 신호를 RS-232 레벨 신호로 변환하고 또 그 반대 방향으로도 전압을 변환해 주는 전용 회로가 필요하다이런 역할을 하는 IC RS-232 트랜시버 (transceiver)라고 한다. Maxim사의 MAX232라는 제품이 그 대표적 예이다.
 


RS-232 표준에 따른 논리 0과 논리 1’의 전압 차이는 최소 6 V에서 최대 30 V이다따라서 일반적인 디지털 회로의 신호와 비교하면 RS-232 표준을 따르는 신호는 잡음 여유가 매우 크다. RS-232 규격에 따르면 송신측과 수신측 사이의 통신 선로의 길이는 최대 15 m에 이른다만일RS-232 표준을 반드시 따라라 하는 것이 아니며 송신부와 수신부가 가깝다면 RS-232 트랜시버를 사용하지 않고 UART끼리 직접 연결하면 된다.

 
I2C의 개요
I2C (Inter-Integrated Circuit) 버스는 마이크로프로세서와 저속 주변 장치 사이의 통신을 위한 용도로 Philips에서 개발한 규격인데 두 가닥의 선을 사용하므로 TWI (Two Wire Interface)라고도 불리고 있다특허권 때문인지 잘 모르겠으나 Philips 이외의 회사들은 거의 대부분 TWI라고 부른다. I2C 버스는 양방향 오픈 드레인 선인 SCL (serial clock) SDA (serial data)로 이루어져 있으며 Master-Slave 형태로 동작한다. SCL은 통신의 동기를 위한 Clock용 선이고 SDA는 데이터용 선이다. Master SCL로 동기를 위한 Clock을 출력하며 Slave SCL로 출력되는 Clock에 맞추어 SDA를 통해 데이터를 출력하거나 입력 받는다단지 SDA 한 선으로만 데이터를 주고 받기 때문에 I2C 버스는 반이중 (half duplex) 통신만 가능하다. SCL 선과 SDA 선은 모두 오픈 드레인므로 두 선에는 각각 풀업 저항을 연결해 주어야 한다.
 
다음 그림은 I2C MasterSlave들 사이의 연결을 보여주고 있다.
 


모든 I2C MasterSlave 장치들의 SCL은 서로 연결되며 SDA 또한 서로 연결된다모든 장치들이 SCL SDA를 각각 공유하고 있으므로 MasterSlave를 개별적으로 지정하기 위한 방법이 있어야 한다. I2C 버스에서 Master가 각 Slave를 구분하는 수단은 Slave의 주소이다모든 I2C Slave 장치들은 7 비트의 고유한 주소를 가지고 있으며 Master는 주소로 원하는 Slave를 지정한다주소의 길이가 7 비트이므로 Master는 최대 128 개의 Slave 장치들과 연결될 수 있다물론 Slave 장치들의 주소는 모두 달라야 한다.
 
앞의 그림에는 Master가 하나 밖에 없지만 I2C 버스에 두 개 이상의 Master들이 존재할 수도 있다버스에 연결된 장치의 수가 아무리 많아도 한 순간에는 오직 하나의 Master와 하나의 Slave만이 통신할 수 있다현재 통신을 진행하고 있는 Master가 버스 소유권을 가지고 있다두 개 이상의 Master가 있는 경우에 현재 버스의 소유권을 가지고 있는 Master Master와 통신을 진행하고 있는 Slave 장치 이외의 나머지 장치들은 이들의 통신을 방해하지 않아야 한다.
 
SCL SDA는 모두 오픈 드레인이므로 모든 장치들의 SCL SDA는 각각 와이어드 AND로 연결 되어 있다와이어드 AND 연결에서는 어느 한 장치라도 0’을 출력하면 해당 신호의 상태는 논리 0’이 된다만일 SCL이나 SDA에 연결되어 있는 어떤 장치가 논리 0’을 출력한다면 다른 장치가 그 신호의 상태를 논리 1’로 만들 수 있는 방법은 없다통신에 참여하지 않은 장치가 SCL이나 SDA 0’을 출력하면 Master가 정상적으로 통신을 진행할 수 없다이것은 I2C 버스에 연결되어 있지만 현재 통신에 참여하지 않고 있는 장치들은 모두 자신의 출력을 플로우팅 상태로 유지해야 한다는 것을 뜻한다.
 
통신이 진행되지 않는 상황에서 모든 장치의 출력은 플로우팅 상태이므로 SCL SDA의 상태는 모두 논리 1’이다이 상황에서 I2C 버스의 사용을 원하는 Master SCL SDA로 시작 조건을 출력하며 버스 소유권을 주장하고 통신을 시작할 수 있다두 신호의 상태가 모두 논리 1’이 아니라면 현재 다른 Master가 버스 소유권을 가지고 통신을 진행 중에 있다는 것을 뜻하므로 그 Master가 버스 소유권을 반납할 때까지는 다른 Master가 새로운 통신을 시작해서는 안 된다.
 
다음 그림은 I2C 프로토콜의 시작 조건정지 조건그리고 데이터 안정 구간을 보여주고 있다.
 


I2C 프로토콜에서 SCL 0’인 구간에서는 SDA의 상태 변화가 허용되지만 SCL 1’인 구간에서는 SDA는 안정된 논리 상태를 유지해야 한다. MasterSlave로 데이터를 출력할 때 SCL 0’인 구간에서 SDA의 비트 전환을 하며 SCL 1’인 구간에서는 SDA의 상태를 그대로 유지한다. Slave가 데이터를 출력하고 Master가 그 데이터를 읽을 때에도 마찬가지이다그래서 SCL 1’인 구간은 데이터가 안정한 구간이다.
 
I2C 프로토콜에서 SCL 1’을 유지하고 있는 구간에서 SDA의 상태가 변하는 것은 일반 데이터 전송이 아닌 특별한 조건을 의미한다. SCL 1’인 동안 SDA 1’에서 0’으로 바뀌는 것을 시작 조건 (start condition, S)이라고 하며 SCL 1’인 동안 SDA 0’에서 1’로 바뀌는 것을 정지 조건 (stop condition, P)이라고 한다. I2C 통신을 원하는 Master SCL SDA가 모두 논리 1’일 때 SDA의 상태를 0’으로 바꾸어 시작 조건을 출력하며 다른 장치들에게 통신의 시작을 알린다마찬가지로 통신을 끝낼 때에는 SCL 1’인 동안 SDA 0’에서 1’로 바꾸어 정지 조건을 출력하며 버스 소유권의 반납을 다른 장치에게 알린다.
 
I2C의 패킷 형식
다음 그림은 I2C 버스에서 사용되는 데이터 패킷의 형식을 보여준다. ACK을 포함한 9 비트가 I2C 규격에서 통신의 기본 단위가 된다.
 


Master SCL SDA가 모두 1’인 상태에서 SDA 0’으로 바꾸어즉 시작 조건을 출력하면서 통신의 시작을 알린다시작 조건 이후부터는SCL의 상태가 0’인 구간에서만 SDA의 논리 값이 바뀐다. Master SCL로 출력하는 Clock에 동기를 맞추어 SDA로는 데이터가 MSB부터 한 비트씩 출력된다. SCL은 항상 Master가 출력하는 신호이지만 SDA는 현재의 동작이 Master의 읽기냐 쓰기냐에 따라 Master의 출력일 수도 Slave의 출력일 수도 있다.
 
비트 데이터가 8 Clock Cycle 동안 SDA로 출력되면 그 데이터를 수신한 쪽에서 9 번째 Clock에 맞추어 그 8 비트 데이터의 수신 여부를 확인해 주는 ACK 비트를 출력한다다시 말해서 ACK 비트는 직전의 8 비트 정보를 수신한 쪽에서 그 정보의 송신자에게 직전 8 비트 정보에 대한 수신 여부를 확인하는 값이다. ACK 비트가 0’이면 정상 수신을 나타내며 ACK 비트가 1’이면 (항상 그런 것은 아니지만정상 수신이 아님을 나타낸다값이 0’인 ACK 비트와 구분하기 위하여 값이 1’인 ACK 비트를 NACK (no acknowledgement)라고 부르기도 한다.
 
만일 Master SDA 8 비트 정보를 출력했다면 그 정보를 수신한 Slave 9 번째 Clock SDA ACK 비트를 출력하여 Master에게 수신 결과를 알린다이 때 Master ACK 비트를 받으려면 9 번째 Clock Cycle 동안 자신의 SDA 출력을 1’로 유지하고 있어야 한다반대로 SDA로 출력된 8 비트 정보가 Slave의 출력이라면 그것을 수신한 Master 9 번째 Clock에서 ACK 비트를 출력한다이 때 Master ACK 비트를 받기 위해 Slave는 자신의 SDA 출력을 1’로 유지하고 있어야 한다.
 
비트 정보와 이어지는 ACK 비트의 전송이 끝난 다음에는 Master가 정지 조건을 출력할 수도 있고 시작 조건을 다시 출력할 수도 있으며 다음 바이트 전송이 이어질 수도 있다다음 동작은 현재 진행 중인 동작이 무엇인가에 따라 달라진다.
 
I2C의 주소 지정 형식
모든 I2C Slave 장치는 7 비트의 고유한 주소를 가지고 있으며 Master는 이 주소를 사용하여 상대 Slave 장치를 지정한다다음 그림은 MasterSlave의 주소를 지정하고 데이터를 주고 받는 방법에 대한 설명이다.
 


먼저 Master는 시작 조건에 이어서 자신이 원하는 Slave 7 비트 주소를 출력한다버스에 연결되어 있는 모든 Slave 장치들은 SDA 선을 계속 감시하면서 Master가 출력한 주소가 자신의 주소와 일치하는지 여부를 검사한다만일 Master가 출력한 주소가 어떤 Slave의 주소와 같으면 그 Slave ACK 비트에 0’을 출력하여 Master에게 응답한다. Master가 출력한 주소를 가진 Slave가 없으면 아무도 ACK 비트로 0’을 출력하지 않으므로 ACK 비트의 상태는 1’을 유지하여 Master NACK을 받게 된다.
 
Master ACK을 받으면 이것은 자신이 출력한 주소를 가진 Slave가 응답했다는 뜻이므로 Master는 다음 단계를 진행한다반면에 Master NACK을 받으면 이것은 자신의 호출에 응답하는 Slave가 없다는 것을 뜻하므로 Master가 더 이상 할 수 있는 일은 없다. Master는 정지 조건을 출력하여 현재의 상황을 종료하고 통신을 다시 시작해야 한다.
 
Slave 주소 7 비트 다음에 오는 8 번째 비트는 다음 동작이 Master의 읽기인지 쓰기인지를 가리킨다. Master가 이 비트로 0을 출력했다면 이것은 Master 쓰기임을 뜻하므로 Slave 주소 다음의 1 바이트 데이터는 Master의 출력이다이 데이터는 앞서 주소가 지정된 Slave를 위한 것이므로 그 Slave가 이 값을 읽어 들인다반면에 Slave 주소 7 비트 다음에 오는 8 번째 비트가 1 이면 이것은 다음 동작이 Master의 읽기라는 것을 의미한다그러므로 Master에 의해 주소가 지정된 Slave ACK을 응답한 후 이어서 Master에게 보낼 데이터를 출력한다.
 
주의할 것은 Slave 주소는 7 비트이지만 패킷의 상위 7 비트로 정렬되고 마지막에 R/W 비트가 LSB 위치에 추가된다는 것이다그렇기 때문에 Slave의 주소를 왼쪽으로 한 비트 쉬프트 시킨 후의 8 비트 값을 Slave의 주소라고 생각하는 것이 더 편할 수도 있다예를 들면DS1037이라는 RTC 칩의 I2C 주소는 1101000b으로 고정되어 있다 DS1037 I2C 주소는 0x68이다. DS1037에 데이터를 기록해야 할 때 Master I2C 버스로 시작 조건을 출력한 다음 11010000b을 출력한다. DS1037의 데이터를 읽고자 한다면 Master I2C 버스로 시작 조건을 출력한 다음 11010001b을 출력한다그러므로 8 비트 값인 0xd0 DS1037의 쓰기 주소, 0xd1 DS1037의 읽기 주소로 생각할 수도 있다.
 
I2C 버스 규격은 I2C 버스의 전기적 특성 및 타이밍과 함께 앞에서 설명한 시작 조건정지 조건주소 지정 방법 등에 대해서만 규정하고 있다구체적인 통신 방법MasterSlave의 주소를 출력한 다음 정지 비트를 출력할 때까지 주고 받는 데이터의 바이트 수, Slave의 내부 레지스터 주소 지정 방법 등은 Slave 장치에 따라 달라진다매우 다양한 종류의 I2C Slave 장치가 있으니 여러 가지 다양한 방법이 있을 수 있다.
 
대부분의 마이크로컨트롤러는 I2C 인터페이스를 지원한다그렇기 때문에 UART를 사용할 때와 비슷하게 I2C 관련 몇 개의 레지스터를 설정한 후 레지스터 읽기/쓰기를 통해 간단하게 I2C 통신을 실행할 수 있다마이크로컨트롤러가 I2C 인터페이스를 지원하지 않으면 프로그램을 통해 비교적 쉽게 I2C 프로토콜을 구현할 수 있다·수신 타이밍을 정확하게 맞추어야 하는 비동기 통신과 달리 Master가 출력하는 Clock에 맞추어 모든 동작이 이루어지므로 타이밍에 관련된 어려움이 특별히 없기 때문이다.
 
I2C 통신의 예
직렬 EEPROM, ADC, DAC, RTC 등을 포함한 다양한 매우 장치들이 I2C 인터페이스를 지원하고 있다. I2C Slave 장치와 통신을 하려면 그 Slave의 데이터쉬트를 참고하여 구체적인 통신 방법을 이해해야 한다다음 그림은 24LC64라는 64 Kbit 직렬 EEPROM의 내부 데이터를 읽기 위한 여러 방법 중 하나이다.
 
 


24LC64의 주소는 1010A2A1A0b로 정해져 있다 4 비트는 1010로 고정되어 있지만 뒤의 3 비트 A2A1A0는 사용자가 임의로 바꿀 수 있다주소의 마지막 3 비트를 사용자가 조절할 수 있도록 24LC64는 이 3 비트에 각각 대응되는 3 개의 입력 핀 A2, A1, A0을 가지고 있다주소의 일부를 사용자가 정하도록 만든 것은 24LC64에 여러 가지 다른 주소를 부여할 수 있도록 하기 위한 것이다만일 24LC64의 주소가 완전히 고정되어 있다면 I2C Master가 구동할 수 있는 24LC64 1 개뿐이다.
 
위의 그림은 24LC64의 저장된 값을 특정 주소부터 연속으로 읽는 방법이다맨 먼저 Master는 시작 조건을 출력한 다음 24LC64 7 비트 주소를 출력하고 8 번째 비트로 0’을 출력하여 다음 동작이 쓰기라는 것을 알린다. Master가 지정한 주소와 동일한 주소를 가진 24LC64가 있다면 그 IC ACK을 출력하여 Master에게 응답한다. ACK을 받은 Master는 이어서 24LC64의 저장 공간 중에서 자신이 원하는 주소를 MSB부터 연속해서 출력한다. 24LC64의 저장 용량은 64 Kbits,  8 K 바이트이므로 내부 주소 지정을 위해서는 13 비트의 주소 정보가 필요하다그러므로 Master는 두 번에 걸쳐 주소를 출력한다매 바이트를 받을 때마다 24LC64Master에게 ACK을 보낸다.
 
24LC64 내부의 주소를 출력한 후 ACK을 받으면 Master는 시작 조건과 Slave 주소를 다시 한 번 더 출력한다그런데 이번에는 Master24LC64의 데이터를 읽을 차례이므로 7 비트 Slave 주소 다음에 오는 8 번째 비트는 1’로 설정한다. 24LC64가 다시 Master에게 ACK으로 응답하면 그 다음부터 Master 24LC64가 출력하는 데이터를 연속해서 읽는다. 24LC64의 출력을 1 바이트 받을 때마다 Master ACK을 출력하여 이를 24LC64에게 알린다. ACK을 받은 24LC64는 내부에서 주소를 1 증가시키고 새로운 주소의 데이터를 읽어서 다음 SCL Clock에 맞추어 출력하게 된다데이터를 연속해서 수신한 Master는 자신이 원하는 마지막 데이터를 받으면 이번에는 NACK을 출력하고 이어 정지 조건을 출력하여 통신을 끝낸다.
 
위의 예는 I2C 통신을 사용하는 24LC64를 사용하기 위한 많은 방법들 중 하나일 뿐이다. I2C 인터페이스를 가진 장치마다 사용법이 다르기도 하거니와 한 장치에서도 명령의 종류에 따라 다양한 방법이 있을 수 있다.
 
I2C의 장·단점
I2C 버스의 가장 큰 장점으로 Slave 장치의 수에 관계 없이 두 가닥의 선만으로 MasterSlave 사이의 양방향 통신이 가능하다는 것을 들 수 있다두 개 이상의 Master를 사용할 수 있다는 사실은 I2C 버스가 가진 또 다른 장점이다.
 
반면에 I2C 버스의 양방향 특성은 오픈 드레인 구조에 기반을 두고 있으므로 근본적으로 동시 양방향 통신이 불가능하고 통신 속도를 높이기 어렵다표준 모드에서 I2C 통신의 최대 속도는 100 kHz이며 고속 모드에서는 최고 400 kHz까지 가능하다다른 동기 통신 프로토콜예를 들어 뒤에서 설명할 SPI와 비교하면 매우 낮은 속도이므로 I2C 버스는 저속 주변 장치와의 데이터 통신이나 주변 장치의 동작 모드 설정 등의 용도로 많이 쓰인다동작 모드 설정은 사용 빈도가 높지 않기 때문에 낮은 속도가 별 문제가 되지 않는다.
 
I2C 인터페이스를 사용하는 제품의 수는 무척 많은 반면 Slave의 주소는 7 비트로 그 길이가 제한되어 있어서 다수의 Slave 장치를 사용할 때 Slave 주소가 충돌할 가능성이 있다이런 문제에 대한 해결책으로 Slave 주소의 하위 2 ~ 3 비트를 사용자가 임의로 설정할 수 있는 제품들이 많기는 하지만 주소가 7 비트로 제한되어 있어서 근본적인 해결책이 될 수는 없다.

 
SPI의 개요
SPI (Serial Peripheral Interconnect) 버스는 Motorola에 의해 개발된 전이중 (full duplex) 통신이 가능한 동기 통신 규격이다. I2C와 마찬가지로 Master Slave 방식으로 동작하며 Master가 동기를 위한 클럭을 출력한다 SPI Slave 장치는 chip enable (/CE) 입력을 가지고 있으며 이 입력이 활성화되었을 때에만 동작한다따라서 Master는 여러 개의 slave select (SS) 선을 Slave들의 /CE에 연결하고 한 순간에 하나의 Slave만 선택하는 방법을 사용하여 두 개 이상의 Slave 장치들을 구동할 수 있다. SPI의 통신 속도는 최고 70 MHz에 이르기 때문에 I2C에 비해 훨씬 빠르다.
 
다음 그림은 SPI 버스를 통해 Master가 한 개의 Slave와 일대일로 연결된 상황을 보여준다.
 


그림에 표시된 4 개의 신호는 SPI 버스에서 정의된 신호이다.
 
 SCLK : Serial Clock. Master가 출력하는 동기용 클럭
 MOSI : Master Output Slave Input. Master의 출력이며 Slave에게는 입력
 MISO : Master Input Slave Output. Slave의 출력이며 Master에게는 입력
 SS : Slave Select. Master의 출력으로 Slave를 선택하기 위한 신호
 
SCLKMaster가 출력하는 클럭 신호이다. SCLK를 기준으로 MasterSlave 사이의 데이터 교환이 진행된다. MOSIMaster의 출력으로 Slave로 정보를 보내기 위한 선이다반대로 MISOSlave의 출력으로 MasterSlave의 정보를 받기 위한 선이다앞의 그림에서 보듯이 MasterSlave MOSI끼리 서로 연결되며 MISO끼리 서로 연결된다. SSMasterSlave를 선택하기 위한 Master의 출력으로 Slave /CE 입력에 연결된다. Slave /CE 입력이 0’인 동안에만 활성화된다.
 
통신을 진행하기 위해서 Master는 우선 SS 0’을 출력하여 해당 Slave를 활성화시킨다그런 다음 Master SLCK로 동기를 위한 클럭을 출력하는데 이 클럭에 맞추어 MOSI로 데이터를 한 비트씩 내보낸다이와 동시에 Master는 자신이 출력하는 클럭에 맞추어 MISO를 한 비트씩 읽는다다시 말해서 SPI Master는 자신의 출력인 SCLK에 맞추어 MOSI로 데이터를 내보내며 동시에 MISO로는 데이터를 수신한다. SPI 버스는 언제나 양방향 통신을 진행한다. SCLK에 맞추어 MOSI로 데이터를 출력하는 동안 MISO로는 데이터가 수신된다수신되는 데이터는 상황에 따라 의미가 있는 값일 수도 있고 쓰레기 값일 수도 있다마찬가지로 Slave의 데이터를 읽기 위하여 SLCK에 맞추어 MISO로 입력을 받는 동안 MOSI로는 데이터가 출력된다.
 
보통 SPI 통신은 8 비트 단위로 진행되지만 12 비트나 16 비트 또는 그 이상의 길이가 한 단위가 될 수도 있다비트 전송 순서에 대한 규정은 없다데이터의 전송은 MSB부터 시작될 수도 있고 LSB부터 시작될 수도 있다데이터를 연속 전송하는 경우 한 단위의 데이터를 보낼 때마다SS 신호를 매번 인가할 수도 있지만 SS 신호를 0’으로 설정한 후 모든 데이터를 다 보낼 때까지 이 상태를 유지하고 있다가 데이터의 전송이 끝났을 때 SS 1’로 바꿀 수도 있다. SPI 규격은 이런 부분까지 규정하고 있지 않으며 MasterSlave 사이의 약속에 따라 결정된다. SPI Slave 장치의 용도와 특성에 따라 사용 방법이 다르므로 Slave 장치의 데이터쉬트를 반드시 확인해야 한다.
 
어떤 마이크로컨트롤러는 설정된 전송 단위에 맞추어 데이터 전송 때마다 자동으로 SS 신호를 출력해 주는 기능을 가지고 있다. ATMEL사의ARM7 기반 AT91SAM7S 계열 마이크로컨트롤러가 그 예이다데이터 전송 단위를 16 비트로 설정했다면 SPI Master SCLK 신호를 출력하기 전에 자동으로 SS 신호를 0’으로 내리고 데이터가 출력되는 동안 이 상태를 유지하다 전송이 끝나면 이 신호를 다시 1’로 올려준다이런 용도로 사용할 수 있는 SS 핀이 여러 개 있어서 사용자가 선택할 수 있다이런 기능이 있으면 정해진 길이의 데이터를 반복해서 출력하는 경우예를 들면 주기적으로 DAC에 값을 전송하는 경우에 매우 편리하다이런 기능이 없는 마이크로컨트롤러의 경우에는 사용자가 프로그램을 통해 수동으로 SS 신호를 제어해야 한다. AVR 마이크로컨트롤러는 이 기능을 지원하지 않으므로 GPIO 핀을 Slave 선택용으로 정하고 수동으로 그 신호를 제어해야 한다.
 
SPI 모드 (mode)
SPI MasterSlaveMaster의 출력인 SCLK에 맞추어 데이터를 한 비트씩 교환한다그런데 클럭에 동기를 맞추는 방법은 한 가지만 있는 것이 아니다클럭이 출력되고 있지 않은 상황에서 클럭의 기본 값은 0’일 수도 있고 1’일 수도 있다그리고 MasterSlave가 매 클럭의 첫 번째 Edge에서 데이터를 읽을 수도 있고 매 클럭의 두 번째 Edge에서 데이터를 읽을 수도 있다앞의 특성을 클럭의 극성 (polarity)이라고 하고 뒤의 특성을 클럭의 위상 (phase)이라고 한다클럭의 극성과 위상의 조합에 따라 모두 4 가지 방법이 사용 가능하다. SPI Slave가지 가능한 방법 중 한 가지를 사용하도록 만들어지고 Master 4 가지 방법을 모두 지원해야 한다.
 
AVR 마이크로컨트롤러의 SPI 제어 레지스터에는 CPOL CPHA라는 비트가 있는데 이 비트의 설정에 따라 출력되는 클럭의 극성과 위상이 달라진다다른 마이크로컨트롤러도 이와 같거나 비슷한 이름의 비트를 가지고 있다. CPOL 비트가 0이면 클럭의 기본 상태가 0’이며 이 비트가 1이면 클럭의 기본 상태는 1’이다그리고 CPHA 비트가 0이면 매 클럭의 첫 번째 Edge에서 데이터가 샘플되며 이 값이 1이면 두 번째 Edge에서 데이터가 샘플된다.
 
다음 그림은 CPHA 비트가 0일 때의 타이밍을 설명하고 있다.
 
 


CPHA 값이 0이므로 클럭의 극성에 상관없이 MasterSlave는 모두 매 클럭의 첫 번째 Edge에서 데이터를 샘플한다따라서 매 클럭의 두 번째 Edge에서 비트 전환이 일어난다.
 
다음은 CPHA 비트가 1일 때의 타이밍을 설명한다.
 
 


클럭의 극성에 상관없이 매 클럭의 두 번째 Edge가 데이터 샘플에 사용되며 따라서 매 클럭의 첫 번째 Edge에서 비트 전환이 일어난다.
 
위의 4 가지 극성과 위상 조합에 0에서 3까지의 숫자를 부여하여 이를 SPI 모드라고 부른다.
 

SPI mode

CPOL

CPHA

0

0

0

1

0

1

2

1

0

3

1

1

 
두 개 이상의 SPI Slave 연결
I2C 버스처럼 SPI 버스에서도 한 개의 Master가 두 개 이상의 Slave와 연결될 수 있다. I2C Slave가 고유한 주소를 가지고 있는 것처럼 각각의 SPI Slave chip enable (/CE) 신호를 가지고 있다. SPI Master는 각 Slave /CE 신호를 제어하여 원하는 Slave를 선택한다다음 그림은 한 개의 SPI Master에 두 개의 Slave들을 연결하는 방법을 설명한다.
 


세 장치의 SCLK, MOSI, MISO는 각각 서로 연결되어 있지만 Slave /CE 신호들은 서로 묶이지 않고 Master의 다른 핀들로 연결된다. Slave의 수에 상관없이 한 순간에는 하나의 SlaveMaster와 통신할 수 있다Slave가 모두 활성화되면 Slave의 출력인 MISO에서 데이터의 충돌이 일어난다그래서 Master는 자신이 원하는 Slave /CE 신호만 0’으로 설정하여 활성화시키고 나머지 Slave /CE 1’로 두어야 한다. /CE 입력이 1’인 Slave는 선택되지 않았기 때문에 자신의 MISO 출력을 hi-Z 상태로 만들어 선택된 SlaveMaster 간의 통신에 영향을 주지 않는다따라서 모든 SPI Slave MISO 출력은 3 상태를 지원한다. /CE 입력이 1’인 Slave는 당연히 Master가 출력한 SCLK MOSI 신호를 무시한다.
 
세 개 이상의 Slave도 같은 방법으로 Master와 연결할 수 있다. Slave의 수가 하나씩 늘어날 때마다 새로운 Slave를 위한 /CE 신호만 하나 더 필요할 뿐이다그런데 이 때 Master에 연결된 Slave들이 사용하는 SPI 모드가 한 가지가 아니거나 비트 전송 순서가 다를 수 있는데 이런 경우에는 통신의 효율이 많이 낮아진다가령 어떤 Slave는 모드 0을 사용하고 또 다른 Slave는 모드 1을 사용한다면 MasterSlave를 바꿀 때마다 동작 모드를 매번 다시 설정해야 한다또한 동작 모드가 같아도 비트 전송 순서가 다르다면 마찬가지 문제가 생긴다.
 
Master가 하나의 Slave만 구동한다면 Slave /CE 신호를 GND로 고정시켜 두어도 상관없다어차피 SCLK, MOSI, MISO를 공유할 다른 Slave가 없기 때문에 이 선들은 하나뿐인 Slave 전용으로 사용된다그렇기 때문에 Slave를 항상 활성화시켜 둬도 기능상의 문제는 생기지는 않는다.
 
SPI 통신의 예
AT45DB161D SPI 인터페이스를 사용하는 16 Mbit 직렬 플래쉬 메모리이다이 플래쉬 메모리에 정보를 기록하거나 저장된 정보를 읽기 위한 여러 방법 중 다음 그림은 main memory page read 명령을 설명하고 있다이 그림에서 데이터는 바이트 단위로 표시되어 있다.
 


main memory page read 명령은 AT45DB161D 내부의 특정 페이지의 내용을 연속으로 읽기 위한 것이다이 플래쉬 메모리의 용량은 2 Mbytes이므로 주소를 지정하기 위해서 21 비트가 필요하다. Master는 가장 먼저 AT45DB161D /CE 신호를 0’으로 만든 다음 main memory page read를 위한 8 비트 명령을 출력하고 이어서 읽기를 원하는 주소 3 바이트를 출력한다. (AT45DB161D MSB 우선의 비트 전송 순서를 사용한다.) main memory page read 명령과 3 바이트 주소를 받으면 AT45DB161D는 저장된 데이터를 읽어서 출력할 준비를 하는데 이 과정에 시간이 필요하다이를 위해 Master 4 바이트를 더 출력한다. Master가 추가로 전송하는 4 바이트를 전송하는 것은 SLCK를 출력하기 위한 동작이므로 출력하는 데이터는 어떤 값이든 상관없다.
 
이렇게 8 바이트를 MOSI로 출력하는 동안 계속해서 Master MISO AT45DB161D의 출력이 들어오지만 이 값은 아무런 의미가 없는 쓰레기 값이다. AT45DB161D의 데이터 전송은 9 번째 바이트부터 시작된다. AT45DB161D 9 번째 바이트에서 Master가 지정한 주소의 내용을MISO로 출력한 후 내부 카운터를 사용하여 주소를 1 증가시킨다이 후 Master MOSI로 한 바이트씩 출력할 때마다 AT45DB161D는 데이터를 출력하고 주소를 1 증가시키는 과정을 계속 되풀이한다이런 과정을 통해 Master AT45DB161D의 데이터를 필요한 만큼 연속해서 읽고 마지막으로 AT45DB161D /CE 신호를 1’로 만들어 통신을 끝낸다. 9 번째 바이트부터 Master SCLK를 출력할 뿐 MOSI로 출력해야 하는 데이터는 없으므로 어떤 값을 보내도 상관 없다.
 
이 명령 외에도 AT45DB161D을 사용에 필요한 다른 많은 명령들이 더 있다각 명령마다 위 그림과 비슷한 타이밍도를 가지고 있으므로 각 명령의 쓰임새와 사용법을 알려면 AT45DB161D의 데이터쉬트를 참고해야 한다.
 
SPI의 장·단점
SPI 버스의 가장 큰 장점으로는 최고 70 MHz에 이르는 빠른 통신 속도와 동시 양방향 통신이 가능하다는 점을 들 수 있다전송 데이터 단위에 대한 제약이 없어서 8 비트, 16 비트, 24 비트 등 원하는 길이를 한 워드로 설정할 수 있다비트 순서에 대한 제약도 없으므로 필요에 따라MSB부터 전송할 수도 있고 LSB부터 전송할 수도 있다. I2C Slave와 달리 SPI Slave는 자체 주소를 가지고 있지 않으므로 주소 충돌의 문제도 발생하지 않는다.
 
I2C 버스와 달리 SPI 버스에는 한 개의 버스 Master만 있을 수 있으며 I2C 버스에 비해 필요한 핀의 수가 더 많다. SPI 버스는 기본적으로 4 가닥의 선을 사용하며 Master에 연결된 Slave의 숫자가 많아질수록 Slave를 선택하기 위한 SS 핀의 수 역시 Slave 수에 비례해서 늘어난다또한 I2C 버스의 ACK와 같은 메커니즘이 없어서 Master는 자신이 통신하고 있는 장치가 실제 존재하는지 여부를 확인할 수 없다.
 

[출처] Serial 통신, UART, I2C, SPI 개요(펌)|작성자 노털