-
리눅스 어플리케이션에서 SPI 사용하기프로그래밍/리눅스 2021. 3. 24. 15:50728x90
I2C에 이어서 SPI를 사용하는 방법도 설명하겠습니다.
먼저 아래 예제 코드를 보시죠.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> #include <errno.h> #include <linux/types.h> #include <linux/spi/spidev.h> int bus = 0; int cs = 0; unsigned int mode = SPI_MODE_3; unsigned int bits = 8; unsigned int lsb_first = 1; unsigned int speed = 1000000; // 1MHz int main() { int fd; int rval; char path[20]; unsigned char buf[10]; struct spi_ioc_transfer xfer[1]; sprintf(path, "/dev/spidev%d.%d", bus, cs); if ((fd = open(path, O_RDWR)) < 0) { fprintf(stderr, "Can't open file '/dev/spidev%d.%d': %s\r\n", bus, cs, strerror(errno)); exit(EXIT_FAILURE); } // Set mode if ((rval = ioctl(fd, SPI_IOC_WR_MODE, &mode)) < 0) { fprintf(stderr, "%s\r\n", strerror(errno)); exit(EXIT_FAILURE); } // Set bit per word if ((rval = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits)) < 0) { fprintf(stderr, "%s\r\n", strerror(errno)); exit(EXIT_FAILURE); } // Set word order if ((rval = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &lsb_first)) < 0) { fprintf(stderr, "%s\r\n", strerror(errno)); exit(EXIT_FAILURE); } // Set max speed(Hz) if ((rval = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed)) < 0) { fprintf(stderr, "%s\r\n", strerror(errno)); exit(EXIT_FAILURE); } // Half-duplex read(fd, buf, 10); write(fd, buf, 10); // Full-duplex memset(xfer, 0, sizeof(xfer)); xfer[0].tx_buf = (__u64)buf; xfer[0].rx_buf = (__u64)buf; xfer[0].len = 10; if ((rval = ioctl(fd, SPI_IOC_MESSAGE(1), xfer)) < 0) { fprintf(stderr, "%s\r\n", strerror(errno)); exit(EXIT_FAILURE); } close(fd); return 0; }
SPI 노드는 /dev 디렉터리에 spidev<bus_number>.<cs_number> 형태로 생성 됩니다. SPI 표준은 다 아시겠지만 통신용 버스는 공용으로 사용하고 Chip select를 다르게 설계하여 사용하고자 하는 칩을 선택해서 사용할 수 있지요.
다음으로 SPI 전송 모드, 속도 등을 설정합니다. 위 코드에는 설정하도록만 구현되어 있지만 현재 어떻게 설정되어 있는지도 알 수 있습니다. ioctl 함수의 2번째 인자를 보면 SPI_IOC_WR_ 이렇게 되어 있는데요. 이 정의들은 SPI_IOC_RD_ 와 쌍으로 되어 있어 설정을 읽어 올 수 도 있습니다.
칩과 통신은 2가지 방법을 구현해 보았는데요. SPI 표준은 전이중(Full-duplex) 통신도 지원됩니다. 따라서 칩에서만 지원한다면 반이중(Half-duplex) 뿐 아니라 전이중 통신으로 Tx/Rx를 동시에 해올 수 있습니다.
728x90'프로그래밍 > 리눅스' 카테고리의 다른 글
리눅스 어플리케이션에서 RTC 사용하기 (0) 2021.03.26 리눅스 어플리케이션에서 I2C 사용하기 (0) 2021.03.23 리눅스 어플리케이션에서 GPIO 사용하기 (0) 2013.03.13