[아두이노] [강좌] 33. SPI 통신 (2) – SPI 함수 알아보기

이번 강좌에서는 SPI 통신을 사용하기 위해 아두이노에서 제공하는 함수들에 대해 알아보자.

 

사실 SPI 통신을 사용하는 센서나 모듈이 많음에도 불구하고 SPI 함수를 직접 다룰 일은 많지 않다. SPI 통신을 사용하는 모듈은 대부분 길이가 긴 데이터를 주고받고또 동작을 위한 단계가 복잡한 경우가 많기 때문에 보통은 해당 모듈의 제조사에서 라이브러리 소스를 제공하거나아두이노에서 제공하는 라이브러리를 사용한다.

 

예를 들어 이더넷 또는 Wifi 모듈의 경우 SPI를 사용하지만대부분의 모듈 제조사에서 자신들의 라이브러리를 제공하고 있으며, SD 쉴드의 경우 아두이노에서 “SD”라는 라이브러리를 제공하여 사용하도록 하고 있다. Wifi SD 쉴드를 직접 제어하기 위해 소스를 구현하고자 한다면일주일 밤낮을 새도 못할 것 같다물론 뚝딱 할 수 있는 고수들은 많겠지만. (그런 고수가 내 블로그 글 읽을 일 없을 테니까 ㅠㅠㅋㅋㅋㅋㅋㅋ)

 

아무튼그렇지만 간혹 SPI 통신을 직접 사용해야 하는 경우도 있고알아둬서 나쁠 일이 없으므로 배워보도록 하자.

 


brown_and_cony-50 (귀척?) 

 

 

지난 강좌에서 설명한대로, SPI 통신을 위해서는 MOSI, MISO, SCK, SS 핀이 필요하고각 핀은 아두이노 보드의 50~53번 핀에 할당되어 있다그 중 SS 핀은 변경이 가능한데만일 하나의 슬레이브만을 사용한다면 그대로 53번을 SS 핀으로 사용하면 되고(물론 변경해도 되고), 둘 이상의 슬레이브를 사용한다면 하나는 53번에, 나머지는 다른 핀에 연결해야 한다. 슬레이브 하나 당 SS 핀 하나. 

 

만일 SS 핀을 변경했다면 소스 상에서도 SS 핀을 변경해줘야 한다? SS 핀을 변경하는 방법은 맨 마지막에 “*참고에서 다시 자세히 설명.

 

 


일단 함수 설명 고고!


SPI 함수는 SPI.h 파일에 정의되어 있으므로 “#include <SPI.h>” 구문을 추가한 후 사용할 수 있다.

 



SPI.begin()

SPI.begin(ss) – Due Only

 

SPI 통신을 위해 통신 포트를 초기화한다듀에(Due) 외의 보드에서는 매개 변수가 없으며듀에의 경우에만 매개 변수로 SS 핀의 번호를 지정할 수 있다듀에탐난다ㅋㅋㅋㅋㅋ

 

 

 

 매개 변수

 

 (듀에 외의 보드에서는 매개 변수 없음)

 ss – 듀에에서만 사용하는 매개 변수. SS 핀 번호를 설정한다.

 



 

 

SPI.setBitOrder(order)

 

데이터 전송 시 최상위 비트를 먼저 전송할지최하위 비트를 먼저 전송할지를 설정한다. SPI 공통의 설정을 변경하는 것이므로슬레이브 간에 설정이 다를 경우에는 SPI.beginTransaction() 함수를 이용해서 설정해야 한다듀에의 경우 매개 변수로 SS 핀이 추가되지만따로 설명은 생략하도록 하겠다듀에는 공식 홈페이지를 참고하세용.

 

 

 

 매개 변수

 

 order – LSBFIRST 또는 MSBFIRST 중에 선택하여 사용한다.

 

 LSBFIRST – 최하위 비트부터 전송

 MSBFIRST – 최상위 비트부터 전송 (default)

 


 


SPI.setClockDivider(divider)

 

SPI 통신 속도 설정을 위해 클럭 나누기 값(-_-)을 설정한다몇 클럭에 한 비트를 보낼 건지 정한다고 생각하면 쉽다지정된 값들 중 하나를 선택하여 사용할 수 있다이 함수 역시 공통으로 사용하는 SPI의 속도를 변경하므로 슬레이브 간의 설정이 다를 경우SPI.beginTransaction() 함수를 사용하여 각각 설정해야 한다.

 

 

 

 매개 변수

 

 divider – 다음 값들 중 하나를 선택한다.

 

- SPI_CLOCK_DIV2

- SPI_CLOCK_DIV4

- SPI_CLOCK_DIV8

- SPI_CLOCK_DIV16

- SPI_CLOCK_DIV32

- SPI_CLOCK_DIV64

- SPI_CLOCK_DIV128



 

예를 들어 ‘SPI_CLOCK_DIV8’을 선택할 경우 클럭 당 한 비트씩 전송하게 되므로, 16MHz의 메인 클럭을 가지는 메가(Mega 2560/ADK) 또는 우노(Uno)의 경우 2MHz(=16MHz/8)의 속도로 통신을 하게 된다. 2,000,000bps의 속도를 가지게 된다는 뜻. (1M = 1,000,000)

 

 

 

SPI.setDataMode(mode)

 

데이터 전송 시 사용할 모드를 선택한다모드는 4가지가 있으며클럭 신호를 HIGHLOW(Falling)부터 시작할지, LOWHIGH(Rising)부터 시작할지클럭이 HIGHLOW(Falling)가 될 때 데이터를 쓸 건지, LOWHIGH(Rising)가 될 때 데이터를 쓸 건지를 정하는 함수이다.

 

?? 뭐라규??

 

다음 표를 보자.

 

 

 

클럭 시작

클럭 종료

모드

신호

데이터

신호

데이터

0

Rising

읽기 (Sample)

Falling

쓰기 (Setup)

1

Rising

쓰기

Falling

읽기

2

Falling

읽기

Rising

쓰기

3

Falling

쓰기

Rising

읽기

 

 

그렇군.

 

brown_and_cony-58 

 

 

다음은 메가의 칩인 ATmega2560의 데이터 시트 중 모드에 관한 부분이다타이밍도를 보면 이해하기 쉬울 듯.

5f998e34b5eadf67672c4e8710f301fc.png
 

  

하하하.

 

 

암튼 매개 변수.

 


 

 매개 변수

 

 mode – 다음 중 하나를 선택하여 설정한다.

 

- SPI_MODE0 (default)

- SPI_MODE1

- SPI_MODE2

- SPI_MODE3


 

 

 

SPI.end()

 

SPI 통신을 종료하고사용하던 핀을 일반 디지털 핀으로 전환한다.

 

 

 

 매개 변수

 

 없음



 

 

 

SPI.beginTransaction(SPISettings)

 

연결된 슬레이브가 두 개 이상일 경우 슬레이브마다 SPI 통신 설정이 다를 수 있는데이럴 경우 각각의 통신마다 설정 값을 변경하기 위해 사용한다.

 

설정을 위해서는 ‘SPISettings’라는 클래스가 사용되는데, SPISettings 클래스를 선언할 때 생성자에 설정 값을 설정하여 객체를 생성한 후SPI.beginTransaction() 함수에 매개 변수로 전달한다.

 

SPISettings 클래스의 생성자는 다음과 같다.

 

 

SPISetting(speed, order, mode)

 

SPI.setOrder() 함수에 사용된 매개 변수와 SPI.setDataMode()에 사용된 매개 변수가 각각 order mode에 들어가며, speed 값은 실제 통신 속도 값을 넣는다. 2MHz를 사용하고 싶으면 2000000, 1MHz를 사용하고 싶다면 1000000을 사용한다각각SPI.setClockDivider() 함수에 매개 변수로 CLOCK_DIV8, CLOCK_DIV16을 사용한 것과 같은 역할을 한다.

 

 

 

 매개 변수

 

 speed – 통신 속도 값

 order – LSBFIRST 또는 MSBFIRST

 mode – SPI_MODE0~3



 

SPI.endTransaction() 함수까지 알아본 후 사용 예제를 살펴보도록 하자.

 

 

 

SPI.endTransaction()

 

다른 슬레이브 기기를 설정하기 위해 이 전의 설정을 종료한다매개 변수는 없다.

 

다음 예제는 두 개의 슬레이브를 각각 다른 설정으로 통신하는 예제 소스이다출처는 아두이노 공식 홈페이지.

 

 

 SPISettingsTest.ino

 

 #include <SPI.h>

  

 int ssA = 20;    // 슬레이브 A SS 

 int ssB = 21;    // 슬레이브 B SS 

 

 SPISettings settingA(2000000, MSBFIRST, SPI_MODE1);

 SPISettings settingB(16000000, LSBFIRST, SPI_MODE3);

 

 byte val1, val2, val3;

 

 void setup() {

   pinMode(ssA, OUTPUT);

   pinMode(ssB, OUTPUT);

 

   SPI.begin();

 }

 

 void loop() {

   SPI.beginTransaction(settingA);   // 슬레이브 A와 통신 시작 – settingA로 설정

 

   digitalWrite(ssA, LOW);          // 슬레이브 A 선택 신호(LOW) 출력

   val1 = SPI.transfer(0);            // 데이터 전송/수신

   val2 = SPI.transfer(100);          // 데이터 전송/수신

   digitalWrite(ssA, HIGH);          // 슬레이브 A 선택 해제 신호(HIGH) 출력


   SPI.endTransaction();             // 슬레이브 A와 통신 종료 – 설정 해제

 

   SPI.beginTransaction(settingB);    // 슬레이브 B와 통신 시작 – settingB로 설정


   digitalWrite(ssB, LOW);           // 슬레이브 B 선택 신호(LOW) 출력

   val3 = SPI.transfer(val1+val2);     // 데이터 전송/수신

   digitalWrite(ssB, HIGH);           // 슬레이브 B 선택 해제 신호(HIGH) 출력


   SPI.endTransaction();             // 슬레이브 B와 통신 종료 – 설정 해제

 

   if(val3) {

      // ...

   }

 }




어렵지 않다그럼 데이터를 전송하고 수신하는 함수를 알아보자.

 

 

 

byte SPI.transfer(data)

 

SPI 통신은 전송과 수신이 동시에 이뤄지기 때문에 전송 함수수신 함수가 따로 있지 않다전송하면 수신되는거수신된 데이터가 반환 값으로 반환된다.

 

 

 

 매개 변수

 

 data – 전송할 데이터 (byte )

  

 반환 값

 

 byte – 수신된 데이터 (byte )



 

 

실제 SPI 통신에 사용되는 함수는 SPI.transfer() 함수 뿐이고나머지는 다 설정 함수네유의해야 할 점은 SPI.transfer() 함수가 사용되기 전 데이터를 전송할 슬레이브의 SS 핀을 LOW로 출력하고전송이 완료되면 HIGH로 변경해야 한다는 것.

 

 

 

함수 몇 개 안되는데왜 이렇게 내용이 길지

 

 

다음 강좌에서는 직접 SPI 통신 함수를 사용해야 하는 몇 안 되는 센서들 중 하나인 기압 센서를 가지고 실습을 해보도록 하겠다그럼 안녕!

  

0
0
이 글을 페이스북으로 퍼가기 이 글을 트위터로 퍼가기 이 글을 카카오스토리로 퍼가기 이 글을 밴드로 퍼가기

임베디드 보드

번호 제목 글쓴이 날짜 조회수
58 아두이노 [강좌] 50. 와이파이 통신 (4) - WebServer 예제 icon 양재동메이커 03-21 9,550
57 아두이노 [강좌] 49. 와이파이 통신 (3) - WebClient 예제 icon 양재동메이커 03-21 13,224
56 아두이노 [강좌] 48. 와이파이 통신 (2) - 커맨드 모드 사용하기 (WiFly 쉴드) icon 양재동메이커 03-20 8,636
55 아두이노 [강좌] 47. 와이파이 통신 (1) - 와이파이란 무엇인가 icon 양재동메이커 03-20 12,400
54 아두이노 [강좌] 46. 블루투스 통신 (5) - 프로토콜 만들기 (2) icon 양재동메이커 03-20 8,926
53 아두이노 [강좌] 45. 블루투스 통신 (4) - 프로토콜 만들기 (1) icon 양재동메이커 03-20 10,414
52 아두이노 [강좌] 44. 블루투스 통신 (3) - RN42 모듈에서 직접 접속하기 icon 양재동메이커 03-20 7,750
51 아두이노 [강좌] 43. 블루투스 통신 (2) - 스마트폰과 통신하기 icon 양재동메이커 03-20 9,850
50 아두이노 [강좌] 42. 블루투스 통신 (1) - RN42 블루투스 모듈 실습하기 icon 양재동메이커 03-20 10,986
49 아두이노 [강좌] 41. 서보 모터 (2) - Servo 함수 알아보기 icon 양재동메이커 03-20 12,708
48 아두이노 [아두이노 강좌] 40. 서보 모터 (1) - 서보 모터 동작 방식 icon 양재동메이커 03-20 12,636
47 아두이노 [강좌] 39. 스텝 모터 (3) - 모터 드라이버 EasyDriver(A3967) 사용하기 icon 양재동메이커 03-20 8,985
46 아두이노 [강좌] 38. 스텝 모터 (2) - Stepper 함수 알아보기 icon 양재동메이커 03-20 12,548
45 아두이노 [강좌] 37. 스텝 모터 (1) - 스텝 모터 동작 방식 icon 양재동메이커 03-20 9,328
44 아두이노 [강좌] 36. DC 모터 (2) - DC 모터 드라이버 실습하기 (TB6612FNG) icon 양재동메이커 03-20 9,195
43 아두이노 [강좌] 35. DC 모터 (1) - DC 모터 동작 방식 icon 양재동메이커 03-20 11,467
42 아두이노 [강좌] 34. SPI 통신 (3) - 기압 센서(MPL115A1) 실습하기 icon 양재동메이커 03-20 8,140
41 아두이노 [강좌] 33. SPI 통신 (2) – SPI 함수 알아보기 icon 양재동메이커 03-20 14,508
40 아두이노 [강좌] 32. SPI 통신 (1) - SPI 통신이란 무엇인가 icon 양재동메이커 03-20 18,981
39 아두이노 [강좌] 31. I2C 통신 (3) - 온도 센서(TMP102) 실습하기 icon 양재동메이커 03-20 14,794