SPI

How to use SPI

root@odroid:~# lsmod                                                            
Module                  Size  Used by                                           
uinput                  6669  1                                                 
ir_lirc_codec           4243  3                                                 
lirc_dev               10110  1 ir_lirc_codec                                   
ir_mce_kbd_decoder      3092  0                                                 
ir_sanyo_decoder        1638  0                                                 
ir_sony_decoder         1667  0                                                 
ir_jvc_decoder          1664  0                                                 
ir_rc6_decoder          2024  0                                                 
ir_rc5_decoder          1552  0                                                 
ir_nec_decoder          1776  0                                                 
meson_ir                2902  0                                                 
joydev                  8607  0                                                 
hid_logitech_dj        11642  0                                                 
fuse                   70879  2                                                 
nls_cp437               5125  1  
                                          
root@odroid:~# modprobe spicc    
                                               
root@odroid:~# lsmod                                                            
Module                  Size  Used by                                           
ads7846                13766  0                                                 
spidev                  5465  0                                                 
spicc                   7846  0                                                 
uinput                  6669  1                                                 
ir_lirc_codec           4243  3                                                 
lirc_dev               10110  1 ir_lirc_codec                                   
ir_mce_kbd_decoder      3092  0                                                 
ir_sanyo_decoder        1638  0                                                 
ir_sony_decoder         1667  0                                                 
ir_jvc_decoder          1664  0                                                 
ir_rc6_decoder          2024  0                                                 
ir_rc5_decoder          1552  0                                                 
ir_nec_decoder          1776  0                                                 
meson_ir                2902  0                                                 
joydev                  8607  0                                                 
hid_logitech_dj        11642  0                                                 
fuse                   70879  2                                                 
nls_cp437               5125  1 
                                                
root@odroid:~# ls /dev/spidev0.0
/dev/spidev0.0                                                                  
root@odroid:~# 

Compile & run SPI test example source code

gcc -o spidev_test spidev_test.c
odroid@odroid:~$ ./spidev_test
spi mode: 0
bits per word: 8
max speed: 500000 Hz (500 KHz)
spidev_test.c
/*
 * SPI testing utility (using spidev driver)
 *
 * Copyright (c) 2007  MontaVista Software, Inc.
 * Copyright (c) 2007  Anton Vorontsov <avorontsov@ru.mvista.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License.
 *
 * Cross-compile with cross-gcc -I/path/to/cross-kernel/include
 */
 
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
 
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#define uchar unsigned char
 
#define MAX_RAW     36
#define MAX_COLUMN  8
 
uchar disp1[MAX_RAW][MAX_COLUMN] = {
    {0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C},//0
    {0x10,0x30,0x50,0x10,0x10,0x10,0x10,0x7C},//1
    {0x3E,0x02,0x02,0x3E,0x20,0x20,0x3E,0x00},//2
    {0x00,0x7C,0x04,0x04,0x7C,0x04,0x04,0x7C},//3
    {0x08,0x18,0x28,0x48,0xFE,0x08,0x08,0x08},//4
    {0x3C,0x20,0x20,0x3C,0x04,0x04,0x3C,0x00},//5
    {0x3C,0x20,0x20,0x3C,0x24,0x24,0x3C,0x00},//6
    {0x3E,0x22,0x04,0x08,0x08,0x08,0x08,0x08},//7
    {0x00,0x3E,0x22,0x22,0x3E,0x22,0x22,0x3E},//8
    {0x3E,0x22,0x22,0x3E,0x02,0x02,0x02,0x3E},//9
    {0x08,0x14,0x22,0x3E,0x22,0x22,0x22,0x22},//A
    {0x3C,0x22,0x22,0x3E,0x22,0x22,0x3C,0x00},//B
    {0x3C,0x40,0x40,0x40,0x40,0x40,0x3C,0x00},//C
    {0x7C,0x42,0x42,0x42,0x42,0x42,0x7C,0x00},//D
    {0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x7C},//E
    {0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x40},//F
    {0x3C,0x40,0x40,0x40,0x40,0x44,0x44,0x3C},//G
    {0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44},//H
    {0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x7C},//I
    {0x3C,0x08,0x08,0x08,0x08,0x08,0x48,0x30},//J
    {0x00,0x24,0x28,0x30,0x20,0x30,0x28,0x24},//K
    {0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C},//L
    {0x81,0xC3,0xA5,0x99,0x81,0x81,0x81,0x81},//M
    {0x00,0x42,0x62,0x52,0x4A,0x46,0x42,0x00},//N
    {0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C},//O
    {0x3C,0x22,0x22,0x22,0x3C,0x20,0x20,0x20},//P
    {0x1C,0x22,0x22,0x22,0x22,0x26,0x22,0x1D},//Q
    {0x3C,0x22,0x22,0x22,0x3C,0x24,0x22,0x21},//R
    {0x00,0x1E,0x20,0x20,0x3E,0x02,0x02,0x3C},//S
    {0x00,0x3E,0x08,0x08,0x08,0x08,0x08,0x08},//T
    {0x42,0x42,0x42,0x42,0x42,0x42,0x22,0x1C},//U
    {0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18},//V
    {0x00,0x49,0x49,0x49,0x49,0x2A,0x1C,0x00},//W
    {0x00,0x41,0x22,0x14,0x08,0x14,0x22,0x41},//X
    {0x41,0x22,0x14,0x08,0x08,0x08,0x08,0x08},//Y
    {0x00,0x7F,0x02,0x04,0x08,0x10,0x20,0x7F},//Z
};
 
static void pabort(const char *s) {
    perror(s);
    abort();
}
 
static const char *device_spidev0_0 = "/dev/spidev0.0";
static const char *device_spidev1_0 = "/dev/spidev1.0";
static uint8_t mode;
static uint8_t bits = 8;
static uint32_t speed = 500000;
 
static void transfer(int fd, uchar address1, uchar dat1, uchar address2, uchar dat2) {
    int ret;
    uint8_t tx[] = {
        address1, dat1, address2, dat2
    };
    uint8_t rx[ARRAY_SIZE(tx)] = {0, };
 
    struct spi_ioc_transfer tr;
 
    tr.tx_buf = (unsigned long)tx;
    tr.rx_buf = (unsigned long)rx;
    tr.len = ARRAY_SIZE(tx);
    tr.speed_hz = speed;
    tr.bits_per_word = bits;
    tr.delay_usecs = 0;
    tr.cs_change = 0;
 
    ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
    if (ret < 1)
        pabort("can't send SPI message");
}
 
int main() {
    uchar i , j;
    int ret = 0;
    int fd;
 
    fd = open(device_spidev0_0, O_RDWR);
    if (fd < 0) {
        printf("can't open /dev/spidev0.0\nTry /dev/spidev1.0\n");
        fd = open(device_spidev1_0, O_RDWR);
        if (fd < 0)
            pabort("can't open /dev/spidev1.0");
    }
 
    /* 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);
 
    transfer(fd, 0x09,0x00,0x09,0x00);
    transfer(fd, 0x0a,0x03,0x0a,0x03);
    transfer(fd, 0x0b,0x07,0x0b,0x07);
    transfer(fd, 0x0c,0x01,0x0c,0x01);
    transfer(fd, 0x0f,0x00,0x0f,0x00);
 
    while (1) {
        for(j = 0; j < MAX_RAW - 1; j++) {
            for(i = 1; i < MAX_COLUMN + 1; i++)
                transfer(fd, i, disp1[j + 1][i - 1], i, disp1[j][i - 1]);
            usleep(1000000);
        }
    }
 
    close(fd);
 
    return ret;
}