Differences
This shows you the differences between two versions of the page.
— |
en:c1_hardware_spi [2015/08/05 16:51] (current) codewalker created |
||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== SPI ====== | ||
+ | {{http://dn.odroid.com/wiki_image/IMG_20150805_163924.jpg?500|}} | ||
+ | === How to use SPI === | ||
+ | <code> | ||
+ | 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 | ||
+ | </code> | ||
+ | <code> | ||
+ | root@odroid:~# modprobe spicc | ||
+ | </code> | ||
+ | |||
+ | <code> | ||
+ | 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 | ||
+ | </code> | ||
+ | |||
+ | <code> | ||
+ | root@odroid:~# ls /dev/spidev0.0 | ||
+ | /dev/spidev0.0 | ||
+ | root@odroid:~# | ||
+ | </code> | ||
+ | |||
+ | === Compile & run SPI test example source code === | ||
+ | gcc -o spidev_test spidev_test.c | ||
+ | |||
+ | <code> | ||
+ | odroid@odroid:~$ ./spidev_test | ||
+ | spi mode: 0 | ||
+ | bits per word: 8 | ||
+ | max speed: 500000 Hz (500 KHz) | ||
+ | </code> | ||
+ | <file c 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; | ||
+ | } | ||
+ | </file> |