ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Raspberry PI 2 /3 와 Arduino를 연결하여 SPI 테스트
    Raspberry Pi/Arduino와 연동 2016. 11. 29. 18:49

    라즈베리파이에서 디폴트로 SPI가 비활성화 되어있기 때문에 활성화 시켜주는 작업이 필요합니다. 다음 포스팅을 참고하세요..

    [임베디드/Raspberry Pi] - Raspberry Pi 2/3에서 SPI 사용하기


    라즈베리파이 보드와 아두이노를 다음처럼 연결해줍니다.

    Raspberry Pi 2/3          Arduino UNO 

    (MOSI)  19       ------   11(MOSI)

    (MISO)  21      ------   12(MISO)

    (SCK)   23       ------   13(SCK)

         GND 6       ------    GND


    아두이노 IDE에 다음 코드를 복사한 후,  아두이노에 업로드 시켜줍니다. 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    #include <SPI.h>  
       
    char buf [100];  
    volatile byte pos = 0;  
    volatile boolean printIt = false;  
    #define   spi_enable()   (SPCR |= _BV(SPE))  
      
      
    void setup (void)  
    {  
      //시리얼 통신 초기화  
      Serial.begin (9600);  
       
      //Master Input Slave Output 12번핀을 출력으로 설정  
      pinMode(MISO, OUTPUT);  
        
      //slave 모드로 SPI 시작   
      spi_enable();  
       
      //인터럽트 시작  
      SPI.setClockDivider(SPI_CLOCK_DIV64); //250kHz   
      SPI.setDataMode(SPI_MODE0);  
      SPI.attachInterrupt();  
       
    }   
       
       
    // SPI 인터럽트 루틴  
    ISR (SPI_STC_vect)  
    {  
      // SPI 데이터 레지스터로부터 한바이트 가져옴  
      byte c = SPDR;    
        
      //버퍼에 자리가 있다면...  
      if (pos < sizeof buf)  
      {  
        buf[pos++= c;  
          
        // 출력을 진행한다.   
         if (c == '\0')  
          printIt = true;        
       }   
    }    
       
      
    void loop (void)  
    {  
      if (printIt)  
        {  
            buf[pos] = 0;    
            Serial.println (buf);  
            pos = 0;  
            printIt = false;  
        }    
          
    }  
    cs


    라즈베리파이에서 다음 코드를 컴파일 시켜 줍니다. 

    1
    pi@raspberrypi:~ $ gcc spi_test.c -o spi_test
    cs

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    #include <stdint.h>  
    #include <unistd.h>  
    #include <stdio.h>  
    #include <stdlib.h>  
    #include <getopt.h>  
    #include <fcntl.h>  
    #include <sys/ioctl.h>  
    #include <linux/types.h>  
    #include <linux/spi/spidev.h>  
      
    #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))  
      
    static void pabort(const char *s)  
    {  
        perror(s);  
        abort();  
    }  
      
    static const char *device = "/dev/spidev0.0";  
    static uint8_t mode;  
    static uint8_t bits = 8;  
    static uint32_t speed = 250000;  
    static uint16_t delay;  
      
    static void transfer(int fd, char* tx, int len)  
    {  
        int ret;  
        uint8_t rx[256];  
        struct spi_ioc_transfer tr = {  
            .tx_buf = (unsigned long)tx,  
            .rx_buf = (unsigned long)rx,  
            .len = len,  
            .delay_usecs = delay,  
            .speed_hz = speed,  
            .bits_per_word = bits,  
        };  
      
        ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);  
        if (ret < 1)  
            pabort("can't send spi message");  
     
        for (ret = 0; ret < len; ret++)   
            printf("%c", rx[ret]);  
        puts("\n");  
    }  
      
      
    int main(int argc, char *argv[])  
    {  
        int ret = 0;  
        int fd;  
      
      
        fd = open(device, O_RDWR);  
        if (fd < 0)  
            pabort("can't open device");  
      
        /* 
         * spi mode 
         */  
        ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);  
        if (ret == -1)  
            pabort("can't set spi mode");  
      
        ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);  
        if (ret == -1)  
            pabort("can't get spi mode");  
      
        /* 
         * bits per word 
         */  
        ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);  
        if (ret == -1)  
            pabort("can't set bits per word");  
      
        ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);  
        if (ret == -1)  
            pabort("can't get bits per word");  
      
        /* 
         * max speed hz 
         */  
        ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);  
        if (ret == -1)  
            pabort("can't set max speed hz");  
      
        ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);  
        if (ret == -1)  
            pabort("can't get max speed hz");  
      
        printf("spi mode: %d\n", mode);  
        printf("bits per word: %d\n", bits);  
        printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);  
     
        char buf[]="echo test";  
        transfer(fd, buf, ARRAY_SIZE(buf));  
      
        close(fd);  
      
        return ret;  
    }
    cs


    아두이노 IDE의 메뉴에서 도구 - 시리얼 모니터를 선택하여 시리얼 모니터를 실행시켜 놓고 라즈베리파이에서 컴파일한 프로그램을 실행시켜줍니다. 

    라즈베리파이에서 실행한 프로그램은  "echo test" 문자열을 spi를 이용해 아두이노로 전송 후, 종료합니다.


    시리얼 모니터를 보면 "echo test" 문자열이 출력된 걸 볼 수 있습니다.


    라즈베리 파이에서  "echo test" 문자열을 SPI를 이용해서 아두이노로 보내면 ,  아두이노는 해당 문자열을  받아 시리얼로 보내어 시리얼 모니터에 "echo test"가 출력되게 됩니다. 


    포스트 작성시에는 문제 없었지만 이후 문제가 생길 수 있습니다.
    댓글로 알려주시면 빠른 시일내에 답변을 드리겠습니다.

    여러분의 응원으로 좋은 컨텐츠가 만들어집니다. 지금 본 내용이 도움이 되었다면 유튜브 구독 부탁드립니다. 감사합니다 : )

    유튜브 구독하기


    댓글 8

    • kim 2016.08.15 01:49


      안녕하세요. SPI 통신을 처음으로 공부하는 초보입니다.
      SPI통신을 직접해보고 싶어 님 블로그를 참고하게 됬는데,
      아두이노가 슬레이브고, 라즈베리파이가 마스터인 상황에서 echo test를 아두이노 에서 잘 받는 것은 확인했습니다.
      그 반대로 아두이노에서 라즈베리파이로 echo 되는 echo test말고 다른 문자열 데이터를 보내고 싶은데 어떻게 해야하는지 도움을 구합니다 ㅠㅠ 어떤 식으로 구현해도 안되네요.. 부탁드립니다

    • name 2017.12.19 13:35


      감사합니다...! 천재신듯

    • ww 2019.11.26 19:12


      안녕하세요. 포스팅 감사합니다. 덕분에 많은 도움이 되었습니다.
      버퍼 사이즈를 256으로 변경하면 시리얼 모니터에 값이 뜨지 않던데.. SPI로 값이 전달이 안된걸까요?

    • ww 2019.11.27 10:19


      답변 감사드립니다. 다시 해보니 정상 출력되는걸 확인했습니다.

Designed by Tistory.