ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 리눅스 어플리케이션에서 SPI 사용하기
    프로그래밍/리눅스 2021. 3. 24. 15:50
    728x90

    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

    댓글

Designed by Tistory.