Arduino/SPI 통신

SPI의 기본적인 연결하기

DesignatedRoom 2020. 11. 5. 18:12

채널은 Address로, Level은 값으로 사용한다.

하드웨어의 연결은 두 아두이노 간의 D10 ~ D13까지 핀들을 각 각 연결한다. 

 

 

Master 소스 코드

더보기
//  MOSI  D11
//  MISO  D12   Master In Slave Out
//  SCK   D13
//  SS    D10 칩 셀렉트

//  SPI Master : Sender
//  마스터는 데이터를 읽는 입장이다.
#include <SPI.h>

#define   CHIP_SELECT   10  //  HIGH면 칩 셀렉트가 선택 안된 상태. LOW이면 선택된 상태

void setup() {
  // put your setup code here, to run once:
  SPI.begin();

  pinMode(CHIP_SELECT,OUTPUT);

  digitalWrite(CHIP_SELECT,HIGH);       //  슬레이브 선택이 안 된 상태
                                        
  SPI.setClockDivider(SPI_CLOCK_DIV16); //  분주비 설정. DIV16는 16Mhz
}

void loop() {
  // put your main code here, to run repeatedly:
  if (Serial.available())
  {
    char data = Serial.read();
    
    //  Master가 Slave에게 데이터를 보내야 한다. 
    //  누구한테 줄지 select를 해야한다. chip select
    
    digitalWrite(CHIP_SELECT,LOW);

    //  전송 코드가 들어올 코드 시작
   char recv = SPI.transfer(0);

   //   전송 코드가 들어올 코드 끝
    digitalWrite(CHIP_SELECT,HIGH);   //  다시 HIGH로 변경

    Serial.println(recv);
  }
}

 

 

Slave 소스 코드

더보기
//  SPI Slave
#include <SPI.h>

#define   CHIP_SELECT   10  //  HIGH면 칩 셀렉트가 선택 안된 상태. low이면 선택된 상태

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  
  pinMode(MOSI,INPUT);  //  Digital 11번 핀
  pinMode(MISO,OUTPUT); //  Digital 12번 핀
  pinMode(SCK,OUTPUT);  //  Digital 13번 핀
  pinMode(CHIP_SELECT, INPUT);  //  선택은 슬레이브에서 해야 한다. 마스터는 받아들이는 입장

  SPI.setClockDivider(SPI_CLOCK_DIV16); //  분주비 설정. DIV16는 16Mhz

  //  SPI통신에서 레지스터의 설정 하기
  
  //  SPI를 활성화
  SPCR |= _BV(SPE); //  _BV는 함수
  
  //  Slave모드로 변경
  SPCR &= _BV(MSTR);  
  
  //  인터럽트를 허용해야 한다.
  SPCR |= _BV(SPIE);
}

void loop() {
  // put your main code here, to run repeatedly:
  
   
   
   //delay(1000);
}

//  SPI통신은 인터럽트를 이용해서 데이터를 수신한다.
ISR(SPI_STC_vect)
{
  SPDR = '0';
}

 

 

위의 내용은 잘 되지 않는다. 아래의 소스는 검증이 끝났다.

마스터 슬레이브 쪽의 시리얼 통신의 시리얼 모니터로 각 자 모두 hello가 뜬다.

두 아두이노의 전원을 각 자 공급만 하고 서로 D10~D13번핀만 서로 연결한다.

Master 소스 코드

더보기
//  SPI통신 master  10~13핀 그대로 연결한다.
//  선은 그대로 한다.
//  슬레이브에 아예 전원을 공급하지 않고 해보자.
#include <SPI.h>
#define chipSelect 10//HIGH 슬레이버 선택되지 않은 상태, LOW 선택된 상태

void setup() {
  Serial.begin(9600);
 SPI.begin();
 pinMode(chipSelect, OUTPUT);
 digitalWrite(chipSelect,HIGH);//슬레이브 선택 안된 상태
 SPI.setClockDivider(SPI_CLOCK_DIV16); //DIV16=16Mhz DIV8=8Mhz
}
byte data;

void loop() {
  char p[10]="hello\n";
  
 
      //master->slave chip select
      digitalWrite(chipSelect,LOW);
      //master->slave전송코드
      for(int i=0;i<6;i++)
      {
       data=SPI.transfer(p[i]);
       Serial.print((char)data);
       //SPI.transfer(p[i]);
      }
      digitalWrite(chipSelect,HIGH);
      
//delay(1000);
}

 

 

 

Slave 소스 코드

더보기
//  spi slaver
#include <SPI.h>
#define chipSelect 10

void setup() {
 pinMode(MOSI,INPUT);//D11번 핀
 pinMode(MISO,OUTPUT);//D12번 핀
 pinMode(SCK,OUTPUT);//D13번 핀
 pinMode(chipSelect,INPUT); // CHIP SELECT

 SPI.setClockDivider(SPI_CLOCK_DIV16);
//SPI통신 레지스터 설정
//SPI 활성화
SPCR |=_BV(SPE);
//슬레이브모드 변경
SPCR &=~_BV(MSTR);
//인터럽트 허용
SPCR |=_BV(SPIE);

Serial.begin(9600);
}

volatile byte c;

void loop() {
if(c!='_'){
   Serial.print((char)c);
   c='_';
}
//delay(1000);
}

//spi통신은 인터럽트를 이용해서 데이터 수신
ISR(SPI_STC_vect){
 c=SPDR;

 //SPDR='a';
 }