본문 바로가기

프로그래밍/프로그래밍_여러가지

아두이노 - ATtiny85 SPI통신 Slave 모드, USI(Universal Serial Interface)

반응형

아두이노 ATtiny85 SPI통신 Slave 모드, USI(Universal Serial Interface)

 

ATtiny85를 슬레이브로 사용하여 SPI통신을 하려고 한다.

ATtiny85는 SPI 라이브러리를 사용할 수 없다. 

ATtiny85는 다른 아두이노처럼 SPI라는 명칭을 사용하지 않고 USI라는 명칭을 사용한다. 데이타시트에 나와있다.

USI - Universal Serial Interface

 

회로도

 

아래 코드는 마스터 보드의 코드이다. 0x99와 0xAA를 100ms마다 번갈아 슬레이브로 보낸다.

Master

// ATmega128 사용

#include <SPI.h>

#define CS  8    // Chip Select pin

void setup() {
  pinMode(CS, OUTPUT);
  digitalWrite(CS, HIGH);
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0)); // 1MHz
  SPI.begin();
}

void loop() {
  digitalWrite(CS, LOW);
  SPI.transfer(0x99);
  digitalWrite(CS, HIGH);
  delay(100);

  digitalWrite(CS, LOW);
  SPI.transfer(0xAA);
  digitalWrite(CS, HIGH);
  delay(100);
}

 

아래 코드는 마스터로부터 SPI통신을 이용하여 1byte를 받아 처리하는 슬레이브 보드의 코드이다.

마스터로부터 받은 데이타가 이미 지정된 데이타(0x99)와 일치하면 LED가 켜지고

일치하지 않으면 LED가 꺼진다.

Slave

// 참조 사이트 : https://weathergadget.wordpress.com/2016/05/19/usi-spi-slave-communication/

#define CS    3     // Chip select
#define LED   4     // Test LED

volatile int data = 0;        

void setup (void) {
  cli();                      // Deactivate Interrupts

  pinMode(CS, INPUT);
  pinMode(LED, OUTPUT);  
  
  USICR = ((1<<USIWM0)|(1<<USICS1));  // USI 통신 인터럽트 관련
  
  GIMSK = 0b00100000;         // 핀 체인지 인터럽트 활성화
  PCMSK = 0b00001000;         // 핀 체인지 인터럽트 핀 설정: PB3

  sei();                      // Activate Interrupts
} 

ISR(PCINT0_vect) {            // pin change interrupt    
  if((PINB & (1<<CS)) == 0){  // Chip select 핀이 LOW로 바뀌면    
    USICR |= (1<<USIOIE);     // USI 통신 인터럽트 실행
    USISR = 1<<USIOIF;        // Clear Overflow bit
  }
  else{
    USICR &= ~(1<<USIOIE);    // USI 통신 인터럽트 실행 안됨
  }
}

ISR(USI_OVF_vect) {        // USI interrupt
  data = USIDR;            // 마스터로부터 받은 데이타를 data에 저장
  USISR = 1<<USIOIF;       // Clear Overflow bit

  if(data==0x99){          // 데이타를 비교하여 led on/off
    digitalWrite(LED, HIGH);
  }
  else{
    digitalWrite(LED, LOW);
  }
}

void loop (void) {
  
}

 

슬레이브 코드를 함수별로 구분해보면 아래와 같다.

코드 참조 사이트 : https://weathergadget.wordpress.com/2016/05/19/usi-spi-slave-communication/

 

1. setup 은 이것저것 setup하는거

2. ISR(PCINT0_vect) 는 핀 체인지 인터럽트

3. ISR(USI_OVF_vect) 는 실제 SPI 데이타 받을 때 인터럽트

4. loop 는 인터럽트가 아닌 다른 동작 프로그램 하는 곳

 

 

SPI 통신은 Master 보드가 통신하고자 하는 Slave 보드에 Chip Select 신호를 보낸 다음 실제 데이타를 보낸다.

마스터에서 Chip Selet 신호가 바뀌면 ATtiny85는 이를 감지해 데이타를 받을 준비를 한다.

Chip Select 신호가 바뀔 때 인터럽트가 실행되는 함수가 ISR(PCINT0_vect) 이다.

이때 필요한 레지스터들이 있다. (GIMSK, PCMSK)

 

그 다음엔 ISR(PCINT0_vect) 함수 안에서 통신 데이타를 받을 준비를 한다.

마스터에서 데이타가 보내지면 실행되는 인터럽트 함수가 ISR(USI_OVF_vect) 이다.

이 함수 안에서 데이타를 받아 다음 실행 프로그램을 작성하면 된다. 

이때 필요한 레지스터들이 있다. (USIDR, USICR, USISR)

 

 

동작에 따른 슬레이브 코딩 방법을 간단히 정리하면

칩선택 신호를 받는 인터럽트 코딩을 하고,

데이타를 받는 인터럽트 코딩을 하면 끝.

 

 

동작 영상

 

 

 

 

 

반응형