BASIC4MCU | 질문게시판 | 아두이노 간 SPI 통신 질문
페이지 정보
작성자 master 작성일2018-07-02 10:09 조회15,043회 댓글0건
https://www.basic4mcu.com/bbs/board.php?bo_table=gac&wr_id=2220
본문
아두이노간에 SPI 통신을 이용해서 데이터를 송, 수신 하려고 하는데 master , slave 을 짜봤는데 이 프로그램에서 데이터가 어떻게 송, 수신 되어지는지 궁금합니다 그리고 혹시 잘못된게 있는지 알려주세요
내공 1000 드립니다1,2 번째 사진 Slave 3번째 사진 Master//http://www.makewith.co/page/project/985/story/2338/////-----------master code-----------//#include <SPI.h>//void setup(void){SPI.begin();// SPI 통신 초기화digitalWrite(SS,HIGH); // 슬레이브가 선택되지 않은 상태로 유지SPI.setClockDivider(SPI_CLOCK_DIV16); // 안정적인 전송을 위해 분주비를 높여 전송 속도를 낮춤Serial.begin(9600);}//void loop(void){if(Serial.available()){char data=Serial.read(); // 데이터 입력 확인if(data=='0'){digitalWrite(SS,LOW); // 슬레이브를 선택한다.char received=SPI.transfer(0); // 1바이트 데이터 수신을 위해 의미 없는 1바이트 데이터를 전송한다.digitalWrite(SS,HIGH); // 슬레이브 선택을 해제한다.Serial.println(received);}}}//-----------slave code-----------//#include <SPI.h>byte num;//void setup(void){pinMode(MISO,OUTPUT); pinMode(MOSI,INPUT); pinMode(SCK,INPUT); pinMode(SS,INPUT); // SPI 통신을 위한 핀들의 입출력 설정SPI.setClockDivider(SPI_CLOCK_DIV16); // 마스터의 전송 속도에 맞추어 통신 속도를 설정한다.SPCR|= _BV(SPE); // SPI 활성화 // SPI 통신을 위한 레지스터를 설정SPCR&=~_BV(MSTR); // Slave 모드 선택SPCR|= _BV(SPIE); // 인터럽트 허용num='A';// 카운터 초기화}//ISR(SPI_STC_vect){ // SPI 통신으로 데이터가 수신될 때 발생하는 인터럽트 처리 루틴SPDR=num; // 카운터 값을 ASCII 값으로 전달}//void loop(void){num=(num+1); // 카운터 값 증가 'A' ~ 'Z'if(num>'Z')num='A';delay(1000);}
질문 예제는 아니지만 비슷한 내용의 예제입니다.링크와 같은 예제를 여기서 추가적으로 설명하고 있습니다.이 글에서는 기술적인 내용을 볼 수 있습니다.
Examples
- Barometric Pressure Sensor: Read air pressure and temperature from a sensor using the SPI protocol.
- Digital Pot Control: Control a AD5206 digital potentiometer using the SPI protocol.
아두이노 레퍼런스 사이트에는 두 종류의 예제가 있습니다.이 예제들은 아두이노끼리 통신하는 예제가 아니고 주변장치를 읽어들이는 예제입니다.SPI 라이브러리는 슬레이 모드를 지원하지 않습니다.라이브러리 헤더파일에도 slave 단어가 검색되지 않죠
마스터 모드 설정void setup(void){SPI.begin();// SPI 통신 초기화digitalWrite(SS,HIGH); // 슬레이브가 선택되지 않은 상태로 유지SPI.setClockDivider(SPI_CLOCK_DIV16); // 안정적인 전송을 위해 분주비를 높여 전송 속도를 낮춤}//슬레이브 모드 설정void setup(void){pinMode(MISO,OUTPUT); pinMode(MOSI,INPUT); pinMode(SCK,INPUT); pinMode(SS,INPUT); // SPI 통신을 위한 핀들의 입출력 설정SPI.setClockDivider(SPI_CLOCK_DIV16); // 마스터의 전송 속도에 맞추어 통신 속도를 설정한다.SPCR|= _BV(SPE); // SPI 활성화 // SPI 통신을 위한 레지스터를 설정SPCR&=~_BV(MSTR); // Slave 모드 선택SPCR|= _BV(SPIE); // 인터럽트 허용}
이 때문에 마스터에 비해서 슬레이브 코드가 지저분합니다.
////-----------master code-----------//#include <SPI.h>//char received;//void setup(void){SPI.begin();digitalWrite(SS,HIGH);SPI.setClockDivider(SPI_CLOCK_DIV16);Serial.begin(9600);}//void loop(void){if(Serial.available()){char data=Serial.read();if(data=='0'){digitalWrite(SS,LOW); received=SPI.transfer(0); digitalWrite(SS,HIGH);Serial.println(received);}}}//-----------slave code-----------//#include <SPI.h>//byte num='A';//void setup(void){pinMode(MISO,OUTPUT); pinMode(MOSI,INPUT); pinMode(SCK,INPUT); pinMode(SS,INPUT);SPI.setClockDivider(SPI_CLOCK_DIV16);SPCR=_BV(SPE)|_BV(SPIE); // 슬레이브 모드, 수신인터럽트}//ISR(SPI_STC_vect){SPDR=num;}//void loop(void){if(++num>'Z')num='A'; delay(1000); // 카운터 값 증가 'A' ~ 'Z'}
동작을 이해한다면 주석을 없애는 것이 머리가 덜 복잡해집니다.
위 예제는1. 마스터의 시리얼모니터에서 '0'을 입력하면2. 마스터에서 아무(쓰레기) 데이터를 1바이트 전송하고3. 슬레이브에서 알파벳 대문자를 차례대로 증가 시키면서 1바이트 전송합니다.4. 마스터에서는 이 값을 받아서 시리얼 모니터에 출력합니다.간단한 내용이죠마스터에서 데이터를 송신하고 않아도 계속해서 슬레이브가 알파벳을 증가시키는 오류가 있습니다.
////-----------master code-----------//#include <SPI.h>//char received;//void setup(void){SPI.begin();digitalWrite(SS,HIGH);SPI.setClockDivider(SPI_CLOCK_DIV16);Serial.begin(9600);}//void loop(void){if(Serial.available()){char data=Serial.read();if(data=='0'){digitalWrite(SS,LOW); received=SPI.transfer(0); digitalWrite(SS,HIGH);Serial.println(received);}}}//-----------slave code-----------//#include <SPI.h>//byte num='A';char flag=0;//void setup(void){pinMode(MISO,OUTPUT); pinMode(MOSI,INPUT); pinMode(SCK,INPUT); pinMode(SS,INPUT);SPI.setClockDivider(SPI_CLOCK_DIV16);SPCR=_BV(SPE)|_BV(SPIE); // 슬레이브 모드, 수신인터럽트}//ISR(SPI_STC_vect){SPDR=num; flag=1;}//void loop(void){if(flag){ flag=0; if(++num>'Z')num='A'; } // 카운터 값 증가 'A' ~ 'Z'}
flag 변수를 사용해서 데이터를 받았을 때만 알파벳을 증가 시키도록 동기화 시켰습니다.
역활을 반대로 바꿔서 시켜보죠1. 마스터에서 알파벳 대문자를 차례대로 1초에 1바이트씩 전송하면2. 슬레이브에서 수신한 후3. 슬레이브의 시리얼 모니터에 출력
////-----------master code-----------//#include <SPI.h>//byte num='A';char received;//void setup(void){SPI.begin();digitalWrite(SS,HIGH);SPI.setClockDivider(SPI_CLOCK_DIV16);}//void loop(void){delay(1000);digitalWrite(SS,LOW); received=SPI.transfer(num); digitalWrite(SS,HIGH);if(++num>'Z')num='A'; // 카운터 값 증가 'A' ~ 'Z'}//-----------slave code-----------//#include <SPI.h>//byte num;char flag=0;//void setup(void){pinMode(MISO,OUTPUT); pinMode(MOSI,INPUT); pinMode(SCK,INPUT); pinMode(SS,INPUT);SPI.setClockDivider(SPI_CLOCK_DIV16);SPCR=_BV(SPE)|_BV(SPIE); // 슬레이브 모드, 수신인터럽트Serial.begin(9600);}//ISR(SPI_STC_vect){num=SPDR; flag=1;}//void loop(void){if(flag){ flag=0; Serial.println(num); }}
동작시켜보지 않았으니 돌려보세요
댓글 0
조회수 15,043등록된 댓글이 없습니다.