2016年8月3日 星期三

BeagleBone Black啟用SPI port

安裝Adafruit BBIO python函式庫的程序


被折磨了好久,整理出來免得忘掉

以下步驟建立在BBB image版本2016-06-19 , Kernel: 4.4.12-ti-r31

刷完2016-06-19  image ,以文字編輯器開啟 /boot/uEnv.txt 檔案, 加入以下描述句
nano /boot/uEnv.txt

cape_disable=bone_capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN
cape_enable=bone_capemgr.enable_partno=BB-SPIDEV0,BB-SPIDEV1

加入描述句後儲存檔案並退出, 然後reboot 重啟BBB
重啟完成後檢查SPI port 是否成功啟用,輸入
cat /sys/devices/platform/bone_capemgr/slots
ls -al /dev/spidev*
這兩條命令, 應會看到以下結果代表成功啟用
root@beaglebone:~# cat /sys/devices/platform/bone_capemgr/slots
 0: PF----  -1
 1: PF----  -1
 2: PF----  -1
 3: PF----  -1
 4: P-O-L-   0 Override Board Name,00A0,Override Manuf,BB-SPIDEV0
 5: P-O-L-   1 Override Board Name,00A0,Override Manuf,BB-SPIDEV1
root@beaglebone:~# ls -al /dev/spidev*
crw-rw---- 1 root spi 153, 1 Aug  1 08:43 /dev/spidev1.0
crw-rw---- 1 root spi 153, 0 Aug  1 08:43 /dev/spidev1.1
crw-rw---- 1 root spi 153, 3 Aug  1 08:43 /dev/spidev2.0
crw-rw---- 1 root spi 153, 2 Aug  1 08:43 /dev/spidev2.1
root@beaglebone:~#

接著建立一隻C程式來做測式
nano spi_test.c

code內容如下:
/* 
  * 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 <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> 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 
 static void pabort(const char *s) 
 { 
      perror(s); 
      abort(); 
 } 
 static const char *device = "/dev/spidev1.0"; 
 static uint32_t mode; 
 static uint8_t bits = 8; 
 static uint32_t speed = 500000; 
 static uint16_t delay; 
 static void transfer(int fd) 
 { 
      int ret; 
      uint8_t tx[] = { 
           0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
           0x40, 0x00, 0x00, 0x00, 0x00, 0x95, 
           0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
           0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
           0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
           0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD, 
           0xF0, 0x0D, 
      }; 
      uint8_t rx[ARRAY_SIZE(tx)] = {0, }; 
      struct spi_ioc_transfer tr = { 
           .tx_buf = (unsigned long)tx, 
           .rx_buf = (unsigned long)rx, 
           .len = ARRAY_SIZE(tx), 
           .delay_usecs = delay, 
           .speed_hz = speed, 
           .bits_per_word = bits, 
      }; 
      if (mode & SPI_TX_QUAD) 
           tr.tx_nbits = 4; 
      else if (mode & SPI_TX_DUAL) 
           tr.tx_nbits = 2; 
      if (mode & SPI_RX_QUAD)  
           tr.rx_nbits = 4; 
      else if (mode & SPI_RX_DUAL) 
           tr.rx_nbits = 2; 
      if (!(mode & SPI_LOOP)) { 
           if (mode & (SPI_TX_QUAD | SPI_TX_DUAL)) 
                tr.rx_buf = 0; 
           else if (mode & (SPI_RX_QUAD | SPI_RX_DUAL)) 
                tr.tx_buf = 0; 
      } 
      ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); 
      if (ret < 1) 
           pabort("can't send spi message"); 
      for (ret = 0; ret < ARRAY_SIZE(tx); ret++) { 
           if (!(ret % 6)) 
                puts(""); 
           printf("%.2X ", rx[ret]); 
      } 
      puts(""); 
 } 
 static void print_usage(const char *prog) 
 { 
      printf("Usage: %s [-DsbdlHOLC3]\n", prog); 
      puts(" -D --device  device to use (default /dev/spidev1.1)\n" 
         " -s --speed  max speed (Hz)\n" 
         " -d --delay  delay (usec)\n" 
         " -b --bpw   bits per word \n" 
         " -l --loop   loopback\n" 
         " -H --cpha   clock phase\n" 
         " -O --cpol   clock polarity\n" 
         " -L --lsb   least significant bit first\n" 
         " -C --cs-high chip select active high\n" 
         " -3 --3wire  SI/SO signals shared\n" 
         " -N --no-cs  no chip select\n" 
         " -R --ready  slave pulls low to pause\n" 
         " -2 --dual   dual transfer\n" 
         " -4 --quad   quad transfer\n"); 
      exit(1); 
 } 
 static void parse_opts(int argc, char *argv[]) 
 { 
      while (1) { 
           static const struct option lopts[] = { 
                { "device", 1, 0, 'D' }, 
                { "speed",  1, 0, 's' }, 
                { "delay",  1, 0, 'd' }, 
                { "bpw",   1, 0, 'b' }, 
                { "loop",  0, 0, 'l' }, 
                { "cpha",  0, 0, 'H' }, 
                { "cpol",  0, 0, 'O' }, 
                { "lsb",   0, 0, 'L' }, 
                { "cs-high", 0, 0, 'C' }, 
                { "3wire",  0, 0, '3' }, 
                { "no-cs",  0, 0, 'N' }, 
                { "ready",  0, 0, 'R' }, 
                { "dual",  0, 0, '2' }, 
                { "quad",  0, 0, '4' }, 
                { NULL, 0, 0, 0 }, 
           }; 
           int c; 
           c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR24", lopts, NULL); 
           if (c == -1) 
                break; 
           switch (c) { 
           case 'D': 
                device = optarg; 
                break; 
           case 's': 
                speed = atoi(optarg); 
                break; 
           case 'd': 
                delay = atoi(optarg); 
                break; 
           case 'b': 
                bits = atoi(optarg); 
                break; 
           case 'l': 
                mode |= SPI_LOOP; 
                break; 
           case 'H': 
                mode |= SPI_CPHA; 
                break; 
           case 'O': 
                mode |= SPI_CPOL; 
                break; 
           case 'L': 
                mode |= SPI_LSB_FIRST; 
                break; 
           case 'C': 
                mode |= SPI_CS_HIGH; 
                break; 
           case '3': 
                mode |= SPI_3WIRE; 
                break; 
           case 'N': 
                mode |= SPI_NO_CS; 
                break; 
           case 'R': 
                mode |= SPI_READY; 
                break; 
           case '2': 
                mode |= SPI_TX_DUAL; 
                break; 
           case '4': 
                mode |= SPI_TX_QUAD; 
                break; 
           default: 
                print_usage(argv[0]); 
                break; 
           } 
      } 
      if (mode & SPI_LOOP) { 
           if (mode & SPI_TX_DUAL) 
                mode |= SPI_RX_DUAL; 
           if (mode & SPI_TX_QUAD) 
                mode |= SPI_RX_QUAD; 
      } 
 } 
 int main(int argc, char *argv[]) 
 { 
      int ret = 0; 
      int fd; 
      parse_opts(argc, argv); 
      fd = open(device, O_RDWR); 
      if (fd < 0) 
           pabort("can't open device"); 
      /* 
       * spi mode 
       */ 
      ret = ioctl(fd, SPI_IOC_WR_MODE32, &mode); 
      if (ret == -1) 
           pabort("can't set spi mode"); 
      ret = ioctl(fd, SPI_IOC_RD_MODE32, &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: 0x%x\n", mode); 
      printf("bits per word: %d\n", bits); 
      printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000); 
      transfer(fd); 
      close(fd); 
      return ret; 
 }

然後編譯此程式
gcc -Wall spi_test.c -o spi_test.o

連結BBB P9 插槽上 pin18 pin21, 這是SPI0 DIDO
接著執行剛才編譯好的測試程式做自我收發,應該可以看到如下結果代表SPI0通訊正常可使用
./spi_test.o 
 spi mode: 0x0 
 bits per word: 8 
 max speed: 500000 Hz (500 KHz) 
 FF FF FF FF FF FF  
 40 00 00 00 00 95  
 FF FF FF FF FF FF  
 FF FF FF FF FF FF  
 FF FF FF FF FF FF  
 DE AD BE EF BA AD  
 F0 0D  
如果把pin18 pin21 的接線斷開會看到如下結果
./spi_test.o 
 spi mode: 0x0 
 bits per word: 8 
 max speed: 500000 Hz (500 KHz) 
 FF FF FF FF FF FF  
 FF FF FF FF FF FF 
 FF FF FF FF FF FF  
 FF FF FF FF FF FF  
 FF FF FF FF FF FF  
 FF FF FF FF FF FF  
 FF FF

以上步驟完成, BBB SPI port 就可以使用了, 接著要安裝 AdaFruit BBIO 函式庫
確認有連結網路,首先進行 package update
sudo apt-get update

安裝 ntpdate
sudo apt-get install ntpdate
kkk

安裝完成, 執行ntpdate 同步時間
sudo ntpdate pool.ntp.org
kkk

再次package update, 並安裝python 相關工具
sudo apt-get update
sudo apt-get install build-essential python-dev python-setuptools python-pip python-smbus –y

完成後用PIP安裝 AdaFruit BBIO 函式庫
sudo pip install Adafruit_BBIO

完成後輸入以下命令檢查安裝正確
sudo python -c "import Adafruit_BBIO.GPIO as GPIO; print GPIO"

應會看到如下結果表示成功
#you should see this or similar:
<module 'Adafruit_BBIO.GPIO' from '/usr/local/lib/python2.7/dist-packages/Adafruit_BBIO/GPIO.so'>


以上

沒有留言:

張貼留言