SPI for NanoPi

From wiki.ferrari.mo.it
Jump to navigation Jump to search

SPI for NanoPi

Note: the test environment is a NanoPi K1 Plus with FriendlyCore installed in eMMC, kernel 4.14.x .

To enable SPI1, execute npi-config and go to 6 - Advanced Options, then to A5 - SPI, then you can enable/disable SPI interfaces.

To test SPI connection, connect MOSI and MISO of the SPI interface in loopback (N.B. the same interface, not connect together SPI0 and SPI1).

Then, compile the following code (NB this is for SPI1):

gcc spi.c -std=c99 -o spi
#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>

static const char *device = "/dev/spidev1.0";   // /dev/spidev0.0 or /dev/spidev0.1
static uint8_t mode = 0;                        // SPI_MODE_0 (see text)
static uint8_t bits = 8;                        // 8 or 9
static uint32_t speed = 1000000;                // Clock frequency [Hz]
static uint16_t delay = 0;                      // Time between end of data and CS de-assert

// Exit and print error code
static void exit_on_error (const char *s) {
    perror(s);
    abort();
}

int main(int argc, char *argv[]) {
    int fd;
    int Buffer_size;
    uint8_t tx[] = {0x01, 0x02, 0x04, 0x08, 0x55, 0x00, 0xAA, 0xFF, };  // Data to send
    Buffer_size = sizeof(tx);                                           // Size of TX (and RX) buffer
    uint8_t rx[sizeof(tx)] = {0, };                                     // RX buffer

    struct spi_ioc_transfer tr = {
        .tx_buf = (unsigned long)tx,
        .rx_buf = (unsigned long)rx,
        .len = Buffer_size,
        .delay_usecs = delay,
        .speed_hz = speed,
        .bits_per_word = bits,
        .cs_change = 0,
    };

    // Open SPI device
    if ((fd = open(device, O_RDWR)) < 0) exit_on_error ("Can't open SPI device");

    // Set SPI mode
    if (ioctl(fd, SPI_IOC_WR_MODE, &mode) == -1) exit_on_error ("Can't set SPI mode");

    // Read and write data (full duplex)
    if (ioctl(fd, SPI_IOC_MESSAGE(1), &tr) < 1) exit_on_error ("Can't send SPI message");

    printf ("Data from SPI Rx buffer: ");
    for (int i = 0; i < Buffer_size; i++) printf("%.2X ", rx[i]);
    printf ("\n");

    close(fd);
    return (0);
}

To test, ececute the command with and without the MISO/MOSI in loopback.