반응형






아래 처럼 두 보드를 연결해주었습니다..


raspberry pi 2/3         Atmega128 

(MOSI)  19       ------ PB2(MOSI)

(MISO)  21      ------ PB3(MISO)

(SCK)   23       ------ PB1(SCK) 

(CS0)   24        ------ PB0    

      GND 6      ------ GND



라즈베리파이에서 SPI를 활성화 시키기 위해서는 다음 포스팅을 참고하세요..

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


라즈베리파이에서 데이터를 보내면... 



AVR과 연결된 피시의 시리얼 터미널에서 데이터가 들어온 것을 볼 수 있습니다.. 



다음은 각각 Atmega128을 위한 슬레이브 SPI 코드 및 라즈베리파이에서의 SPI 코드입니다..

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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
 * spi_slave.c
 *
 * Created: 2016-06-28
 * Author : webnautes
 */ 
 
 #define F_CPU 16000000UL
 
 //1. baud rate를 선택
 #define USART_BAUDRATE 9600
 
 //2.시스템 클록과 원하는 baud rate를 이용하여 UBRR 값을 계산한다.
 #define UBRR_VALUE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
 
#include <avr/io.h>
#include <avr/interrupt.h>
 
 
void usartInit()
{
    //3. UBRR0은 16비트 레지스터이기 때문에 8비트씩 나누어서 넣어야 한다.
    UBRR0H = (uint8_t)(UBRR_VALUE>>8);
    UBRR0L = (uint8_t) UBRR_VALUE;
    
    //4. USART 설정
    UCSR0C |= (1<<UCSZ00)|(1<<UCSZ01); //Charecter size : 8비트
    UCSR0C &= ~(1<<USBS0); //stop  bit : 1비트
    UCSR0C &= ~((1<<UPM01)|(1<<UPM00)); // no parity mode
    
    //5. 송수신을 가능하게 한다.
    UCSR0B=(1<<RXEN0)|(1<<TXEN0);
}
 
void transmitByte(uint8_t data) {
    
    //이전 전송이 끝나기를 기다림
    while(!(UCSR0A&(1<<UDRE0))){};
    
    UDR0 = data;                                            /* send data */
}
 
uint8_t receiveByte(void) {
    // 수신 되기를 기다림
    while(!(UCSR0A&(1<<RXC0))){};
    return UDR0;                                /* return register value */
}
 
 
void printString(volatile unsigned char str[]) {
    uint8_t i = 0;
    while (str[i]!='\0') {
        transmitByte(str[i]);
        i++;
    }
}
 
void readString(char str[], uint8_t maxLength) {
    char response;
    uint8_t i;
    i = 0;
    while (i < (maxLength - 1)) {                   /* prevent over-runs */
        response = receiveByte();
        transmitByte(response);                                    /* echo */
        if (response == '\r') {                     /* enter marks the end */
            break;
        }
        else {
            str[i] = response;                       /* add in a letter */
            i++;
        }
    }
    str[i] = 0;                          /* terminal NULL character */
}
 
void  init_SPI( ) {
    
    DDRB &= ~((1<<PB1)|(1<<PB2)|(1<<PB0)); // SCK, MOSI, SS --> inputs
    DDRB |= (1<<PB3);                  // MISO --> output
    
    //slave mode
    SPCR &= ~(1<<MSTR);
    
    //16000KHz / 16 
    SPCR  |= (1<<SPR0);
    
    //enable SPI
    SPCR |= ((1<<SPE)|(1<<SPIE));
 
}
 
 
 
 
unsigned char SPI_write(unsigned char cData) {
    SPDR = cData;
    while ( !(SPSR & (1<<SPIF))) ;
    return SPDR;
}
 
unsigned char SPI_read( void ) {
    SPDR = 0x0;
    while ( !(SPSR & (1<<SPIF))) ;
    return SPDR;
}
 
 
 
volatile unsigned char str[100];
 
 
ISR(SPI_STC_vect)
{
    static uint8_t idx=0;
    unsigned char ch = SPDR;
 
    if ( ch == '\0' )
    {
        str[idx]='\0';
        printString(str);
        idx=0;
    }
    else {
            str[idx]=ch;
            idx++;
    }    
 
 
}
 
int main (void)
{
    init_SPI();
    usartInit();
    sei();
    
    while(1)
    {
 
 
    }
}
 
 
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
102
#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 = 1000000;
static uint16_t delay=0;
 
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 test0";
    transfer(fd, buf, ARRAY_SIZE(buf));
 
    close(fd);
 
 
    return ret;
}
cs


반응형

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

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

유튜브 구독하기


제가 쓴 책도 한번 검토해보세요.

  1. 1234 2019.05.01 18:23

    안녕하세요
    라즈베리파이와 아트메가의 차이점을 알수있을까요?
    어떤 상황에서는 라즈베리파이를 사용하고 어떤 상황에서는 아트메가를 채택하는지 알고싶습니다.

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.05.01 18:41 신고

      라즈베리파이는 CPU를 장착하기 때문에 운영체제가 올라가게되고...

      아트메가는 마이크로컨트롤러를 장착하기 때문에 운영체제를 사용못하고 펌웨어를 올릴 수 있습니다.



      네트워크 관련 응용에 대해서 비교해보면..

      라즈베리파이를 사용한다면 웹서버, 파일서버등을 구축하여 많은 사용자들이 서버에 접속하여 서비스를 이용할 수 있도록 할 수 있습니다.
      물론 PC나 서버 컴퓨터 정도의 성능은 나오지 않지요..

      아트메가의 경우에는 라즈베리파이에 비해 성능이 상대적으로 떨어지기 때문에 많은 사용자가 동시에 접속하는 서버를 구축하기 힘듭니다. 그래서 소규모의 네트워크를 위한 라우터, 인터넷 공유기등을 만드는데 사용합니다.

  2. Favicon of https://noel-embedded.tistory.com BlogIcon 수리노을 2019.05.02 02:39 신고

    MCU 마이크로컨트롤러는 CPU를 포함하며 메모리와 여러 모듈이 함께 있는 SoC입니다. 라즈베리파이는 BCM사의 ARM chip으로 아트메가는 atmel사의 atmega chip으로 둘 모두 MCU입니다. 둘 모두 사용하려는 운영체제가 하드웨어를 지원한다면 OS를 올릴 수 있습니다. 단, atmega는 8비트 cpu와 적은 메모리양으로 인해서 올리지 않고 기본 펌웨어로 사용하는 것입니다.

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.05.02 05:14 신고

      좋은 답변 감사합니다.

      엄밀히 말하면 Atmega도 OS를 올릴수 있는게 맞습니다. 하지만 Raspberry Pi에 올라가는 Linux와는 기능과 성능 에서 차이가 많이나서 주로 특수한 임베디드 응용에서 사용하지 않나 싶습니다.

      둘 다 코어를 기반으로 주변장치를 연결할때 사용하는 시리얼, I2C 등의 인터페이스를 추가하여 설계했기때문에 soc라 볼수 있을지 모르지만 둘다 마이크로컨트롤러라 부르지는 않나 싶습니다.

      라즈베리파이 공식 홈페이지의 하드웨어 소개에서도 마이크로프로세서라고 언급합니다.

      마이크로컨트롤러라면 독자적으로 동작이 가능해야하는데..
      라즈베리파이에 장착된 브로드컴사의 칩에는 메모리가 포함되어 있지 않아서 이기도합니다..

  3. Favicon of https://noel-embedded.tistory.com BlogIcon 수리노을 2019.05.02 14:56 신고

    답 감사합니다

  4. Nox 2020.11.04 15:45

    안녕하세요. 좋은 글 감사합니다.
    라즈베리파이에서 문자열을 받을려면 리시브 함수를 어떻게 해야하나요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.11.04 19:13 신고

      쓰레드로 소켓에서 데이터들어오면 읽어오는 함수를 구현하면 됩니다. 채팅 소스 코드를 찾아 참고하면 좋을듯합니다

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.11.04 19:14 신고

      아 다시보니 소켓통신이 아니군요. 깃허브에서 코드에서 사용한 함수나 상수를 같이 적어.검색하면 리시브 구현한 코드를 찾을수 있을듯합니다

+ Recent posts